import 'dart:io' show Platform; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:just_audio_background/just_audio_background.dart'; import 'shell/app_shell.dart'; import 'theme/accent.dart'; import 'theme/app_theme.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); // Lock-screen / notification transport is only available where audio_service // has a backend — Android/iOS. Skipping init elsewhere keeps the Linux dev // target (and tests) running. if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { // Never let background-audio setup block the first frame: on failure or // hang we still start the app (playback just loses lock-screen controls). try { await JustAudioBackground.init( androidNotificationChannelId: 'com.laforrestchurch.timbre.audio', androidNotificationChannelName: 'Timbre playback', androidNotificationOngoing: true, ).timeout(const Duration(seconds: 8)); } catch (e, st) { debugPrint('JustAudioBackground.init failed: $e\n$st'); } } runApp(const ProviderScope(child: TimbreApp())); } class TimbreApp extends ConsumerWidget { const TimbreApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { // The theme rebuilds whenever the album-art accent changes. final accent = ref.watch(accentProvider); return MaterialApp( title: 'Timbre', debugShowCheckedModeBanner: false, theme: buildTimbreTheme(accent), home: const AppShell(), ); } }