Automatically use dark mode based on system settings

Fixes #193
This commit is contained in:
Vishesh Handa
2021-02-06 23:01:09 +01:00
parent b5e2004d89
commit 9a3bf6ad42
8 changed files with 93 additions and 34 deletions

View File

@ -14,8 +14,12 @@ settings:
invalid: Please enter a valid email invalid: Please enter a valid email
display: display:
title: Display Settings title: Display Settings
darkTheme: Dark Theme
homeScreen: Home Screen homeScreen: Home Screen
theme: Theme
theme:
light: Light
dark: Dark
default: System Default
gitAuthor: Git Author Settings gitAuthor: Git Author Settings
versionInfo: Version Info versionInfo: Version Info
analytics: Analytics analytics: Analytics

View File

@ -5,6 +5,7 @@
- text: "Ignore folders with a .gjignore file. It's a temporary hack untill we start reading the .gjignore files like the .gitignore files" - text: "Ignore folders with a .gjignore file. It's a temporary hack untill we start reading the .gjignore files like the .gitignore files"
- text: "Add a working Experimental Markdown Toolbar" - text: "Add a working Experimental Markdown Toolbar"
- text: "Basic Undo/Redo support for Raw Editor" - text: "Basic Undo/Redo support for Raw Editor"
- text: "Automatically use dark mode based on system settings - #193"
- version: "1.73" - version: "1.73"
date: 2020-11-15 date: 2020-11-15

View File

@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart' as foundation;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:device_info/device_info.dart'; import 'package:device_info/device_info.dart';
import 'package:dynamic_theme/dynamic_theme.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:easy_localization_loader/easy_localization_loader.dart'; import 'package:easy_localization_loader/easy_localization_loader.dart';
import 'package:flutter_sentry/flutter_sentry.dart'; import 'package:flutter_sentry/flutter_sentry.dart';
@ -281,14 +280,6 @@ class _JournalAppState extends State<JournalApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DynamicTheme(
defaultBrightness: Brightness.light,
data: (b) => b == Brightness.light ? Themes.light : Themes.dark,
themedWidgetBuilder: buildApp,
);
}
MaterialApp buildApp(BuildContext context, ThemeData themeData) {
var stateContainer = Provider.of<Repository>(context); var stateContainer = Provider.of<Repository>(context);
var settings = Provider.of<Settings>(context); var settings = Provider.of<Settings>(context);
var appSettings = Provider.of<AppSettings>(context); var appSettings = Provider.of<AppSettings>(context);
@ -303,7 +294,10 @@ class _JournalAppState extends State<JournalApp> {
supportedLocales: EasyLocalization.of(context).supportedLocales, supportedLocales: EasyLocalization.of(context).supportedLocales,
locale: EasyLocalization.of(context).locale, locale: EasyLocalization.of(context).locale,
theme: themeData, theme: Themes.light,
darkTheme: Themes.dark,
themeMode: settings.theme.toThemeMode(),
navigatorObservers: <NavigatorObserver>[ navigatorObservers: <NavigatorObserver>[
AnalyticsRouteObserver(), AnalyticsRouteObserver(),
], ],

View File

@ -2,7 +2,6 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:dynamic_theme/dynamic_theme.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:email_validator/email_validator.dart'; import 'package:email_validator/email_validator.dart';
import 'package:ext_storage/ext_storage.dart'; import 'package:ext_storage/ext_storage.dart';
@ -141,7 +140,6 @@ class SettingsListState extends State<SettingsList> {
}, },
); );
var brightness = DynamicTheme.of(context).brightness;
var defaultNewFolder = settings.defaultNewNoteFolderSpec; var defaultNewFolder = settings.defaultNewNoteFolderSpec;
if (defaultNewFolder.isEmpty) { if (defaultNewFolder.isEmpty) {
defaultNewFolder = tr("rootFolder"); defaultNewFolder = tr("rootFolder");
@ -158,13 +156,15 @@ class SettingsListState extends State<SettingsList> {
return ListView(children: [ return ListView(children: [
SettingsHeader(tr('settings.display.title')), SettingsHeader(tr('settings.display.title')),
SwitchListTile( ListPreference(
title: Text(tr('settings.display.darkTheme')), title: tr('settings.display.theme'),
value: brightness == Brightness.dark, currentOption: settings.theme.toPublicString(),
onChanged: (bool newVal) { options: SettingsTheme.options.map((f) => f.toPublicString()).toList(),
var b = newVal ? Brightness.dark : Brightness.light; onChange: (String publicStr) {
var dynamicTheme = DynamicTheme.of(context); var s = SettingsTheme.fromPublicString(publicStr);
dynamicTheme.setBrightness(b); settings.theme = s;
settings.save();
setState(() {});
}, },
), ),
ProOverlay( ProOverlay(

View File

@ -48,6 +48,7 @@ class Settings extends ChangeNotifier {
int version = 2; int version = 2;
SettingsHomeScreen homeScreen = SettingsHomeScreen.Default; SettingsHomeScreen homeScreen = SettingsHomeScreen.Default;
SettingsTheme theme = SettingsTheme.Default;
SettingsMarkdownDefaultView markdownDefaultView = SettingsMarkdownDefaultView markdownDefaultView =
SettingsMarkdownDefaultView.Default; SettingsMarkdownDefaultView.Default;
@ -127,6 +128,7 @@ class Settings extends ChangeNotifier {
homeScreen = homeScreen =
SettingsHomeScreen.fromInternalString(_getString(pref, "homeScreen")); SettingsHomeScreen.fromInternalString(_getString(pref, "homeScreen"));
theme = SettingsTheme.fromInternalString(_getString(pref, "theme"));
imageLocationSpec = imageLocationSpec =
_getString(pref, "imageLocationSpec") ?? imageLocationSpec; _getString(pref, "imageLocationSpec") ?? imageLocationSpec;
@ -232,6 +234,8 @@ class Settings extends ChangeNotifier {
await _setBool(pref, "emojiParser", emojiParser, defaultSet.emojiParser); await _setBool(pref, "emojiParser", emojiParser, defaultSet.emojiParser);
await _setString(pref, "homeScreen", homeScreen.toInternalString(), await _setString(pref, "homeScreen", homeScreen.toInternalString(),
defaultSet.homeScreen.toInternalString()); defaultSet.homeScreen.toInternalString());
await _setString(pref, "theme", theme.toInternalString(),
defaultSet.theme.toInternalString());
await _setString(pref, "imageLocationSpec", imageLocationSpec, await _setString(pref, "imageLocationSpec", imageLocationSpec,
defaultSet.imageLocationSpec); defaultSet.imageLocationSpec);
await _setBool(pref, "zenMode", zenMode, defaultSet.zenMode); await _setBool(pref, "zenMode", zenMode, defaultSet.zenMode);
@ -349,6 +353,7 @@ class Settings extends ChangeNotifier {
'markdownDefaultView': markdownDefaultView.toInternalString(), 'markdownDefaultView': markdownDefaultView.toInternalString(),
'markdownLastUsedView': markdownLastUsedView.toInternalString(), 'markdownLastUsedView': markdownLastUsedView.toInternalString(),
'homeScreen': homeScreen.toInternalString(), 'homeScreen': homeScreen.toInternalString(),
'theme': theme.toInternalString(),
'imageLocationSpec': imageLocationSpec, 'imageLocationSpec': imageLocationSpec,
'zenMode': zenMode.toString(), 'zenMode': zenMode.toString(),
'saveTitleInH1': saveTitleInH1.toString(), 'saveTitleInH1': saveTitleInH1.toString(),
@ -784,3 +789,63 @@ class SettingsHomeScreen {
String generateRandomId() { String generateRandomId() {
return Uuid().v4().substring(0, 8); return Uuid().v4().substring(0, 8);
} }
class SettingsTheme {
static const Dark = SettingsTheme("settings.theme.dark", "dark");
static const Light = SettingsTheme("settings.theme.light", "light");
static const SystemDefault =
SettingsTheme("settings.theme.default", "default");
static const Default = SystemDefault;
final String _str;
final String _publicString;
const SettingsTheme(this._publicString, this._str);
String toInternalString() {
return _str;
}
String toPublicString() {
return tr(_publicString);
}
static const options = <SettingsTheme>[
Light,
Dark,
SystemDefault,
];
static SettingsTheme fromInternalString(String str) {
for (var opt in options) {
if (opt.toInternalString() == str) {
return opt;
}
}
return Default;
}
static SettingsTheme fromPublicString(String str) {
for (var opt in options) {
if (opt.toPublicString() == str) {
return opt;
}
}
return Default;
}
@override
String toString() {
assert(false, "SettingsTheme toString should never be called");
return "";
}
ThemeMode toThemeMode() {
if (this == SystemDefault) {
return ThemeMode.system;
}
if (this == Light) {
return ThemeMode.light;
}
return ThemeMode.dark;
}
}

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:dynamic_theme/dynamic_theme.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:function_types/function_types.dart'; import 'package:function_types/function_types.dart';
@ -8,6 +7,7 @@ import 'package:provider/provider.dart';
import 'package:time/time.dart'; import 'package:time/time.dart';
import 'package:gitjournal/app_settings.dart'; import 'package:gitjournal/app_settings.dart';
import 'package:gitjournal/settings.dart';
class AppDrawerHeader extends StatelessWidget { class AppDrawerHeader extends StatelessWidget {
final Func0<void> repoListToggled; final Func0<void> repoListToggled;
@ -180,12 +180,15 @@ class ThemeSwitcherButton extends StatelessWidget {
return GestureDetector( return GestureDetector(
child: const FaIcon(FontAwesomeIcons.solidMoon), child: const FaIcon(FontAwesomeIcons.solidMoon),
onTap: () { onTap: () {
var dynamicTheme = DynamicTheme.of(context); var theme = Theme.of(context);
var brightness = dynamicTheme.brightness; var settings = context.read<Settings>();
dynamicTheme.setBrightness(brightness == Brightness.light if (theme.brightness == Brightness.light) {
? Brightness.dark settings.theme = SettingsTheme.Dark;
: Brightness.light); } else {
settings.theme = SettingsTheme.Light;
}
settings.save();
}, },
); );
} }

View File

@ -213,13 +213,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.5+1" version: "0.0.5+1"
dynamic_theme:
dependency: "direct main"
description:
name: dynamic_theme
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
easy_localization: easy_localization:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -27,7 +27,6 @@ dependencies:
crypton: ^1.1.3 crypton: ^1.1.3
device_info: ">=0.4.2+4 <2.0.0" device_info: ">=0.4.2+4 <2.0.0"
dots_indicator: ^0.0.3 dots_indicator: ^0.0.3
dynamic_theme: ^1.0.0
easy_localization: ^2.3.2 easy_localization: ^2.3.2
easy_localization_loader: ^0.0.2 easy_localization_loader: ^0.0.2
email_validator: ^1.0.6 email_validator: ^1.0.6