Switch dark mode in runtime

This commit is contained in:
Ming Ming 2021-04-17 17:04:46 +08:00
parent c22c89678b
commit 1ab320fe76
7 changed files with 65 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

View file

@ -61,3 +61,5 @@ class FileRemovedEvent {
final Account account; final Account account;
final File file; final File file;
} }
class ThemeChangedEvent {}

View file

@ -56,6 +56,10 @@ class Pref {
Future<bool> setLastVersion(int value) => _pref.setInt("lastVersion", value); Future<bool> setLastVersion(int value) => _pref.setInt("lastVersion", value);
bool isDarkTheme([bool def = false]) => _pref.getBool("isDarkTheme") ?? def;
Future<bool> setDarkTheme(bool value) => _pref.setBool("isDarkTheme", value);
Pref._(); Pref._();
static final _inst = Pref._(); static final _inst = Pref._();

View file

@ -105,6 +105,14 @@ class AppTheme extends StatelessWidget {
: Colors.white60; : Colors.white60;
} }
static Color getAppBarDarkModeSwitchColor(BuildContext context) {
return Colors.black87;
}
static Color getAppBarDarkModeSwitchTrackColor(BuildContext context) {
return Colors.white.withOpacity(.5);
}
static const primarySwatchLight = Colors.blue; static const primarySwatchLight = Colors.blue;
static const primarySwatchDark = Colors.cyan; static const primarySwatchDark = Colors.cyan;

View file

@ -1,7 +1,11 @@
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:kiwi/kiwi.dart';
import 'package:nc_photos/account.dart'; import 'package:nc_photos/account.dart';
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/pref.dart';
import 'package:nc_photos/theme.dart'; import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/account_picker_dialog.dart'; import 'package:nc_photos/widget/account_picker_dialog.dart';
import 'package:nc_photos/widget/settings.dart'; import 'package:nc_photos/widget/settings.dart';
@ -63,6 +67,19 @@ class HomeSliverAppBar extends StatelessWidget {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
actions: (actions ?? []) + actions: (actions ?? []) +
[ [
Switch(
value: Theme.of(context).brightness == Brightness.dark,
onChanged: _onDarkModeChanged,
activeColor: AppTheme.getAppBarDarkModeSwitchColor(context),
inactiveThumbColor:
AppTheme.getAppBarDarkModeSwitchColor(context),
activeTrackColor:
AppTheme.getAppBarDarkModeSwitchTrackColor(context),
activeThumbImage:
const AssetImage("assets/ic_dark_mode_switch_24dp.png"),
inactiveThumbImage:
const AssetImage("assets/ic_dark_mode_switch_24dp.png"),
),
PopupMenuButton( PopupMenuButton(
tooltip: MaterialLocalizations.of(context).moreButtonTooltip, tooltip: MaterialLocalizations.of(context).moreButtonTooltip,
itemBuilder: (context) => itemBuilder: (context) =>
@ -89,6 +106,12 @@ class HomeSliverAppBar extends StatelessWidget {
); );
} }
void _onDarkModeChanged(bool value) {
Pref.inst().setDarkTheme(value).then((_) {
KiwiContainer().resolve<EventBus>().fire(ThemeChangedEvent());
});
}
final Account account; final Account account;
/// Screen specific action buttons /// Screen specific action buttons

View file

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/pref.dart';
import 'package:nc_photos/snack_bar_manager.dart'; import 'package:nc_photos/snack_bar_manager.dart';
import 'package:nc_photos/theme.dart'; import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/album_viewer.dart'; import 'package:nc_photos/widget/album_viewer.dart';
@ -14,9 +16,18 @@ import 'package:nc_photos/widget/sign_in.dart';
import 'package:nc_photos/widget/splash.dart'; import 'package:nc_photos/widget/splash.dart';
import 'package:nc_photos/widget/viewer.dart'; import 'package:nc_photos/widget/viewer.dart';
class MyApp extends StatelessWidget implements SnackBarHandler { class MyApp extends StatefulWidget {
MyApp() { @override
createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> implements SnackBarHandler {
@override
void initState() {
super.initState();
SnackBarManager().registerHandler(this); SnackBarManager().registerHandler(this);
_themeChangedListener =
AppEventListener<ThemeChangedEvent>(_onThemeChangedEvent)..begin();
} }
@override @override
@ -25,6 +36,7 @@ class MyApp extends StatelessWidget implements SnackBarHandler {
onGenerateTitle: (context) => AppLocalizations.of(context).appTitle, onGenerateTitle: (context) => AppLocalizations.of(context).appTitle,
theme: _getLightTheme(), theme: _getLightTheme(),
darkTheme: _getDarkTheme(), darkTheme: _getDarkTheme(),
themeMode: Pref.inst().isDarkTheme() ? ThemeMode.dark : ThemeMode.light,
initialRoute: Splash.routeName, initialRoute: Splash.routeName,
onGenerateRoute: _onGenerateRoute, onGenerateRoute: _onGenerateRoute,
scaffoldMessengerKey: _scaffoldMessengerKey, scaffoldMessengerKey: _scaffoldMessengerKey,
@ -34,6 +46,13 @@ class MyApp extends StatelessWidget implements SnackBarHandler {
); );
} }
@override
void dispose() {
super.dispose();
SnackBarManager().unregisterHandler(this);
_themeChangedListener.end();
}
@override @override
showSnackBar(SnackBar snackBar) => showSnackBar(SnackBar snackBar) =>
_scaffoldMessengerKey.currentState?.showSnackBar(snackBar); _scaffoldMessengerKey.currentState?.showSnackBar(snackBar);
@ -67,6 +86,10 @@ class MyApp extends StatelessWidget implements SnackBarHandler {
return route; return route;
} }
void _onThemeChangedEvent(ThemeChangedEvent ev) {
setState(() {});
}
Route<dynamic> _handleBasicRoute(RouteSettings settings) { Route<dynamic> _handleBasicRoute(RouteSettings settings) {
for (final e in _getRouter().entries) { for (final e in _getRouter().entries) {
if (e.key == settings.name) { if (e.key == settings.name) {
@ -165,5 +188,7 @@ class MyApp extends StatelessWidget implements SnackBarHandler {
final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>(); final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
static final _log = Logger("widget.my_app.MyApp"); AppEventListener<ThemeChangedEvent> _themeChangedListener;
static final _log = Logger("widget.my_app.MyAppState");
} }