diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/MethodHandler.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/MethodHandler.kt index 36e01b2a..93e6fc24 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/MethodHandler.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/MethodHandler.kt @@ -34,12 +34,9 @@ class MethodHandler(private val scope: CoroutineScope) : FlutterPlugin, } override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - val taskQueue = flutterPluginBinding.binaryMessenger.makeBackgroundTaskQueue() channel = MethodChannel( flutterPluginBinding.binaryMessenger, channelName, - StandardMethodCodec.INSTANCE, - taskQueue ) channel!!.setMethodCallHandler(this) } diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/PlatformSettingsHandler.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/PlatformSettingsHandler.kt index cd1722d1..a2acaef0 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/PlatformSettingsHandler.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/PlatformSettingsHandler.kt @@ -33,7 +33,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler, private lateinit var ignoreRequestResult: MethodChannel.Result companion object { - const val channelName = "com.hiddify.app/platform.settings" + const val channelName = "app.hiddify.com/platform" const val REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = 44 val gson = Gson() diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index 6aee6f0a..f36bacab 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -122,7 +122,7 @@ void initLoggers( final logToFile = debug || (!Platform.isAndroid && !Platform.isIOS); if (logToFile) { _loggers.addPrinter( - FileLogPrinter(read(filesEditorServiceProvider).appLogsPath), + FileLogPrinter(read(filesEditorServiceProvider).appLogsFile.path), ); } Loggy.initLoggy( diff --git a/lib/data/repository/core_facade_impl.dart b/lib/data/repository/core_facade_impl.dart index fa89af87..d8256dd6 100644 --- a/lib/data/repository/core_facade_impl.dart +++ b/lib/data/repository/core_facade_impl.dart @@ -34,15 +34,11 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade { return exceptionHandler( () { loggy.debug("setting up singbox"); - loggy.debug("base dir: ${filesEditor.baseDir.path}"); - loggy.debug("working dir: ${filesEditor.workingDir.path}"); - loggy.debug("temp dir: ${filesEditor.tempDir.path}"); - return singbox .setup( - filesEditor.baseDir.path, - filesEditor.workingDir.path, - filesEditor.tempDir.path, + filesEditor.dirs.baseDir.path, + filesEditor.dirs.workingDir.path, + filesEditor.dirs.tempDir.path, ) .map((r) { loggy.debug("setup complete"); @@ -180,7 +176,7 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade { @override Stream>> watchLogs() { - return singbox.watchLogs(filesEditor.coreLogsPath).handleExceptions( + return singbox.watchLogs(filesEditor.coreLogsFile.path).handleExceptions( (error, stackTrace) { loggy.warning("error watching logs", error, stackTrace); return CoreServiceFailure.unexpected(error, stackTrace); diff --git a/lib/features/logs/view/logs_page.dart b/lib/features/logs/view/logs_page.dart index 7c5d093c..3a6bee65 100644 --- a/lib/features/logs/view/logs_page.dart +++ b/lib/features/logs/view/logs_page.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fpdart/fpdart.dart'; @@ -32,7 +31,7 @@ class LogsPage extends HookConsumerWidget with PresLogger { child: Text(t.logs.shareCoreLogs), onTap: () async { await UriUtils.tryShareOrLaunchFile( - Uri.parse(filesEditor.coreLogsPath), + Uri.parse(filesEditor.coreLogsFile.path), fileOrDir: filesEditor.logsDir.uri, ); }, @@ -41,7 +40,7 @@ class LogsPage extends HookConsumerWidget with PresLogger { child: Text(t.logs.shareAppLogs), onTap: () async { await UriUtils.tryShareOrLaunchFile( - Uri.parse(filesEditor.appLogsPath), + Uri.parse(filesEditor.appLogsFile.path), fileOrDir: filesEditor.logsDir.uri, ); }, diff --git a/lib/features/settings/view/per_app_proxy_page.dart b/lib/features/settings/view/per_app_proxy_page.dart index 18fc3ef0..d885110a 100644 --- a/lib/features/settings/view/per_app_proxy_page.dart +++ b/lib/features/settings/view/per_app_proxy_page.dart @@ -5,7 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/prefs/general_prefs.dart'; import 'package:hiddify/domain/singbox/rules.dart'; -import 'package:hiddify/services/platform_settings.dart'; +import 'package:hiddify/services/platform_services.dart'; import 'package:hiddify/services/service_providers.dart'; import 'package:hiddify/utils/riverpod_utils.dart'; import 'package:hiddify/utils/utils.dart'; @@ -23,7 +23,7 @@ Future> installedPackagesInfo( InstalledPackagesInfoRef ref, ) async { return ref - .watch(platformSettingsProvider) + .watch(platformServicesProvider) .getInstalledPackages() .getOrElse((err) { _logger.error("error getting installed packages", err); @@ -38,7 +38,7 @@ Future packageIcon( ) async { ref.disposeDelay(const Duration(seconds: 10)); final bytes = await ref - .watch(platformSettingsProvider) + .watch(platformServicesProvider) .getPackageIcon(packageName) .getOrElse((err) { _logger.warning("error getting package icon", err); diff --git a/lib/features/settings/widgets/platform_settings_tiles.dart b/lib/features/settings/widgets/platform_settings_tiles.dart index 37414ca3..11f83834 100644 --- a/lib/features/settings/widgets/platform_settings_tiles.dart +++ b/lib/features/settings/widgets/platform_settings_tiles.dart @@ -13,7 +13,7 @@ Future isIgnoringBatteryOptimizations( IsIgnoringBatteryOptimizationsRef ref, ) async => ref - .watch(platformSettingsProvider) + .watch(platformServicesProvider) .isIgnoringBatteryOptimizations() .getOrElse((l) => false) .run(); @@ -35,7 +35,7 @@ class PlatformSettingsTiles extends HookConsumerWidget { enabled: enabled, onTap: () async { await ref - .read(platformSettingsProvider) + .read(platformServicesProvider) .requestIgnoreBatteryOptimizations() .run(); await Future.delayed(const Duration(seconds: 1)); diff --git a/lib/services/files_editor_service.dart b/lib/services/files_editor_service.dart index 3bba89db..f9a9d298 100644 --- a/lib/services/files_editor_service.dart +++ b/lib/services/files_editor_service.dart @@ -3,82 +3,65 @@ import 'dart:io'; import 'package:flutter/services.dart'; import 'package:hiddify/domain/constants.dart'; import 'package:hiddify/gen/assets.gen.dart'; +import 'package:hiddify/services/platform_services.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; +typedef Directories = ({ + Directory baseDir, + Directory workingDir, + Directory tempDir +}); + class FilesEditorService with InfraLogger { + FilesEditorService(this.platformServices); - late final _methodChannel = const MethodChannel("com.hiddify.app/files.method"); + final PlatformServices platformServices; - late final Directory baseDir; - late final Directory workingDir; - late final Directory tempDir; - late final Directory logsDir; - late final Directory _configsDir; + late final Directories dirs; - Future?> getPaths() async { - try { - final Map? directoryMap = await _methodChannel.invokeMethod('get_paths'); - return directoryMap?.cast(); - } on PlatformException catch (e) { - // print("Failed to get shared directory: '${e.message}'."); - return null; - } - } + Directory get workingDir => dirs.workingDir; + Directory get configsDir => + Directory(p.join(workingDir.path, Constants.configsFolderName)); + Directory get logsDir => dirs.workingDir; + + File get appLogsFile => File(p.join(logsDir.path, "app.log")); + File get coreLogsFile => File(p.join(logsDir.path, "box.log")); Future init() async { - if (Platform.isIOS) { - final paths = await getPaths(); - baseDir = Directory(paths!["base"]!); - workingDir = Directory(paths["working"]!); - tempDir = Directory(paths["temp"]!); + dirs = await platformServices.getPaths().getOrElse( + (error) { + loggy.error("error getting paths", error, StackTrace.current); + throw error; + }, + ).run(); + + loggy.info("directories: $dirs"); + + if (!await dirs.baseDir.exists()) { + await dirs.baseDir.create(recursive: true); + } + if (!await dirs.workingDir.exists()) { + await dirs.workingDir.create(recursive: true); + } + if (!await configsDir.exists()) { + await configsDir.create(recursive: true); + } + + if (await appLogsFile.exists()) { + await appLogsFile.writeAsString(""); } else { - baseDir = await getApplicationSupportDirectory(); - if (Platform.isAndroid) { - final externalDir = await getExternalStorageDirectory(); - workingDir = externalDir!; - } else if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { - workingDir = baseDir; - } else { - workingDir = await getApplicationDocumentsDirectory(); - } - tempDir = await getTemporaryDirectory(); - } - logsDir = workingDir; - - loggy.debug("base dir: ${baseDir.path}"); - loggy.debug("working dir: ${workingDir.path}"); - loggy.debug("temp dir: ${tempDir.path}"); - loggy.debug("logs dire: ${logsDir.path}"); - - _configsDir = - Directory(p.join(workingDir.path, Constants.configsFolderName)); - if (!await baseDir.exists()) { - await baseDir.create(recursive: true); - } - if (!await workingDir.exists()) { - await workingDir.create(recursive: true); - } - if (!await _configsDir.exists()) { - await _configsDir.create(recursive: true); + await appLogsFile.create(recursive: true); } - final appLogFile = File(appLogsPath); - if (await appLogFile.exists()) { - await appLogFile.writeAsString(""); + if (await coreLogsFile.exists()) { + await coreLogsFile.writeAsString(""); } else { - await appLogFile.create(recursive: true); + await coreLogsFile.create(recursive: true); } await _populateGeoAssets(); - - final coreLogFile = File(coreLogsPath); - if (await coreLogFile.exists()) { - await coreLogFile.writeAsString(""); - } else { - await coreLogFile.create(recursive: true); - } } static Future getDatabaseDirectory() async { @@ -90,11 +73,8 @@ class FilesEditorService with InfraLogger { return getApplicationDocumentsDirectory(); } - String get appLogsPath => p.join(logsDir.path, "app.log"); - String get coreLogsPath => p.join(logsDir.path, "box.log"); - String configPath(String fileName) { - return p.join(_configsDir.path, "$fileName.json"); + return p.join(configsDir.path, "$fileName.json"); } String tempConfigPath(String fileName) => configPath("temp_$fileName"); diff --git a/lib/services/platform_settings.dart b/lib/services/platform_services.dart similarity index 66% rename from lib/services/platform_settings.dart rename to lib/services/platform_services.dart index 37ee6b3f..3d62b754 100644 --- a/lib/services/platform_settings.dart +++ b/lib/services/platform_services.dart @@ -1,16 +1,48 @@ import 'dart:convert'; +import 'dart:io'; import 'package:flutter/services.dart'; import 'package:fpdart/fpdart.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hiddify/services/files_editor_service.dart'; import 'package:hiddify/utils/utils.dart'; +import 'package:path_provider/path_provider.dart'; -part 'platform_settings.freezed.dart'; -part 'platform_settings.g.dart'; +part 'platform_services.freezed.dart'; +part 'platform_services.g.dart'; -class PlatformSettings with InfraLogger { - late final MethodChannel _methodChannel = - const MethodChannel("com.hiddify.app/platform.settings"); +class PlatformServices with InfraLogger { + final _methodChannel = const MethodChannel("app.hiddify.com/platform"); + + TaskEither getPaths() { + return TaskEither( + () async { + loggy.debug("getting paths"); + final Directories dirs; + if (Platform.isIOS) { + final paths = await _methodChannel.invokeMethod("get_paths"); + loggy.debug("paths: $paths"); + dirs = ( + baseDir: Directory(paths?["base"]! as String), + workingDir: Directory(paths?["working"]! as String), + tempDir: Directory(paths?["temp"]! as String), + ); + } else { + final baseDir = await getApplicationSupportDirectory(); + final workingDir = Platform.isAndroid + ? await getExternalStorageDirectory() + : baseDir; + final tempDir = await getTemporaryDirectory(); + dirs = ( + baseDir: baseDir, + workingDir: workingDir!, + tempDir: tempDir, + ); + } + return right(dirs); + }, + ); + } TaskEither isIgnoringBatteryOptimizations() { return TaskEither( diff --git a/lib/services/service_providers.dart b/lib/services/service_providers.dart index 8b01ab9c..ae7445e0 100644 --- a/lib/services/service_providers.dart +++ b/lib/services/service_providers.dart @@ -1,7 +1,7 @@ import 'package:hiddify/data/data_providers.dart'; import 'package:hiddify/services/cron_service.dart'; import 'package:hiddify/services/files_editor_service.dart'; -import 'package:hiddify/services/platform_settings.dart'; +import 'package:hiddify/services/platform_services.dart'; import 'package:hiddify/services/singbox/singbox_service.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -9,14 +9,14 @@ part 'service_providers.g.dart'; @Riverpod(keepAlive: true) FilesEditorService filesEditorService(FilesEditorServiceRef ref) => - FilesEditorService(); + FilesEditorService(ref.watch(platformServicesProvider)); @Riverpod(keepAlive: true) SingboxService singboxService(SingboxServiceRef ref) => SingboxService(); -@riverpod -PlatformSettings platformSettings(PlatformSettingsRef ref) => - PlatformSettings(); +@Riverpod(keepAlive: true) +PlatformServices platformServices(PlatformServicesRef ref) => + PlatformServices(); @Riverpod(keepAlive: true) CronService cronService(CronServiceRef ref) {