the-mews/app/lib/presentation/app.dart

102 lines
2.9 KiB
Dart

import 'package:actors/actors.dart';
import 'package:flutter/material.dart';
import 'package:signals/signals_flutter.dart' show SignalBuilder;
import '../application/actors/fetch_actor.dart';
import '../application/controllers/browser_controller.dart';
import '../application/controllers/reader_settings_controller.dart';
import '../database/database.dart';
import '../l10n/strings.dart';
import 'reader/reader_screen.dart';
/// Wires the app's dependencies together and provides them to the tree.
/// Everything is local-first: the database is created up front and the fetch
/// actor is the only path to the network.
class AppDependencies {
AppDependencies({MewsDatabase? database, Actor<FetchCommand, FetchResult>? fetch})
: db = database ?? MewsDatabase(),
fetch = fetch ?? Actor.create(FetchHandler.new) {
browser = BrowserController(db: db, fetch: this.fetch);
settings = ReaderSettingsController(db);
library = LibraryController(db);
}
final MewsDatabase db;
final Actor<FetchCommand, FetchResult> fetch;
late final BrowserController browser;
late final ReaderSettingsController settings;
late final LibraryController library;
Future<void> start() async {
await settings.load();
await library.load();
await browser.restoreLastSession();
}
}
class AppScope extends InheritedWidget {
const AppScope({
required this.deps,
required this.strings,
required super.child,
super.key,
});
final AppDependencies deps;
final Strings strings;
static AppScope of(BuildContext context) =>
context.getInheritedWidgetOfExactType<AppScope>()!;
@override
bool updateShouldNotify(AppScope oldWidget) => false;
}
class MewsApp extends StatelessWidget {
const MewsApp({required this.deps, required this.strings, super.key});
final AppDependencies deps;
final Strings strings;
@override
Widget build(BuildContext context) {
return AppScope(
deps: deps,
strings: strings,
child: StringsScope(
strings: strings,
child: const _ThemedApp(),
),
);
}
}
class _ThemedApp extends StatelessWidget {
const _ThemedApp();
@override
Widget build(BuildContext context) {
final deps = AppScope.of(context).deps;
return SignalBuilder(builder: (context) {
final mode = switch (deps.settings.themeMode.value) {
'light' => ThemeMode.light,
'dark' => ThemeMode.dark,
_ => ThemeMode.system,
};
return MaterialApp(
title: 'Mews',
themeMode: mode,
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xff1a4f9c)),
),
darkTheme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xff1a4f9c), brightness: Brightness.dark),
),
home: const ReaderScreen(),
);
});
}
}