59 lines
2.2 KiB
Dart
59 lines
2.2 KiB
Dart
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 'settings/settings_store.dart';
|
|
import 'shell/app_shell.dart';
|
|
import 'state/providers.dart';
|
|
import 'theme/accent.dart';
|
|
import 'theme/app_theme.dart';
|
|
import 'widgets/splash_screen.dart';
|
|
|
|
Future<void> 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 accent either tracks the album art (default) or is pinned to a
|
|
// user-chosen static color. The theme rebuilds whenever it changes.
|
|
final settings = ref.watch(settingsProvider);
|
|
final accent = settings.useStaticAccent
|
|
? settings.staticAccentColor
|
|
: ref.watch(accentProvider);
|
|
// Keep the accent synced with the remote track's art while acting as a
|
|
// remote (bug #6). Alive as long as the app is.
|
|
ref.watch(remoteAccentSyncProvider);
|
|
return MaterialApp(
|
|
title: 'Timbre',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: buildTimbreTheme(accent),
|
|
// AppShell mounts under the splash and boots behind it; the splash fades
|
|
// out after a couple of seconds.
|
|
home: const SplashGate(child: AppShell()),
|
|
);
|
|
}
|
|
}
|