improved performance and battery usage on older devices

This commit is contained in:
2026-09-25 23:58:08 +02:00
parent ed8e52f475
commit 56a497985b
70 changed files with 1631 additions and 621 deletions
+48 -23
View File
@@ -167,6 +167,12 @@ Future<void> main() async {
await Future.wait(initialisationTasks);
log('app initialisation done!');
// Independent of the notification setup below, so it runs alongside it.
final widgetSyncInit = _startupStep(
'widget sync',
WidgetSync.ensureInitialized,
);
// Local notifications: init the plugin (with tap/action callbacks) and the
// Android channels, then register the FCM background isolate handler that
// decrypts and renders Nextcloud pushes while the app is not in foreground.
@@ -186,9 +192,9 @@ Future<void> main() async {
),
);
// Wire up the home-screen widget bridge before runApp so any widget render
// triggered during startup hits initialised native storage.
await _startupStep('widget sync', WidgetSync.ensureInitialized);
// The home-screen widget bridge must be ready before runApp so any widget
// render triggered during startup hits initialised native storage.
await widgetSyncInit;
unawaited(
WidgetBackgroundTask.initialize().onError(
(e, _) => log('Workmanager init failed: $e'),
@@ -271,6 +277,10 @@ class Main extends StatefulWidget {
}
class _MainState extends State<Main> {
final List<NavigatorObserver> _navigatorObservers = [
AppRoutes.chatRouteObserver,
DownloadRouteObserver(),
];
bool _showPostLoginSplash = false;
bool _appMounted = true;
late AccountStatus _lastStatus;
@@ -364,39 +374,45 @@ class _MainState extends State<Main> {
@override
Widget build(BuildContext context) => Directionality(
textDirection: TextDirection.ltr,
child: BlocBuilder<SettingsCubit, Settings>(
builder: (context, settings) {
final devToolsSettings = settings.devToolsSettings;
// Selects only what the root uses: Settings is mutated in place and
// re-emitted as a fresh instance on every write, so a plain BlocBuilder
// would rebuild MaterialApp (and every route) for unrelated settings.
child: BlocSelector<SettingsCubit, Settings, _RootSettings>(
selector: (settings) => (
appTheme: settings.appTheme,
mcBaseUrl: settings.devToolsSettings.resolveMarianumConnectBaseUrl(),
notificationsEnabled: settings.notificationSettings.enabled,
showPerformanceOverlay:
settings.devToolsSettings.showPerformanceOverlay,
checkerboardOffscreenLayers:
settings.devToolsSettings.checkerboardOffscreenLayers,
checkerboardRasterCacheImages:
settings.devToolsSettings.checkerboardRasterCacheImages,
),
builder: (context, root) {
// Keep the MC dio singleton aligned with the currently selected
// endpoint (live / beta / custom). Idempotent when the URL is
// unchanged so it's safe to call on every rebuild. Mirrored into
// WidgetSync so the background isolate refreshes against the same
// endpoint.
final mcBaseUrl = devToolsSettings.resolveMarianumConnectBaseUrl();
MarianumConnectEndpoint.update(mcBaseUrl);
unawaited(WidgetSync.setMarianumConnectBaseUrl(mcBaseUrl));
// unchanged. Mirrored into WidgetSync so the background isolate
// refreshes against the same endpoint.
MarianumConnectEndpoint.update(root.mcBaseUrl);
unawaited(WidgetSync.setMarianumConnectBaseUrl(root.mcBaseUrl));
// Mirror the notification toggle into group-scoped storage so the FCM
// background isolate and the iOS NSE can suppress rendering when off.
unawaited(
const PushRegistrationStore().setNotificationsEnabled(
settings.notificationSettings.enabled,
root.notificationsEnabled,
),
);
return MaterialApp(
showPerformanceOverlay: devToolsSettings.showPerformanceOverlay,
checkerboardOffscreenLayers:
devToolsSettings.checkerboardOffscreenLayers,
checkerboardRasterCacheImages:
devToolsSettings.checkerboardRasterCacheImages,
showPerformanceOverlay: root.showPerformanceOverlay,
checkerboardOffscreenLayers: root.checkerboardOffscreenLayers,
checkerboardRasterCacheImages: root.checkerboardRasterCacheImages,
debugShowCheckedModeBanner: false,
navigatorKey: AppRoutes.rootNavigatorKey,
// Used by ChatView.didPopNext to reclaim the global ChatBloc.
// DownloadRouteObserver tracks full-page navigations so the downloads
// chip only surfaces once the user leaves the screen they started on.
navigatorObservers: [
AppRoutes.chatRouteObserver,
DownloadRouteObserver(),
],
navigatorObservers: _navigatorObservers,
localizationsDelegates: const [
...GlobalMaterialLocalizations.delegates,
GlobalWidgetsLocalizations.delegate,
@@ -404,7 +420,7 @@ class _MainState extends State<Main> {
supportedLocales: const [Locale('de'), Locale('en')],
locale: const Locale('de'),
title: 'Marianum Fulda',
themeMode: settings.appTheme,
themeMode: root.appTheme,
theme: LightAppTheme.theme,
darkTheme: DarkAppTheme.theme,
// Brand-colored backdrop behind every route. During the logout
@@ -527,3 +543,12 @@ class _MainState extends State<Main> {
),
);
}
typedef _RootSettings = ({
ThemeMode appTheme,
String mcBaseUrl,
bool notificationsEnabled,
bool showPerformanceOverlay,
bool checkerboardOffscreenLayers,
bool checkerboardRasterCacheImages,
});