Change mapping

This commit is contained in:
problematicconsumer
2024-02-17 11:58:34 +03:30
parent 0aeb0e346f
commit 3541f8e3db
9 changed files with 269 additions and 364 deletions

View File

@@ -34,7 +34,7 @@ class ConfigOptionRepositoryImpl
@override
Either<ConfigOptionFailure, ConfigOptionEntity> getConfigOption() {
try {
final map = ConfigOptionEntity.initial().toMap();
final map = ConfigOptionEntity.initial().toJson();
for (final key in map.keys) {
final persisted = preferences.get(key);
if (persisted != null) {
@@ -49,7 +49,7 @@ class ConfigOptionRepositoryImpl
map[key] = persisted;
}
}
final options = ConfigOptionEntityMapper.fromMap(map);
final options = ConfigOptionEntity.fromJson(map);
return right(options);
} catch (error, stackTrace) {
return left(ConfigOptionUnexpectedFailure(error, stackTrace));
@@ -62,7 +62,7 @@ class ConfigOptionRepositoryImpl
) {
return exceptionHandler(
() async {
final map = patch.toMap();
final map = patch.toJson();
await updateByJson(map);
return right(unit);
},
@@ -74,7 +74,7 @@ class ConfigOptionRepositoryImpl
TaskEither<ConfigOptionFailure, Unit> resetConfigOption() {
return exceptionHandler(
() async {
final map = ConfigOptionEntity.initial().toMap();
final map = ConfigOptionEntity.initial().toJson();
await updateByJson(map);
return right(unit);
},
@@ -86,7 +86,7 @@ class ConfigOptionRepositoryImpl
Future<void> updateByJson(
Map<String, dynamic> options,
) async {
final map = ConfigOptionEntity.initial().toMap();
final map = ConfigOptionEntity.initial().toJson();
for (final key in map.keys) {
final value = options[key];
if (value != null) {

View File

@@ -1,6 +1,6 @@
import 'dart:convert';
import 'package:dart_mappable/dart_mappable.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hiddify/core/model/optional_range.dart';
import 'package:hiddify/core/utils/json_converters.dart';
import 'package:hiddify/features/log/model/log_level.dart';
@@ -9,99 +9,68 @@ import 'package:hiddify/singbox/model/singbox_config_option.dart';
import 'package:hiddify/singbox/model/singbox_rule.dart';
import 'package:hiddify/utils/platform_utils.dart';
part 'config_option_entity.mapper.dart';
part 'config_option_entity.freezed.dart';
part 'config_option_entity.g.dart';
@MappableClass(
caseStyle: CaseStyle.paramCase,
includeCustomMappers: [
OptionalRangeJsonMapper(),
IntervalInSecondsMapper(),
],
)
class ConfigOptionEntity with ConfigOptionEntityMappable {
const ConfigOptionEntity({
required this.serviceMode,
this.logLevel = LogLevel.warn,
this.resolveDestination = false,
this.ipv6Mode = IPv6Mode.disable,
this.remoteDnsAddress = "udp://1.1.1.1",
this.remoteDnsDomainStrategy = DomainStrategy.auto,
this.directDnsAddress = "1.1.1.1",
this.directDnsDomainStrategy = DomainStrategy.auto,
this.mixedPort = 2334,
this.localDnsPort = 6450,
this.tunImplementation = TunImplementation.mixed,
this.mtu = 9000,
this.strictRoute = true,
this.connectionTestUrl = "http://cp.cloudflare.com/",
this.urlTestInterval = const Duration(minutes: 10),
this.enableClashApi = true,
this.clashApiPort = 6756,
this.bypassLan = false,
this.allowConnectionFromLan = false,
this.enableFakeDns = false,
this.enableDnsRouting = true,
this.independentDnsCache = true,
this.enableTlsFragment = false,
this.tlsFragmentSize = const OptionalRange(min: 1, max: 500),
this.tlsFragmentSleep = const OptionalRange(min: 0, max: 500),
this.enableTlsMixedSniCase = false,
this.enableTlsPadding = false,
this.tlsPaddingSize = const OptionalRange(min: 1, max: 1500),
this.enableMux = false,
this.muxPadding = false,
this.muxMaxStreams = 8,
this.muxProtocol = MuxProtocol.h2mux,
this.enableWarp = false,
this.warpDetourMode = WarpDetourMode.outbound,
this.warpLicenseKey = "",
this.warpCleanIp = "auto",
this.warpPort = 0,
this.warpNoise = const OptionalRange(),
});
@freezed
class ConfigOptionEntity with _$ConfigOptionEntity {
const ConfigOptionEntity._();
final ServiceMode serviceMode;
final LogLevel logLevel;
final bool resolveDestination;
@MappableField(key: "ipv6-mode")
final IPv6Mode ipv6Mode;
final String remoteDnsAddress;
final DomainStrategy remoteDnsDomainStrategy;
final String directDnsAddress;
final DomainStrategy directDnsDomainStrategy;
final int mixedPort;
final int localDnsPort;
final TunImplementation tunImplementation;
final int mtu;
final bool strictRoute;
final String connectionTestUrl;
final Duration urlTestInterval;
final bool enableClashApi;
final int clashApiPort;
final bool bypassLan;
final bool allowConnectionFromLan;
final bool enableFakeDns;
final bool enableDnsRouting;
final bool independentDnsCache;
final bool enableTlsFragment;
final OptionalRange tlsFragmentSize;
final OptionalRange tlsFragmentSleep;
final bool enableTlsMixedSniCase;
final bool enableTlsPadding;
final OptionalRange tlsPaddingSize;
final bool enableMux;
final bool muxPadding;
final int muxMaxStreams;
final MuxProtocol muxProtocol;
final bool enableWarp;
final WarpDetourMode warpDetourMode;
final String warpLicenseKey;
final String warpCleanIp;
final int warpPort;
final OptionalRange warpNoise;
@JsonSerializable(fieldRename: FieldRename.kebab)
const factory ConfigOptionEntity({
required ServiceMode serviceMode,
@Default(LogLevel.warn) LogLevel logLevel,
@Default(false) bool resolveDestination,
@Default(IPv6Mode.disable) IPv6Mode ipv6Mode,
@Default("udp://1.1.1.1") String remoteDnsAddress,
@Default(DomainStrategy.auto) DomainStrategy remoteDnsDomainStrategy,
@Default("1.1.1.1") String directDnsAddress,
@Default(DomainStrategy.auto) DomainStrategy directDnsDomainStrategy,
@Default(2334) int mixedPort,
@Default(6450) int localDnsPort,
@Default(TunImplementation.mixed) TunImplementation tunImplementation,
@Default(9000) int mtu,
@Default(true) bool strictRoute,
@Default("http://cp.cloudflare.com/") String connectionTestUrl,
@IntervalInSecondsConverter()
@Default(Duration(minutes: 10))
Duration urlTestInterval,
@Default(true) bool enableClashApi,
@Default(6756) int clashApiPort,
@Default(false) bool bypassLan,
@Default(false) bool allowConnectionFromLan,
@Default(false) bool enableFakeDns,
@Default(true) bool enableDnsRouting,
@Default(true) bool independentDnsCache,
@Default(false) bool enableTlsFragment,
@OptionalRangeJsonConverter()
@Default(OptionalRange(min: 1, max: 500))
OptionalRange tlsFragmentSize,
@OptionalRangeJsonConverter()
@Default(OptionalRange(min: 0, max: 500))
OptionalRange tlsFragmentSleep,
@Default(false) bool enableTlsMixedSniCase,
@Default(false) bool enableTlsPadding,
@OptionalRangeJsonConverter()
@Default(OptionalRange(min: 1, max: 1500))
OptionalRange tlsPaddingSize,
@Default(false) bool enableMux,
@Default(false) bool muxPadding,
@Default(8) int muxMaxStreams,
@Default(MuxProtocol.h2mux) MuxProtocol muxProtocol,
@Default(false) bool enableWarp,
@Default(WarpDetourMode.outbound) WarpDetourMode warpDetourMode,
@Default("") String warpLicenseKey,
@Default("auto") String warpCleanIp,
@Default(0) int warpPort,
@OptionalRangeJsonConverter()
@Default(OptionalRange())
OptionalRange warpNoise,
}) = _ConfigOptionEntity;
factory ConfigOptionEntity.initial() =>
ConfigOptionEntity(serviceMode: ServiceMode.defaultMode);
factory ConfigOptionEntity.initial() => ConfigOptionEntity(
serviceMode: ServiceMode.defaultMode,
);
bool hasExperimentalOptions() {
if (PlatformUtils.isDesktop && serviceMode == ServiceMode.tun) {
@@ -120,11 +89,54 @@ class ConfigOptionEntity with ConfigOptionEntityMappable {
String format() {
const encoder = JsonEncoder.withIndent(' ');
return encoder.convert(toMap());
return encoder.convert(toJson());
}
ConfigOptionEntity patch(ConfigOptionPatch patch) {
return copyWith.$delta(patch.delta());
return copyWith(
serviceMode: patch.serviceMode ?? serviceMode,
logLevel: patch.logLevel ?? logLevel,
resolveDestination: patch.resolveDestination ?? resolveDestination,
ipv6Mode: patch.ipv6Mode ?? ipv6Mode,
remoteDnsAddress: patch.remoteDnsAddress ?? remoteDnsAddress,
remoteDnsDomainStrategy:
patch.remoteDnsDomainStrategy ?? remoteDnsDomainStrategy,
directDnsAddress: patch.directDnsAddress ?? directDnsAddress,
directDnsDomainStrategy:
patch.directDnsDomainStrategy ?? directDnsDomainStrategy,
mixedPort: patch.mixedPort ?? mixedPort,
localDnsPort: patch.localDnsPort ?? localDnsPort,
tunImplementation: patch.tunImplementation ?? tunImplementation,
mtu: patch.mtu ?? mtu,
strictRoute: patch.strictRoute ?? strictRoute,
connectionTestUrl: patch.connectionTestUrl ?? connectionTestUrl,
urlTestInterval: patch.urlTestInterval ?? urlTestInterval,
enableClashApi: patch.enableClashApi ?? enableClashApi,
clashApiPort: patch.clashApiPort ?? clashApiPort,
bypassLan: patch.bypassLan ?? bypassLan,
allowConnectionFromLan:
patch.allowConnectionFromLan ?? allowConnectionFromLan,
enableFakeDns: patch.enableFakeDns ?? enableFakeDns,
enableDnsRouting: patch.enableDnsRouting ?? enableDnsRouting,
independentDnsCache: patch.independentDnsCache ?? independentDnsCache,
enableTlsFragment: patch.enableTlsFragment ?? enableTlsFragment,
tlsFragmentSize: patch.tlsFragmentSize ?? tlsFragmentSize,
tlsFragmentSleep: patch.tlsFragmentSleep ?? tlsFragmentSleep,
enableTlsMixedSniCase:
patch.enableTlsMixedSniCase ?? enableTlsMixedSniCase,
enableTlsPadding: patch.enableTlsPadding ?? enableTlsPadding,
tlsPaddingSize: patch.tlsPaddingSize ?? tlsPaddingSize,
enableMux: patch.enableMux ?? enableMux,
muxPadding: patch.muxPadding ?? muxPadding,
muxMaxStreams: patch.muxMaxStreams ?? muxMaxStreams,
muxProtocol: patch.muxProtocol ?? muxProtocol,
enableWarp: patch.enableWarp ?? enableWarp,
warpDetourMode: patch.warpDetourMode ?? warpDetourMode,
warpLicenseKey: patch.warpLicenseKey ?? warpLicenseKey,
warpCleanIp: patch.warpCleanIp ?? warpCleanIp,
warpPort: patch.warpPort ?? warpPort,
warpNoise: patch.warpNoise ?? warpNoise,
);
}
SingboxConfigOption toSingbox({
@@ -179,98 +191,57 @@ class ConfigOptionEntity with ConfigOptionEntityMappable {
rules: rules,
);
}
factory ConfigOptionEntity.fromJson(Map<String, dynamic> json) =>
_$ConfigOptionEntityFromJson(json);
}
@MappableClass(
caseStyle: CaseStyle.paramCase,
ignoreNull: true,
includeCustomMappers: [
OptionalRangeJsonMapper(),
IntervalInSecondsMapper(),
],
)
class ConfigOptionPatch with ConfigOptionPatchMappable {
const ConfigOptionPatch({
this.serviceMode,
this.logLevel,
this.resolveDestination,
this.ipv6Mode,
this.remoteDnsAddress,
this.remoteDnsDomainStrategy,
this.directDnsAddress,
this.directDnsDomainStrategy,
this.mixedPort,
this.localDnsPort,
this.tunImplementation,
this.mtu,
this.strictRoute,
this.connectionTestUrl,
this.urlTestInterval,
this.enableClashApi,
this.clashApiPort,
this.bypassLan,
this.allowConnectionFromLan,
this.enableFakeDns,
this.enableDnsRouting,
this.independentDnsCache,
this.enableTlsFragment,
this.tlsFragmentSize,
this.tlsFragmentSleep,
this.enableTlsMixedSniCase,
this.enableTlsPadding,
this.tlsPaddingSize,
this.enableMux,
this.muxPadding,
this.muxMaxStreams,
this.muxProtocol,
this.enableWarp,
this.warpDetourMode,
this.warpLicenseKey,
this.warpCleanIp,
this.warpPort,
this.warpNoise,
});
@freezed
class ConfigOptionPatch with _$ConfigOptionPatch {
const ConfigOptionPatch._();
final ServiceMode? serviceMode;
final LogLevel? logLevel;
final bool? resolveDestination;
@MappableField(key: "ipv6-mode")
final IPv6Mode? ipv6Mode;
final String? remoteDnsAddress;
final DomainStrategy? remoteDnsDomainStrategy;
final String? directDnsAddress;
final DomainStrategy? directDnsDomainStrategy;
final int? mixedPort;
final int? localDnsPort;
final TunImplementation? tunImplementation;
final int? mtu;
final bool? strictRoute;
final String? connectionTestUrl;
final Duration? urlTestInterval;
final bool? enableClashApi;
final int? clashApiPort;
final bool? bypassLan;
final bool? allowConnectionFromLan;
final bool? enableFakeDns;
final bool? enableDnsRouting;
final bool? independentDnsCache;
final bool? enableTlsFragment;
final OptionalRange? tlsFragmentSize;
final OptionalRange? tlsFragmentSleep;
final bool? enableTlsMixedSniCase;
final bool? enableTlsPadding;
final OptionalRange? tlsPaddingSize;
final bool? enableMux;
final bool? muxPadding;
final int? muxMaxStreams;
final MuxProtocol? muxProtocol;
final bool? enableWarp;
final WarpDetourMode? warpDetourMode;
final String? warpLicenseKey;
final String? warpCleanIp;
final int? warpPort;
final OptionalRange? warpNoise;
@JsonSerializable(fieldRename: FieldRename.kebab)
const factory ConfigOptionPatch({
ServiceMode? serviceMode,
LogLevel? logLevel,
bool? resolveDestination,
IPv6Mode? ipv6Mode,
String? remoteDnsAddress,
DomainStrategy? remoteDnsDomainStrategy,
String? directDnsAddress,
DomainStrategy? directDnsDomainStrategy,
int? mixedPort,
int? localDnsPort,
TunImplementation? tunImplementation,
int? mtu,
bool? strictRoute,
String? connectionTestUrl,
@IntervalInSecondsConverter() Duration? urlTestInterval,
bool? enableClashApi,
int? clashApiPort,
bool? bypassLan,
bool? allowConnectionFromLan,
bool? enableFakeDns,
bool? enableDnsRouting,
bool? independentDnsCache,
bool? enableTlsFragment,
@OptionalRangeJsonConverter() OptionalRange? tlsFragmentSize,
@OptionalRangeJsonConverter() OptionalRange? tlsFragmentSleep,
bool? enableTlsMixedSniCase,
bool? enableTlsPadding,
@OptionalRangeJsonConverter() OptionalRange? tlsPaddingSize,
bool? enableMux,
bool? muxPadding,
int? muxMaxStreams,
MuxProtocol? muxProtocol,
bool? enableWarp,
WarpDetourMode? warpDetourMode,
String? warpLicenseKey,
String? warpCleanIp,
int? warpPort,
@OptionalRangeJsonConverter() OptionalRange? warpNoise,
}) = _ConfigOptionPatch;
Map<String, dynamic> delta() =>
toMap()..removeWhere((key, value) => value == null);
factory ConfigOptionPatch.fromJson(Map<String, dynamic> json) =>
_$ConfigOptionPatchFromJson(json);
}