Files
tasq/lib/app.dart
T
2026-04-27 06:20:39 +08:00

65 lines
2.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'routing/app_router.dart';
import 'models/profile.dart';
import 'providers/connectivity_provider.dart';
import 'providers/profile_provider.dart';
import 'services/background_location_service.dart';
import 'theme/app_theme.dart';
import 'utils/snackbar.dart';
import 'widgets/ios_install_prompt.dart';
import 'widgets/offline_banner.dart';
class TasqApp extends ConsumerWidget {
const TasqApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// Keep the connectivity monitor alive at the root so the global online
// check is wired into StreamRecoveryWrapper before any provider subscribes
// to a Supabase realtime stream. Without this watch the autoDispose
// provider only stays alive while OfflineBanner is mounted, which is too
// late for offline-cold-launch detection.
ref.watch(connectivityMonitorProvider);
final router = ref.watch(appRouterProvider);
// Ensure background service is running if the profile indicates tracking.
// This handles the case where the app restarts while tracking was already
// enabled (service should persist, but this guarantees it). It also stops
// the service when tracking is disabled externally.
ref.listen<AsyncValue<Profile?>>(currentProfileProvider, (
previous,
next,
) async {
final profile = next.valueOrNull;
final allow = profile?.allowTracking ?? false;
if (allow) {
await startBackgroundLocationUpdates();
} else {
await stopBackgroundLocationUpdates();
}
});
return MaterialApp.router(
title: 'TasQ',
routerConfig: router,
scaffoldMessengerKey: scaffoldMessengerKey,
theme: AppTheme.light(),
darkTheme: AppTheme.dark(),
themeMode: ThemeMode.system,
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
FlutterQuillLocalizations.delegate,
],
builder: (context, child) => OfflineBanner(
child: IosInstallPrompt(child: child ?? const SizedBox.shrink()),
),
);
}
}