diff --git a/lib/data/api/clash_api.dart b/lib/data/api/clash_api.dart deleted file mode 100644 index c73397c9..00000000 --- a/lib/data/api/clash_api.dart +++ /dev/null @@ -1,145 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:dio/dio.dart'; -import 'package:fpdart/fpdart.dart'; -import 'package:hiddify/domain/clash/clash.dart'; -import 'package:hiddify/domain/constants.dart'; -import 'package:hiddify/utils/utils.dart'; -import 'package:web_socket_channel/web_socket_channel.dart'; - -class ClashApi with InfraLogger { - ClashApi(int port) : address = "${Constants.localHost}:$port"; - - final String address; - - late final _clashDio = Dio( - BaseOptions( - baseUrl: "http://$address", - connectTimeout: const Duration(seconds: 3), - receiveTimeout: const Duration(seconds: 10), - sendTimeout: const Duration(seconds: 3), - ), - ); - - TaskEither> getProxies() { - return TaskEither( - () async { - final response = await _clashDio.get("/proxies"); - if (response.statusCode != 200 || response.data == null) { - return left(response.statusMessage ?? ""); - } - final proxies = ((jsonDecode(response.data! as String) - as Map)["proxies"] as Map) - .entries - .map( - (e) { - final proxyMap = (e.value as Map) - ..putIfAbsent('name', () => e.key); - return ClashProxy.fromJson(proxyMap); - }, - ); - return right(proxies.toList()); - }, - ); - } - - TaskEither changeProxy(String selectorName, String proxyName) { - return TaskEither( - () async { - final response = await _clashDio.put( - "/proxies/$selectorName", - data: {"name": proxyName}, - ); - if (response.statusCode != HttpStatus.noContent) { - return left(response.statusMessage ?? ""); - } - return right(unit); - }, - ); - } - - TaskEither getProxyDelay( - String name, - String url, { - Duration timeout = const Duration(seconds: 10), - }) { - return TaskEither( - () async { - final response = await _clashDio.get( - "/proxies/$name/delay", - queryParameters: { - "timeout": timeout.inMilliseconds, - "url": url, - }, - ); - if (response.statusCode != 200 || response.data == null) { - return left(response.statusMessage ?? ""); - } - return right(response.data!["delay"] as int); - }, - ); - } - - TaskEither getConfigs() { - return TaskEither( - () async { - final response = await _clashDio.get("/configs"); - if (response.statusCode != 200 || response.data == null) { - return left(response.statusMessage ?? ""); - } - final config = - ClashConfig.fromJson(response.data as Map); - return right(config); - }, - ); - } - - TaskEither updateConfigs(String path) { - return TaskEither.of(unit); - } - - TaskEither patchConfigs(ClashConfig config) { - return TaskEither( - () async { - final response = await _clashDio.patch( - "/configs", - data: config.toJson(), - ); - if (response.statusCode != HttpStatus.noContent) { - return left(response.statusMessage ?? ""); - } - return right(unit); - }, - ); - } - - Stream watchLogs(LogLevel level) { - return const Stream.empty(); - } - - Stream watchTraffic() { - final channel = WebSocketChannel.connect( - Uri.parse("ws://$address/traffic"), - ); - return channel.stream.map( - (event) { - return ClashTraffic.fromJson( - jsonDecode(event as String) as Map, - ); - }, - ); - } - - TaskEither getTraffic() { - return TaskEither( - () async { - final response = await _clashDio.get>("/traffic"); - if (response.statusCode != 200 || response.data == null) { - return left(response.statusMessage ?? ""); - } - return right(ClashTraffic.fromJson(response.data!)); - }, - ); - } -} diff --git a/lib/data/data_providers.dart b/lib/data/data_providers.dart index d70bef5b..0f1b653c 100644 --- a/lib/data/data_providers.dart +++ b/lib/data/data_providers.dart @@ -3,13 +3,11 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/prefs/general_prefs.dart'; -import 'package:hiddify/data/api/clash_api.dart'; import 'package:hiddify/data/local/database.dart'; import 'package:hiddify/data/repository/app_repository_impl.dart'; import 'package:hiddify/data/repository/config_options_store.dart'; import 'package:hiddify/data/repository/repository.dart'; import 'package:hiddify/domain/app/app.dart'; -import 'package:hiddify/domain/constants.dart'; import 'package:hiddify/domain/core_facade.dart'; import 'package:hiddify/domain/singbox/singbox.dart'; import 'package:hiddify/features/geo_asset/data/geo_asset_data_providers.dart'; @@ -51,9 +49,6 @@ Dio dio(DioRef ref) { AppRepository appRepository(AppRepositoryRef ref) => AppRepositoryImpl(ref.watch(dioProvider)); -@Riverpod(keepAlive: true) -ClashApi clashApi(ClashApiRef ref) => ClashApi(Defaults.clashApiPort); - @riverpod Future configOptions(ConfigOptionsRef ref) async { final geoAssets = await ref @@ -86,7 +81,6 @@ CoreFacade coreFacade(CoreFacadeRef ref) => CoreFacadeImpl( ref.watch(geoAssetPathResolverProvider), ref.watch(profilePathResolverProvider), ref.watch(platformServicesProvider), - ref.watch(clashApiProvider), ref.read(debugModeNotifierProvider), () => ref.read(configOptionsProvider.future), ); diff --git a/lib/data/repository/core_facade_impl.dart b/lib/data/repository/core_facade_impl.dart index be953ec1..375a1e8b 100644 --- a/lib/data/repository/core_facade_impl.dart +++ b/lib/data/repository/core_facade_impl.dart @@ -2,11 +2,8 @@ import 'dart:convert'; import 'dart:io'; import 'package:fpdart/fpdart.dart'; -import 'package:hiddify/data/api/clash_api.dart'; import 'package:hiddify/data/repository/exception_handlers.dart'; -import 'package:hiddify/domain/clash/clash.dart'; import 'package:hiddify/domain/connectivity/connection_status.dart'; -import 'package:hiddify/domain/constants.dart'; import 'package:hiddify/domain/core_facade.dart'; import 'package:hiddify/domain/core_service_failure.dart'; import 'package:hiddify/domain/singbox/singbox.dart'; @@ -24,7 +21,6 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade { this.geoAssetPathResolver, this.profilePathResolver, this.platformServices, - this.clash, this.debug, this.configOptions, ); @@ -34,7 +30,6 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade { final GeoAssetPathResolver geoAssetPathResolver; final ProfilePathResolver profilePathResolver; final PlatformServices platformServices; - final ClashApi clash; final bool debug; final Future Function() configOptions; @@ -263,67 +258,6 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade { ); } - @override - TaskEither getConfigs() { - return exceptionHandler( - () async => clash.getConfigs().mapLeft(CoreServiceFailure.other).run(), - CoreServiceFailure.unexpected, - ); - } - - @override - TaskEither patchOverrides(ClashConfig overrides) { - return exceptionHandler( - () async => - clash.patchConfigs(overrides).mapLeft(CoreServiceFailure.other).run(), - CoreServiceFailure.unexpected, - ); - } - - @override - TaskEither> getProxies() { - return exceptionHandler( - () async => clash.getProxies().mapLeft(CoreServiceFailure.other).run(), - CoreServiceFailure.unexpected, - ); - } - - @override - TaskEither changeProxy( - String selectorName, - String proxyName, - ) { - return exceptionHandler( - () async => clash - .changeProxy(selectorName, proxyName) - .mapLeft(CoreServiceFailure.other) - .run(), - CoreServiceFailure.unexpected, - ); - } - - @override - Stream> watchTraffic() { - return clash.watchTraffic().handleExceptions(CoreServiceFailure.unexpected); - } - - @override - TaskEither testDelay( - String proxyName, { - String testUrl = Defaults.connectionTestUrl, - }) { - return exceptionHandler( - () async { - final result = clash - .getProxyDelay(proxyName, testUrl) - .mapLeft(CoreServiceFailure.other) - .run(); - return result; - }, - CoreServiceFailure.unexpected, - ); - } - @override Stream watchConnectionStatus() => singbox.watchConnectionStatus(); diff --git a/lib/domain/clash/clash.dart b/lib/domain/clash/clash.dart deleted file mode 100644 index 4db9fff2..00000000 --- a/lib/domain/clash/clash.dart +++ /dev/null @@ -1,6 +0,0 @@ -export 'clash_config.dart'; -export 'clash_enums.dart'; -export 'clash_facade.dart'; -export 'clash_log.dart'; -export 'clash_proxy.dart'; -export 'clash_traffic.dart'; diff --git a/lib/domain/clash/clash_config.dart b/lib/domain/clash/clash_config.dart deleted file mode 100644 index 5e515ea4..00000000 --- a/lib/domain/clash/clash_config.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:fpdart/fpdart.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:hiddify/domain/clash/clash_enums.dart'; - -part 'clash_config.freezed.dart'; -part 'clash_config.g.dart'; - -@freezed -class ClashConfig with _$ClashConfig { - const ClashConfig._(); - - @JsonSerializable(includeIfNull: false, fieldRename: FieldRename.kebab) - const factory ClashConfig({ - @JsonKey(name: 'port') int? httpPort, - int? socksPort, - int? redirPort, - int? tproxyPort, - int? mixedPort, - List? authentication, - bool? allowLan, - String? bindAddress, - TunnelMode? mode, - LogLevel? logLevel, - bool? ipv6, - }) = _ClashConfig; - - ClashConfig patch(ClashConfigPatch patch) { - return copyWith( - httpPort: (patch.httpPort ?? optionOf(httpPort)).toNullable(), - socksPort: (patch.socksPort ?? optionOf(socksPort)).toNullable(), - redirPort: (patch.redirPort ?? optionOf(redirPort)).toNullable(), - tproxyPort: (patch.tproxyPort ?? optionOf(tproxyPort)).toNullable(), - mixedPort: (patch.mixedPort ?? optionOf(mixedPort)).toNullable(), - authentication: - (patch.authentication ?? optionOf(authentication)).toNullable(), - allowLan: (patch.allowLan ?? optionOf(allowLan)).toNullable(), - bindAddress: (patch.bindAddress ?? optionOf(bindAddress)).toNullable(), - mode: (patch.mode ?? optionOf(mode)).toNullable(), - logLevel: (patch.logLevel ?? optionOf(logLevel)).toNullable(), - ipv6: (patch.ipv6 ?? optionOf(ipv6)).toNullable(), - ); - } - - factory ClashConfig.fromJson(Map json) => - _$ClashConfigFromJson(json); -} - -@freezed -class ClashConfigPatch with _$ClashConfigPatch { - const ClashConfigPatch._(); - - @JsonSerializable(includeIfNull: false) - const factory ClashConfigPatch({ - Option? httpPort, - Option? socksPort, - Option? redirPort, - Option? tproxyPort, - Option? mixedPort, - Option>? authentication, - Option? allowLan, - Option? bindAddress, - Option? mode, - Option? logLevel, - Option? ipv6, - }) = _ClashConfigPatch; -} diff --git a/lib/domain/clash/clash_enums.dart b/lib/domain/clash/clash_enums.dart deleted file mode 100644 index f8ad5af3..00000000 --- a/lib/domain/clash/clash_enums.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'package:flutter/material.dart'; - -enum TunnelMode { - rule, - global, - direct; -} - -enum LogLevel { - info, - warning, - error, - debug, - silent; - - Color get color => switch (this) { - info => Colors.lightGreen, - warning => Colors.orangeAccent, - error => Colors.redAccent, - debug => Colors.lightBlue, - _ => Colors.white, - }; -} - -enum ProxyType { - direct("Direct"), - reject("Reject"), - compatible("Compatible"), - pass("Pass"), - shadowSocks("ShadowSocks"), - shadowSocksR("ShadowSocksR"), - snell("Snell"), - socks5("Socks5"), - http("Http"), - vmess("Vmess"), - vless("Vless"), - trojan("Trojan"), - hysteria("Hysteria"), - wireGuard("WireGuard"), - tuic("Tuic"), - ssh("SSH"), - relay("Relay"), - selector("Selector"), - fallback("Fallback"), - urlTest("URLTest", "urltest"), - loadBalance("LoadBalance"), - unknown("Unknown"); - - const ProxyType(this.label, [this._key]); - - final String? _key; - final String label; - - String get key => _key ?? name; - - static List groupValues = [ - selector, - fallback, - urlTest, - loadBalance, - ]; -} diff --git a/lib/domain/clash/clash_facade.dart b/lib/domain/clash/clash_facade.dart deleted file mode 100644 index 2a2443ee..00000000 --- a/lib/domain/clash/clash_facade.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:fpdart/fpdart.dart'; -import 'package:hiddify/domain/clash/clash.dart'; -import 'package:hiddify/domain/constants.dart'; -import 'package:hiddify/domain/core_service_failure.dart'; - -abstract class ClashFacade { - TaskEither getConfigs(); - - TaskEither patchOverrides(ClashConfig overrides); - - TaskEither> getProxies(); - - TaskEither changeProxy( - String selectorName, - String proxyName, - ); - - TaskEither testDelay( - String proxyName, { - String testUrl = Defaults.connectionTestUrl, - }); - - Stream> watchTraffic(); -} diff --git a/lib/domain/clash/clash_log.dart b/lib/domain/clash/clash_log.dart deleted file mode 100644 index c016e6ba..00000000 --- a/lib/domain/clash/clash_log.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:hiddify/domain/clash/clash_enums.dart'; - -part 'clash_log.freezed.dart'; -part 'clash_log.g.dart'; - -@freezed -class ClashLog with _$ClashLog { - const ClashLog._(); - - const factory ClashLog({ - @JsonKey(name: 'type') required LogLevel level, - @JsonKey(name: 'payload') required String message, - @JsonKey(defaultValue: DateTime.now) required DateTime time, - }) = _ClashLog; - - String get timeStamp => - "${time.month}-${time.day} ${time.hour}:${time.minute}:${time.second}"; - - factory ClashLog.fromJson(Map json) => - _$ClashLogFromJson(json); -} diff --git a/lib/domain/clash/clash_proxy.dart b/lib/domain/clash/clash_proxy.dart deleted file mode 100644 index 28e5b9ad..00000000 --- a/lib/domain/clash/clash_proxy.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:dartx/dartx.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:hiddify/domain/clash/clash_enums.dart'; - -part 'clash_proxy.freezed.dart'; -part 'clash_proxy.g.dart'; - -// TODO: test and improve -@Freezed(fromJson: true) -sealed class ClashProxy with _$ClashProxy { - const ClashProxy._(); - - const factory ClashProxy.group({ - required String name, - @JsonKey(fromJson: _typeFromJson) required ProxyType type, - required List all, - required String now, - @Default(false) bool udp, - List? history, - @JsonKey(includeFromJson: false, includeToJson: false) int? delay, - }) = ClashProxyGroup; - - const factory ClashProxy.item({ - required String name, - @JsonKey(fromJson: _typeFromJson) required ProxyType type, - @Default(false) bool udp, - List? history, - @JsonKey(includeFromJson: false, includeToJson: false) int? delay, - }) = ClashProxyItem; - - factory ClashProxy.fromJson(Map json) { - final isGroup = json.containsKey('all') || - json.containsKey('now') || - ProxyType.groupValues.any( - (e) => e.label == json.getOrElse('type', () => null), - ); - if (isGroup) { - return ClashProxyGroup.fromJson(json); - } else { - return ClashProxyItem.fromJson(json); - } - } -} - -ProxyType _typeFromJson(dynamic type) => - ProxyType.values - .firstOrNullWhere((e) => e.key == (type as String?)?.toLowerCase()) ?? - ProxyType.unknown; - -@freezed -class ClashHistory with _$ClashHistory { - const ClashHistory._(); - - const factory ClashHistory({ - required String time, - required int delay, - }) = _ClashHistory; - - factory ClashHistory.fromJson(Map json) => - _$ClashHistoryFromJson(json); -} diff --git a/lib/domain/clash/clash_traffic.dart b/lib/domain/clash/clash_traffic.dart deleted file mode 100644 index 8602bc26..00000000 --- a/lib/domain/clash/clash_traffic.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'clash_traffic.freezed.dart'; -part 'clash_traffic.g.dart'; - -@freezed -class ClashTraffic with _$ClashTraffic { - const ClashTraffic._(); - - const factory ClashTraffic({ - @JsonKey(name: 'up') required int upload, - @JsonKey(name: 'down') required int download, - }) = _ClashTraffic; - - factory ClashTraffic.fromJson(Map json) => - _$ClashTrafficFromJson(json); -} diff --git a/lib/domain/core_facade.dart b/lib/domain/core_facade.dart index a3ada4aa..15d0ba48 100644 --- a/lib/domain/core_facade.dart +++ b/lib/domain/core_facade.dart @@ -1,4 +1,3 @@ -import 'package:hiddify/domain/clash/clash.dart'; import 'package:hiddify/domain/singbox/singbox.dart'; -abstract interface class CoreFacade implements SingboxFacade, ClashFacade {} +abstract interface class CoreFacade implements SingboxFacade {}