From 7a451dccce0f7fce76e673e3ad4d0a9733f6875d Mon Sep 17 00:00:00 2001 From: Liplum Date: Tue, 24 Sep 2024 02:55:13 +0800 Subject: [PATCH] precache the timetable background when app was resumed --- lib/app.dart | 189 ++++++++++++++++++++++++++++----------------------- 1 file changed, 104 insertions(+), 85 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index 2a252343..59583a55 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -12,6 +12,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mimir/agreements/entity/agreements.dart'; import 'package:mimir/agreements/page/privacy_policy.dart'; +import 'package:mimir/credentials/init.dart'; import 'package:mimir/files.dart'; import 'package:mimir/intent/file_type/handle.dart'; import 'package:mimir/lifecycle.dart'; @@ -45,6 +46,8 @@ class _MimirAppState extends ConsumerState { Settings.timetable.focusTimetable ? buildTimetableFocusRouter() : buildCommonRoutingConfig(), ); late final router = buildRouter($routingConfig); + StreamSubscription? intentSub; + StreamSubscription? $appLink; @override void initState() { @@ -55,6 +58,47 @@ class _MimirAppState extends ConsumerState { ); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } + if (!kIsWeb) { + fitSystemScreenshot.init(); + } + + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + $appLink = AppLinks().uriLinkStream.listen(handleUriLink); + }); + if (UniversalPlatform.isIOS || UniversalPlatform.isAndroid) { + // Listen to media sharing coming from outside the app while the app is in the memory. + intentSub = ReceiveSharingIntent.instance.getMediaStream().listen((list) async { + ref.read($intentFiles.notifier).state = [ + ...ref.read($intentFiles), + ...list, + ]; + await handleFileIntents(list); + }, onError: (error) { + debugPrintError(error); + }); + + // Get the media sharing coming from outside the app while the app is closed. + ReceiveSharingIntent.instance.getInitialMedia().then((list) async { + ref.read($intentFiles.notifier).state = [ + ...ref.read($intentFiles), + ...list, + ]; + await handleFileIntents(list); + if (UniversalPlatform.isIOS) { + await Future.wait(list.map((file) => File(file.path).delete(recursive: false))); + } + // Tell the library that we are done processing the intent. + ReceiveSharingIntent.instance.reset(); + }); + } + } + + @override + void dispose() { + $appLink?.cancel(); + fitSystemScreenshot.release(); + intentSub?.cancel(); + super.dispose(); } @override @@ -123,6 +167,28 @@ class _MimirAppState extends ConsumerState { ), ); } + + Future handleUriLink(Uri uri) async { + ref.read($appLinks.notifier).state = [...ref.read($appLinks), (uri: uri, ts: DateTime.now())]; + final navigateCtx = $key.currentContext; + if (navigateCtx == null) return; + if (!kIsWeb) { + final maybePath = Uri.decodeFull(uri.toString()); + if (uri.scheme == "file") { + await onHandleFilePath(context: navigateCtx, path: maybePath); + return; + } else { + final isFile = await File(maybePath).exists(); + if (isFile) { + if (!navigateCtx.mounted) return; + await onHandleFilePath(context: navigateCtx, path: maybePath); + return; + } + } + } + if (!navigateCtx.mounted) return; + await onHandleDeepLink(context: navigateCtx, deepLink: uri); + } } class _PostServiceRunner extends ConsumerStatefulWidget { @@ -138,57 +204,26 @@ class _PostServiceRunner extends ConsumerStatefulWidget { } class _PostServiceRunnerState extends ConsumerState<_PostServiceRunner> { - StreamSubscription? intentSub; - StreamSubscription? $appLink; + late final AppLifecycleListener _listener; @override void initState() { super.initState(); + _listener = AppLifecycleListener( + onResume: onResume, + ); if (!kIsWeb) { - fitSystemScreenshot.init(); - } - if (!kIsWeb) { - Future.delayed(Duration.zero).then((value) async { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { await checkAppUpdate( context: $key.currentContext!, delayAtLeast: const Duration(milliseconds: 3000), manually: false, ); }); - } - WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - $appLink = AppLinks().uriLinkStream.listen(handleUriLink); - }); - if (UniversalPlatform.isIOS || UniversalPlatform.isAndroid) { - initQuickActions(); - // Listen to media sharing coming from outside the app while the app is in the memory. - intentSub = ReceiveSharingIntent.instance.getMediaStream().listen((list) async { - ref.read($intentFiles.notifier).state = [ - ...ref.read($intentFiles), - ...list, - ]; - await handleFileIntents(list); - }, onError: (error) { - debugPrintError(error); - }); - - // Get the media sharing coming from outside the app while the app is closed. - ReceiveSharingIntent.instance.getInitialMedia().then((list) async { - ref.read($intentFiles.notifier).state = [ - ...ref.read($intentFiles), - ...list, - ]; - await handleFileIntents(list); - if (UniversalPlatform.isIOS) { - await Future.wait(list.map((file) => File(file.path).delete(recursive: false))); - } - // Tell the library that we are done processing the intent. - ReceiveSharingIntent.instance.reset(); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + await tryAutoSyncTimetable(); }); } - WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - await tryAutoSyncTimetable(); - }); WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { final navigateCtx = $key.currentContext; if (navigateCtx == null) return; @@ -196,64 +231,39 @@ class _PostServiceRunnerState extends ConsumerState<_PostServiceRunner> { if (accepted == true) return; await AgreementsAcceptanceSheet.show(navigateCtx); }); - } - - Future handleFileIntents(List files) async { - final navigateCtx = $key.currentContext; - if (navigateCtx == null) return; - for (final file in files) { - // ignore the url intent from the this app - if (file.type == SharedMediaType.url) { - final uri = Uri.tryParse(file.path); - if (uri != null && canHandleDeepLink(deepLink: uri)) continue; - } - if (!navigateCtx.mounted) return; - await onHandleFilePath(context: navigateCtx, path: file.path); + if (UniversalPlatform.isIOS || UniversalPlatform.isAndroid) { + initQuickActions(); } } @override - void didChangeDependencies() { + void dispose() { + _listener.dispose(); + super.dispose(); + } + + Future onResume() async { + await precacheTimetableBackground(); + } + + Future precacheTimetableBackground() async { // precache timetable background file final timetableBk = Settings.timetable.backgroundImage; if (timetableBk != null && timetableBk.enabled) { if (kIsWeb) { - precacheImage(NetworkImage(timetableBk.path), context); + await precacheImage(NetworkImage(timetableBk.path), context); } else { - precacheImage(FileImage(Files.timetable.backgroundFile), context); + await precacheImage(FileImage(Files.timetable.backgroundFile), context); } } - super.didChangeDependencies(); } @override - void dispose() { - $appLink?.cancel(); - fitSystemScreenshot.release(); - intentSub?.cancel(); - super.dispose(); - } - - Future handleUriLink(Uri uri) async { - ref.read($appLinks.notifier).state = [...ref.read($appLinks), (uri: uri, ts: DateTime.now())]; - final navigateCtx = $key.currentContext; - if (navigateCtx == null) return; - if (!kIsWeb) { - final maybePath = Uri.decodeFull(uri.toString()); - if (uri.scheme == "file") { - await onHandleFilePath(context: navigateCtx, path: maybePath); - return; - } else { - final isFile = await File(maybePath).exists(); - if (isFile) { - if (!navigateCtx.mounted) return; - await onHandleFilePath(context: navigateCtx, path: maybePath); - return; - } - } - } - if (!navigateCtx.mounted) return; - await onHandleDeepLink(context: navigateCtx, deepLink: uri); + Widget build(BuildContext context) { + ref.listen(CredentialsInit.storage.oa.$credentials, (pre, next) async { + await initQuickActions(); + }); + return widget.child; } Future tryAutoSyncTimetable() async { @@ -271,9 +281,18 @@ class _PostServiceRunnerState extends ConsumerState<_PostServiceRunner> { } } } +} - @override - Widget build(BuildContext context) { - return widget.child; +Future handleFileIntents(List files) async { + final navigateCtx = $key.currentContext; + if (navigateCtx == null) return; + for (final file in files) { + // ignore the url intent from the this app + if (file.type == SharedMediaType.url) { + final uri = Uri.tryParse(file.path); + if (uri != null && canHandleDeepLink(deepLink: uri)) continue; + } + if (!navigateCtx.mounted) return; + await onHandleFilePath(context: navigateCtx, path: file.path); } }