wip: Sicherungs-Commit aller Änderungen seit April + Arbeitsstruktur (CLAUDE.md, ROADMAP.md, PROGRESS.md, Autopilot)
6 Wochen uncommittete Arbeit (Voice-Channels, LiveKit-Manager, Settings-Modal u.v.m.) als ein WIP-Commit gesichert, damit nichts verloren geht und der Pi den aktuellen Stand klonen kann. Thematische Aufarbeitung: siehe ROADMAP M0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrAGBxBT6GfPXzeWQ4AXb
This commit is contained in:
+94
-16
@@ -1,29 +1,107 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:pyramid/core/app_state.dart';
|
||||
import 'package:pyramid/core/notification_service.dart' show checkPendingReply, setAppForeground;
|
||||
import 'package:pyramid/core/router.dart';
|
||||
import 'package:pyramid/core/settings_prefs.dart';
|
||||
import 'package:pyramid/core/theme.dart';
|
||||
import 'package:pyramid/features/auth/login_notifier.dart';
|
||||
import 'package:pyramid/widgets/pyramid_loader.dart';
|
||||
|
||||
class PyramidApp extends ConsumerWidget {
|
||||
class PyramidApp extends ConsumerStatefulWidget {
|
||||
const PyramidApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final router = ref.watch(routerProvider);
|
||||
final colorScheme = ref.watch(colorSchemeProvider);
|
||||
ConsumerState<PyramidApp> createState() => _PyramidAppState();
|
||||
}
|
||||
|
||||
return MaterialApp.router(
|
||||
title: 'Pyramid',
|
||||
theme: buildTheme(colorScheme, Brightness.light),
|
||||
darkTheme: buildTheme(colorScheme, Brightness.dark),
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [Locale('de'), Locale('en')],
|
||||
class _PyramidAppState extends ConsumerState<PyramidApp>
|
||||
with WidgetsBindingObserver {
|
||||
bool _prefsLoaded = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_loadPersistedPrefs();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
switch (state) {
|
||||
case AppLifecycleState.resumed:
|
||||
setAppForeground(true);
|
||||
checkPendingReply(ref);
|
||||
case AppLifecycleState.paused:
|
||||
case AppLifecycleState.detached:
|
||||
// Clears heartbeat so PushService.kt shows FCM notifications immediately.
|
||||
// Background Matrix syncs must not re-set the heartbeat (see notification_service.dart).
|
||||
setAppForeground(false);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadPersistedPrefs() async {
|
||||
final saved = await loadThemePrefs();
|
||||
if (!mounted) return;
|
||||
ref.read(themeModeProvider.notifier).state = saved.isDark;
|
||||
ref.read(accentProvider.notifier).state = saved.accentIdx;
|
||||
ref.read(radiusProvider.notifier).state = saved.radius;
|
||||
ref.read(motionProvider.notifier).state = saved.motion;
|
||||
setState(() => _prefsLoaded = true);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Block the router from rendering until auth state is known so the
|
||||
// /server page never flashes before the redirect to /app fires.
|
||||
final authAsync = ref.watch(isLoggedInProvider);
|
||||
if (authAsync.isLoading || !_prefsLoaded) {
|
||||
return const MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: Scaffold(
|
||||
backgroundColor: Color(0xFF1A1B1E),
|
||||
body: Center(child: PyramidLoader(size: 80)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final router = ref.watch(routerProvider);
|
||||
final isDark = ref.watch(themeModeProvider);
|
||||
final accentIdx = ref.watch(accentProvider);
|
||||
final radius = ref.watch(radiusProvider);
|
||||
final density = ref.watch(densityProvider);
|
||||
final motion = ref.watch(motionProvider);
|
||||
final accent = accentPresets[accentIdx].color;
|
||||
|
||||
return PyramidTheme(
|
||||
isDark: isDark,
|
||||
accent: accent,
|
||||
radius: radius,
|
||||
density: density,
|
||||
motion: motion,
|
||||
child: MaterialApp.router(
|
||||
title: 'Pyramid',
|
||||
theme: buildPyramidThemeData(false),
|
||||
darkTheme: buildPyramidThemeData(true),
|
||||
themeMode: isDark ? ThemeMode.dark : ThemeMode.light,
|
||||
routerConfig: router,
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [Locale('de'), Locale('en')],
|
||||
debugShowCheckedModeBanner: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user