diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index 30e1bd4a..7cd4a9f9 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -147,7 +147,6 @@ Future initAppServices( await Future.wait( [ read(singboxServiceProvider).init(), - read(cronServiceProvider).startScheduler(), ], ); _logger.debug('initialized app services'); diff --git a/lib/core/app/app_view.dart b/lib/core/app/app_view.dart index 8a9440c9..69549dc6 100644 --- a/lib/core/app/app_view.dart +++ b/lib/core/app/app_view.dart @@ -37,6 +37,17 @@ class AppView extends HookConsumerWidget with PresLogger { theme: theme.light(), darkTheme: theme.dark(), title: Constants.appName, + + // https://github.com/ponnamkarthik/FlutterToast/issues/393 + builder: (context, child) => Overlay( + initialEntries: [ + if (child != null) ...[ + OverlayEntry( + builder: (context) => child, + ), + ], + ], + ), ); } } diff --git a/lib/features/common/app_update_notifier.dart b/lib/features/common/app_update_notifier.dart index 7b0864b9..6742ac2f 100644 --- a/lib/features/common/app_update_notifier.dart +++ b/lib/features/common/app_update_notifier.dart @@ -66,11 +66,11 @@ class AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger { ).run(); } - void _schedule() { + Future _schedule() async { loggy.debug("scheduling app update checker"); - ref.watch(cronServiceProvider).schedule( + return ref.read(cronServiceProvider).schedule( key: 'app_update', - duration: const Duration(hours: 4), + duration: const Duration(hours: 8), callback: () async { await Future.delayed(const Duration(seconds: 5)); final updateState = await check(); diff --git a/lib/features/common/common_controllers.dart b/lib/features/common/common_controllers.dart index d94102b3..8cfbb413 100644 --- a/lib/features/common/common_controllers.dart +++ b/lib/features/common/common_controllers.dart @@ -1,8 +1,11 @@ +import 'package:hiddify/core/prefs/general_prefs.dart'; import 'package:hiddify/features/common/app_update_notifier.dart'; import 'package:hiddify/features/common/connectivity/connectivity_controller.dart'; import 'package:hiddify/features/common/window/window_controller.dart'; import 'package:hiddify/features/logs/notifier/notifier.dart'; +import 'package:hiddify/features/profiles/notifier/notifier.dart'; import 'package:hiddify/features/system_tray/controller/system_tray_controller.dart'; +import 'package:hiddify/services/service_providers.dart'; import 'package:hiddify/utils/platform_utils.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -12,6 +15,15 @@ part 'common_controllers.g.dart'; // https://github.com/rrousselGit/riverpod/discussions/2730 @Riverpod(keepAlive: true) void commonControllers(CommonControllersRef ref) { + ref.listen( + introCompletedProvider, + (_, completed) async { + if (completed) { + await ref.read(cronServiceProvider).startScheduler(); + } + }, + fireImmediately: true, + ); ref.listen( logsNotifierProvider, (previous, next) {}, @@ -26,6 +38,11 @@ void commonControllers(CommonControllersRef ref) { (previous, next) {}, fireImmediately: true, ); + ref.listen( + profilesUpdateNotifierProvider, + (previous, next) {}, + fireImmediately: true, + ); if (PlatformUtils.isDesktop) { ref.listen( windowControllerProvider, diff --git a/lib/features/profiles/notifier/notifier.dart b/lib/features/profiles/notifier/notifier.dart index 3e29cfc6..7fc6e689 100644 --- a/lib/features/profiles/notifier/notifier.dart +++ b/lib/features/profiles/notifier/notifier.dart @@ -1 +1,2 @@ export 'profiles_notifier.dart'; +export 'profiles_update_notifier.dart'; diff --git a/lib/features/profiles/notifier/profiles_update_notifier.dart b/lib/features/profiles/notifier/profiles_update_notifier.dart new file mode 100644 index 00000000..ed1ae442 --- /dev/null +++ b/lib/features/profiles/notifier/profiles_update_notifier.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:fpdart/fpdart.dart'; +import 'package:hiddify/core/core_providers.dart'; +import 'package:hiddify/core/router/router.dart'; +import 'package:hiddify/data/data_providers.dart'; +import 'package:hiddify/domain/failures.dart'; +import 'package:hiddify/domain/profiles/profiles.dart'; +import 'package:hiddify/services/service_providers.dart'; +import 'package:hiddify/utils/utils.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'profiles_update_notifier.g.dart'; + +typedef ProfileUpdateResult = ({ + String name, + Either failureOrSuccess +}); + +@Riverpod(keepAlive: true) +class ProfilesUpdateNotifier extends _$ProfilesUpdateNotifier with AppLogger { + @override + Stream build() { + ref.listenSelf( + (previous, next) { + if (next case AsyncData(value: final result)) { + final t = ref.read(translationsProvider); + final context = rootNavigatorKey.currentContext; + if (context == null || !context.mounted) return; + SnackBar(content: Text(t.profile.update.successMsg)); + switch (result.failureOrSuccess) { + case Right(): + CustomToast.success(t.profile.update.successMsg).show(context); + case Left(value: final err): + CustomToast.error(t.printError(err)).show(context); + } + } + }, + ); + _schedule(); + return const Stream.empty(); + } + + Future _schedule() async { + loggy.debug("scheduling profiles update worker"); + return ref.read(cronServiceProvider).schedule( + key: 'profiles_update', + duration: const Duration(minutes: 10), + callback: () async { + final failureOrProfiles = + await ref.read(profilesRepositoryProvider).watchAll().first; + if (failureOrProfiles case Right(value: final profiles)) { + for (final profile in profiles) { + loggy.debug("checking profile: [${profile.name}]"); + final updateInterval = profile.options?.updateInterval; + if (updateInterval != null && + updateInterval <= + DateTime.now().difference(profile.lastUpdate)) { + final failureOrSuccess = await ref + .read(profilesRepositoryProvider) + .update(profile) + .run(); + state = AsyncData( + (name: profile.name, failureOrSuccess: failureOrSuccess), + ); + } else { + loggy.debug("skipping profile: [${profile.name}]"); + } + } + } + }, + ); + } +} diff --git a/lib/services/cron_service.dart b/lib/services/cron_service.dart index fc65a513..ace624df 100644 --- a/lib/services/cron_service.dart +++ b/lib/services/cron_service.dart @@ -28,7 +28,6 @@ class CronService with InfraLogger { }) { loggy.debug("scheduling [$key]"); jobs[key] = (key, duration, callback); - _scheduler?.trigger(); } Future run(Job job) async {