Implement ValueNotifier for all settings
This commit is contained in:
@@ -167,7 +167,7 @@ class KanjiBox extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
color: calculatedForeground,
|
||||
fontSize: calculatedFontSize,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -133,7 +133,7 @@ class _DrawingBoardState extends State<DrawingBoard> {
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: panelColor.foregroundColor,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -257,7 +257,7 @@ class _DrawingBoardState extends State<DrawingBoard> {
|
||||
),
|
||||
);
|
||||
|
||||
if (reduceKanjiDrawingBoardSize) {
|
||||
if (reduceKanjiDrawingBoardSize.value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(50, 0, 50, 30),
|
||||
child: board,
|
||||
|
||||
@@ -94,7 +94,7 @@ class HistoryEntryTile extends StatelessWidget {
|
||||
child: Text(formatTime(entry.lastTimestamp)),
|
||||
),
|
||||
DefaultTextStyle.merge(
|
||||
style: japaneseFont.textStyle,
|
||||
style: japaneseFont.value.textStyle,
|
||||
child: entry.isKanji
|
||||
? KanjiBox.headline4(context: context, kanji: entry.kanji!)
|
||||
: Expanded(child: Text(entry.word!)),
|
||||
|
||||
@@ -24,7 +24,7 @@ class Grade extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
color: colors.foregroundColor,
|
||||
fontSize: 20.0,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class Header extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 70.0,
|
||||
color: colors.foregroundColor,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ class Radical extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
color: colors.foregroundColor,
|
||||
fontSize: 40.0,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -66,14 +66,14 @@ class YomiChips extends StatelessWidget {
|
||||
|
||||
Widget yomiWrapper(BuildContext context) {
|
||||
final yomiCards = yomi
|
||||
.map((y) => romajiEnabled ? transliterateKanaToLatin(y) : y)
|
||||
.map((y) => romajiEnabled.value ? transliterateKanaToLatin(y) : y)
|
||||
.map(
|
||||
(y) => yomiCard(
|
||||
context: context,
|
||||
yomi: y,
|
||||
color: type.getColor(context),
|
||||
extraTextStyle: type != YomiType.meaning && !romajiEnabled
|
||||
? japaneseFont.textStyle
|
||||
extraTextStyle: type != YomiType.meaning && !romajiEnabled.value
|
||||
? japaneseFont.value.textStyle
|
||||
: null,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -46,7 +46,7 @@ class _GridItem extends StatelessWidget {
|
||||
child: FittedBox(
|
||||
child: Text(
|
||||
kanji,
|
||||
style: japaneseFont.textStyle.merge(
|
||||
style: japaneseFont.value.textStyle.merge(
|
||||
TextStyle(color: colors.foregroundColor),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -54,7 +54,7 @@ class KanjiSearchBarState extends State<KanjiSearchBar> {
|
||||
controller: textController,
|
||||
onChanged: (text) => onChanged(),
|
||||
onSubmitted: (_) => {},
|
||||
style: japaneseFont.textStyle,
|
||||
style: japaneseFont.value.textStyle,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Search',
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
|
||||
|
||||
@@ -40,7 +40,7 @@ class LibraryListEntryTile extends StatelessWidget {
|
||||
(index + 1).toString(),
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium!.merge(japaneseFont.textStyle),
|
||||
).textTheme.titleMedium!.merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class GlobalSearchBar extends StatelessWidget {
|
||||
onSubmitted: (text) => _search(context, text),
|
||||
controller: textController,
|
||||
focusNode: textFocus,
|
||||
style: japaneseFont.textStyle,
|
||||
style: japaneseFont.value.textStyle,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Search',
|
||||
border: OutlineInputBorder(
|
||||
|
||||
@@ -45,7 +45,7 @@ class _LanguageSelectorState extends State<LanguageSelector> {
|
||||
isSelected: isSelected,
|
||||
children: [
|
||||
_languageOption('Auto'),
|
||||
_languageOption('日本語', style: japaneseFont.textStyle),
|
||||
_languageOption('日本語', style: japaneseFont.value.textStyle),
|
||||
_languageOption('English'),
|
||||
],
|
||||
onPressed: (buttonIndex) {
|
||||
|
||||
@@ -22,13 +22,13 @@ class JapaneseHeader extends StatelessWidget {
|
||||
children: [
|
||||
(furigana != null)
|
||||
? Text(
|
||||
romajiEnabled
|
||||
romajiEnabled.value
|
||||
? transliterateKanaToLatin(furigana!)
|
||||
: furigana!,
|
||||
style: japaneseFont.textStyle,
|
||||
style: japaneseFont.value.textStyle,
|
||||
)
|
||||
: const Text(''),
|
||||
Text(baseWord, style: japaneseFont.textStyle),
|
||||
Text(baseWord, style: japaneseFont.value.textStyle),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -29,7 +29,7 @@ class KanjiRow extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
color: colors.foregroundColor,
|
||||
fontSize: fontSize,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -48,7 +48,7 @@ class KanjiKanaBox extends StatelessWidget {
|
||||
children: [
|
||||
(furigana != null)
|
||||
? Text(
|
||||
romajiEnabled
|
||||
romajiEnabled.value
|
||||
? transliterateKanaToLatin(furigana!)
|
||||
: furigana!,
|
||||
style:
|
||||
@@ -56,9 +56,9 @@ class KanjiKanaBox extends StatelessWidget {
|
||||
fontSize: fFontsize,
|
||||
color: colors.foregroundColor,
|
||||
).merge(
|
||||
romajiEnabled && autoTransliterateRomaji
|
||||
romajiEnabled.value && autoTransliterateRomaji
|
||||
? null
|
||||
: japaneseFont.textStyle,
|
||||
: japaneseFont.value.textStyle,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
@@ -72,9 +72,9 @@ class KanjiKanaBox extends StatelessWidget {
|
||||
child: Text(baseWord),
|
||||
style: TextStyle(
|
||||
fontSize: kanjiFontsize,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
if (romajiEnabled && showRomajiBelow)
|
||||
if (romajiEnabled.value && showRomajiBelow)
|
||||
Text(transliterateKanaToLatin(furigana ?? baseWord)),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -53,8 +53,8 @@ class _SearchResultCardState extends State<SearchResultCard> {
|
||||
(data) => setState(() {
|
||||
isFavourited = data['favourites'] ?? false;
|
||||
isQuickListed =
|
||||
quickAddLibraryList != null &&
|
||||
(data[quickAddLibraryList!] ?? false);
|
||||
quickAddLibraryList.value != null &&
|
||||
(data[quickAddLibraryList.value!] ?? false);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -139,11 +139,11 @@ class _SearchResultCardState extends State<SearchResultCard> {
|
||||
onLongPress: () =>
|
||||
copyToClipboard(context, widget.result.japanese.firstOrNull?.base),
|
||||
onDoubleTap: () {
|
||||
if (isQuickListed && quickAddLibraryList != null) {
|
||||
if (isQuickListed && quickAddLibraryList.value != null) {
|
||||
GetIt.instance
|
||||
.get<Database>()
|
||||
.libraryListDeleteEntry(
|
||||
quickAddLibraryList!,
|
||||
quickAddLibraryList.value!,
|
||||
jmdictEntryId: widget.result.entryId,
|
||||
)
|
||||
.then((_) => fetchFavouriteAndQuickListStatus());
|
||||
@@ -151,7 +151,7 @@ class _SearchResultCardState extends State<SearchResultCard> {
|
||||
GetIt.instance
|
||||
.get<Database>()
|
||||
.libraryListInsertEntry(
|
||||
quickAddLibraryList!,
|
||||
quickAddLibraryList.value!,
|
||||
jmdictEntryId: widget.result.entryId,
|
||||
)
|
||||
.then((_) => fetchFavouriteAndQuickListStatus());
|
||||
|
||||
@@ -61,27 +61,27 @@ class _HomeState extends State<Home> {
|
||||
content: WordSearchView(),
|
||||
titleBar: 'Search',
|
||||
icon: Icon(Icons.search),
|
||||
actions: [
|
||||
if (incognitoModeEnabled)
|
||||
IconButton(
|
||||
icon: const Icon(Mdi.incognito),
|
||||
onPressed: () =>
|
||||
showSnackbar(context, 'History tracking is disabled'),
|
||||
),
|
||||
],
|
||||
// actions: [
|
||||
// if (incognitoModeEnabled.value)
|
||||
// IconButton(
|
||||
// icon: const Icon(Mdi.incognito),
|
||||
// onPressed: () =>
|
||||
// showSnackbar(context, 'History tracking is disabled'),
|
||||
// ),
|
||||
// ],
|
||||
),
|
||||
_Page(
|
||||
content: KanjiSearchView(),
|
||||
titleBar: 'Kanji Search',
|
||||
icon: Icon(Mdi.ideogramCjk, size: 30),
|
||||
actions: [
|
||||
if (incognitoModeEnabled)
|
||||
IconButton(
|
||||
icon: const Icon(Mdi.incognito),
|
||||
onPressed: () =>
|
||||
showSnackbar(context, 'History tracking is disabled'),
|
||||
),
|
||||
],
|
||||
// actions: [
|
||||
// if (incognitoModeEnabled.value)
|
||||
// IconButton(
|
||||
// icon: const Icon(Mdi.incognito),
|
||||
// onPressed: () =>
|
||||
// showSnackbar(context, 'History tracking is disabled'),
|
||||
// ),
|
||||
// ],
|
||||
),
|
||||
const _Page(
|
||||
content: HistoryView(),
|
||||
|
||||
@@ -153,7 +153,7 @@ class _KanjiSearchResultPageState extends State<KanjiSearchResultPage> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
actions: [
|
||||
if (incognitoModeEnabled)
|
||||
if (incognitoModeEnabled.value)
|
||||
IconButton(
|
||||
icon: const Icon(Mdi.incognito),
|
||||
onPressed: () =>
|
||||
@@ -233,7 +233,7 @@ class _KanjiSearchResultPageState extends State<KanjiSearchResultPage> {
|
||||
.libraryListListContains('favourites', kanji: widget.kanji)
|
||||
.then((value) => setState(() => isFavourite = value));
|
||||
|
||||
if (!incognitoModeEnabled && !addedToDatabase) {
|
||||
if (!incognitoModeEnabled.value && !addedToDatabase) {
|
||||
GetIt.instance
|
||||
.get<Database>()
|
||||
.historyEntryInsertKanji(widget.kanji)
|
||||
|
||||
@@ -48,7 +48,7 @@ class _GridItem extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
color: colors.foregroundColor,
|
||||
fontSize: 25,
|
||||
).merge(japaneseFont.textStyle),
|
||||
).merge(japaneseFont.value.textStyle),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -178,7 +178,7 @@ class _KanjiRadicalSearchState extends State<KanjiRadicalSearch> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Choose by radicals')),
|
||||
body: DefaultTextStyle.merge(
|
||||
style: japaneseFont.textStyle,
|
||||
style: japaneseFont.value.textStyle,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
|
||||
@@ -47,7 +47,7 @@ class _WordSearchResultPageState extends State<WordSearchResultPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (!incognitoModeEnabled && !addedToDatabase) {
|
||||
if (!incognitoModeEnabled.value && !addedToDatabase) {
|
||||
GetIt.instance
|
||||
.get<Database>()
|
||||
.historyEntryInsertWord(widget.searchTerm)
|
||||
@@ -87,7 +87,7 @@ class _WordSearchResultPageState extends State<WordSearchResultPage> {
|
||||
appBar: AppBar(
|
||||
title: Text('"${widget.searchTerm}"'),
|
||||
actions: [
|
||||
if (incognitoModeEnabled)
|
||||
if (incognitoModeEnabled.value)
|
||||
IconButton(
|
||||
icon: const Icon(Mdi.incognito),
|
||||
onPressed: () =>
|
||||
|
||||
@@ -74,12 +74,12 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
|
||||
Future<void> changeFont(BuildContext context) async {
|
||||
final int? i = await _chooseFromList(
|
||||
list: [for (final font in JapaneseFont.values) font.name],
|
||||
chosen: japaneseFont.index,
|
||||
list: [for (final font in JapaneseFontChoice.values) font.name],
|
||||
chosen: japaneseFont.value.index,
|
||||
)(context);
|
||||
if (i != null) {
|
||||
setState(() {
|
||||
japaneseFont = JapaneseFont.values[i];
|
||||
japaneseFont.value = JapaneseFontChoice.values[i];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -91,14 +91,14 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
if (!context.mounted) return;
|
||||
final int? i = await _chooseFromList(
|
||||
list: ['None', ...libraryLists.map((e) => e.name)],
|
||||
chosen: quickAddLibraryList == null
|
||||
chosen: quickAddLibraryList.value == null
|
||||
? 0
|
||||
: libraryLists.indexWhere((l) => l.name == quickAddLibraryList) + 1,
|
||||
: libraryLists.indexWhere((l) => l.name == quickAddLibraryList.value) + 1,
|
||||
title: 'Choose library for quick add',
|
||||
)(context);
|
||||
if (i != null) {
|
||||
setState(() {
|
||||
quickAddLibraryList = i == 0 ? null : libraryLists[i - 1].name;
|
||||
quickAddLibraryList.value = i == 0 ? null : libraryLists[i - 1].name;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -211,15 +211,15 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
'Display romaji instead of kana for word readings',
|
||||
),
|
||||
leading: const Icon(Mdi.alphabetical),
|
||||
onToggle: (b) => setState(() => romajiEnabled = b),
|
||||
initialValue: romajiEnabled,
|
||||
onToggle: (b) => setState(() => romajiEnabled.value = b),
|
||||
initialValue: romajiEnabled.value,
|
||||
activeSwitchColor: mugitenWheatBackground,
|
||||
),
|
||||
SettingsTile(
|
||||
title: const Text('Japanese font'),
|
||||
leading: const Icon(Icons.format_size),
|
||||
onPressed: changeFont,
|
||||
trailing: Text(japaneseFont.name),
|
||||
trailing: Text(japaneseFont.value.name),
|
||||
// subtitle:
|
||||
// 'Which font to use for japanese text. This might be useful if your phone shows kanji with a Chinese font.',
|
||||
// subtitleMaxLines: 3,
|
||||
@@ -228,7 +228,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
title: const Text('Quick Add Library List'),
|
||||
leading: const Icon(Icons.bookmark),
|
||||
onPressed: changeQuickAddLibraryList,
|
||||
trailing: Text(quickAddLibraryList ?? 'None'),
|
||||
trailing: Text(quickAddLibraryList.value ?? 'None'),
|
||||
description: const Text(
|
||||
'Which library to add words on double tapping in search results',
|
||||
),
|
||||
@@ -243,21 +243,21 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
description: const Text('Let theme be determined by system'),
|
||||
leading: const Icon(Icons.brightness_auto),
|
||||
onToggle: (b) {
|
||||
setState(() => autoThemeEnabled = b);
|
||||
setState(() => autoThemeEnabled.value = b);
|
||||
GetIt.instance.get<ThemeController>().updateThemeMode();
|
||||
},
|
||||
initialValue: autoThemeEnabled,
|
||||
initialValue: autoThemeEnabled.value,
|
||||
activeSwitchColor: mugitenWheatBackground,
|
||||
),
|
||||
SettingsTile.switchTile(
|
||||
title: const Text('Dark Theme'),
|
||||
leading: const Icon(Icons.dark_mode),
|
||||
onToggle: (b) {
|
||||
setState(() => darkThemeEnabled = b);
|
||||
setState(() => darkThemeEnabled.value = b);
|
||||
GetIt.instance.get<ThemeController>().updateThemeMode();
|
||||
},
|
||||
initialValue: darkThemeEnabled,
|
||||
enabled: !autoThemeEnabled,
|
||||
initialValue: darkThemeEnabled.value,
|
||||
enabled: !autoThemeEnabled.value,
|
||||
activeSwitchColor: mugitenWheatBackground,
|
||||
),
|
||||
],
|
||||
@@ -302,8 +302,8 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
description: const Text(
|
||||
'Useful for reviewing search history without creating clutter',
|
||||
),
|
||||
onToggle: (b) => setState(() => incognitoModeEnabled = b),
|
||||
initialValue: incognitoModeEnabled,
|
||||
onToggle: (b) => setState(() => incognitoModeEnabled.value = b),
|
||||
initialValue: incognitoModeEnabled.value,
|
||||
activeSwitchColor: mugitenWheatBackground,
|
||||
),
|
||||
SettingsTile.switchTile(
|
||||
@@ -312,8 +312,8 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
description: const Text(
|
||||
'Useful if you keep accidentally activating system gestures',
|
||||
),
|
||||
onToggle: (b) => setState(() => reduceKanjiDrawingBoardSize = b),
|
||||
initialValue: reduceKanjiDrawingBoardSize,
|
||||
onToggle: (b) => setState(() => reduceKanjiDrawingBoardSize.value = b),
|
||||
initialValue: reduceKanjiDrawingBoardSize.value,
|
||||
activeSwitchColor: mugitenWheatBackground,
|
||||
),
|
||||
SettingsTile(
|
||||
|
||||
@@ -5,7 +5,128 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
final SharedPreferences _prefs = GetIt.instance.get<SharedPreferences>();
|
||||
|
||||
enum JapaneseFont {
|
||||
abstract interface class StringifySharedPrefItem<T> {
|
||||
String serializeSetting(T value) => value.toString();
|
||||
T deserializeSetting(String s);
|
||||
}
|
||||
|
||||
abstract class SharedPrefItem<T> extends ValueNotifier<T> {
|
||||
final String key;
|
||||
final T defaultValue;
|
||||
|
||||
SharedPrefItem(this.key, this.defaultValue)
|
||||
: super(_getValue<T>(key, defaultValue));
|
||||
|
||||
static T _getValue<T>(String key, T defaultValue) {
|
||||
Object? result = _prefs.get(key);
|
||||
|
||||
switch (defaultValue) {
|
||||
case StringifySharedPrefItem():
|
||||
if (result is String) {
|
||||
try {
|
||||
result = (defaultValue as StringifySharedPrefItem)
|
||||
.deserializeSetting(result);
|
||||
} catch (e) {
|
||||
// If deserialization fails, reset to default value.
|
||||
_setValue<T>(key, defaultValue);
|
||||
result = defaultValue;
|
||||
}
|
||||
} else {
|
||||
// If the stored value is not a String, reset to default value.
|
||||
_setValue<T>(key, defaultValue);
|
||||
result = defaultValue;
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return result as T;
|
||||
}
|
||||
|
||||
static void _setValue<T>(String key, T value) {
|
||||
switch (value) {
|
||||
case null:
|
||||
_prefs.remove(key);
|
||||
case bool():
|
||||
_prefs.setBool(key, value);
|
||||
case int():
|
||||
_prefs.setInt(key, value);
|
||||
case double():
|
||||
_prefs.setDouble(key, value);
|
||||
case String():
|
||||
_prefs.setString(key, value);
|
||||
case List<String>():
|
||||
_prefs.setStringList(key, value);
|
||||
case StringifySharedPrefItem():
|
||||
_prefs.setString(
|
||||
key,
|
||||
(value as StringifySharedPrefItem).serializeSetting(value),
|
||||
);
|
||||
default:
|
||||
throw Exception(
|
||||
'Unsupported type for SharedPrefItem: ${value.runtimeType}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
T get value => _getValue<T>(key, defaultValue);
|
||||
|
||||
@override
|
||||
set value(T newValue) {
|
||||
final oldValue = _getValue<T>(key, defaultValue);
|
||||
_setValue<T>(key, newValue);
|
||||
|
||||
if (oldValue != newValue) {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to save search history and other data to the database.
|
||||
class IncognitoModeEnabled extends SharedPrefItem<bool> {
|
||||
IncognitoModeEnabled() : super('incognitoModeEnabled', false);
|
||||
}
|
||||
|
||||
final incognitoModeEnabled = IncognitoModeEnabled();
|
||||
|
||||
/// Whether to show romaji readings in the word search results and elsewhere.
|
||||
class RomajiEnabled extends SharedPrefItem<bool> {
|
||||
RomajiEnabled() : super('romajiEnabled', false);
|
||||
}
|
||||
|
||||
final romajiEnabled = RomajiEnabled();
|
||||
|
||||
/// Whether to use a dark theme.
|
||||
class DarkThemeEnabled extends SharedPrefItem<bool> {
|
||||
DarkThemeEnabled() : super('darkThemeEnabled', false);
|
||||
}
|
||||
|
||||
final darkThemeEnabled = DarkThemeEnabled();
|
||||
|
||||
/// Whether to let the system control which theme to use.
|
||||
class AutoThemeEnabled extends SharedPrefItem<bool> {
|
||||
AutoThemeEnabled() : super('autoThemeEnabled', true);
|
||||
}
|
||||
|
||||
final autoThemeEnabled = AutoThemeEnabled();
|
||||
|
||||
/// Whether to reduce the size of the kanji drawing board.
|
||||
///
|
||||
/// This is a workaround for an issue where it's easy to activate the 'go back' gesture when
|
||||
/// drawing a little too close to the edge of the screen.
|
||||
class ReduceKanjiDrawingBoardSize extends SharedPrefItem<bool> {
|
||||
ReduceKanjiDrawingBoardSize() : super('reduceKanjiDrawingBoardSize', false);
|
||||
}
|
||||
|
||||
final reduceKanjiDrawingBoardSize = ReduceKanjiDrawingBoardSize();
|
||||
|
||||
class QuickAddLibraryList extends SharedPrefItem<String?> {
|
||||
QuickAddLibraryList() : super('quickAddLibraryList', null);
|
||||
}
|
||||
|
||||
final quickAddLibraryList = QuickAddLibraryList();
|
||||
|
||||
enum JapaneseFontChoice implements StringifySharedPrefItem<JapaneseFontChoice> {
|
||||
system,
|
||||
droidSansJapanese,
|
||||
hinaMincho,
|
||||
@@ -16,87 +137,52 @@ enum JapaneseFont {
|
||||
mPlusRounded1c,
|
||||
notoSansJapanese,
|
||||
notoSerifJapanese,
|
||||
zenKurenaido,
|
||||
}
|
||||
zenKurenaido;
|
||||
|
||||
extension Methods on JapaneseFont {
|
||||
TextStyle get textStyle {
|
||||
switch (this) {
|
||||
case JapaneseFont.droidSansJapanese:
|
||||
TextStyle(fontFamily: 'Droid Sans Japanese');
|
||||
case JapaneseFont.notoSansJapanese:
|
||||
return GoogleFonts.notoSansJp();
|
||||
case JapaneseFont.notoSerifJapanese:
|
||||
return GoogleFonts.notoSerifJp();
|
||||
case JapaneseFont.hinaMincho:
|
||||
return GoogleFonts.hinaMincho();
|
||||
case JapaneseFont.ibmPlexSansJP:
|
||||
return GoogleFonts.ibmPlexSansJp();
|
||||
case JapaneseFont.kleeOne:
|
||||
return GoogleFonts.kleeOne();
|
||||
case JapaneseFont.kosugi:
|
||||
return GoogleFonts.kosugi();
|
||||
case JapaneseFont.mPlus2:
|
||||
return GoogleFonts.mPlus2();
|
||||
case JapaneseFont.mPlusRounded1c:
|
||||
return GoogleFonts.mPlusRounded1c();
|
||||
case JapaneseFont.zenKurenaido:
|
||||
return GoogleFonts.zenTokyoZoo();
|
||||
case JapaneseFont.system:
|
||||
}
|
||||
|
||||
return const TextStyle();
|
||||
}
|
||||
|
||||
String get name => switch (this) {
|
||||
JapaneseFont.system => 'System Default',
|
||||
JapaneseFont.droidSansJapanese => 'Droid Sans Japanese',
|
||||
JapaneseFont.notoSansJapanese => 'Noto Sans Japanese',
|
||||
JapaneseFont.notoSerifJapanese => 'Noto Serif Japanese',
|
||||
JapaneseFont.hinaMincho => 'Hina Mincho',
|
||||
JapaneseFont.ibmPlexSansJP => 'IBM Plex Sans JP',
|
||||
JapaneseFont.kleeOne => 'Klee One',
|
||||
JapaneseFont.kosugi => 'Kosugi',
|
||||
JapaneseFont.mPlus2 => 'M PLUS 2',
|
||||
JapaneseFont.mPlusRounded1c => 'M PLUS Rounded 1c',
|
||||
JapaneseFont.zenKurenaido => 'Zen Kurenaido',
|
||||
TextStyle get textStyle => switch (this) {
|
||||
JapaneseFontChoice.droidSansJapanese => const TextStyle(
|
||||
fontFamily: 'Droid Sans Japanese',
|
||||
),
|
||||
JapaneseFontChoice.notoSansJapanese => GoogleFonts.notoSansJp(),
|
||||
JapaneseFontChoice.notoSerifJapanese => GoogleFonts.notoSerifJp(),
|
||||
JapaneseFontChoice.hinaMincho => GoogleFonts.hinaMincho(),
|
||||
JapaneseFontChoice.ibmPlexSansJP => GoogleFonts.ibmPlexSansJp(),
|
||||
JapaneseFontChoice.kleeOne => GoogleFonts.kleeOne(),
|
||||
JapaneseFontChoice.kosugi => GoogleFonts.kosugi(),
|
||||
JapaneseFontChoice.mPlus2 => GoogleFonts.mPlus2(),
|
||||
JapaneseFontChoice.mPlusRounded1c => GoogleFonts.mPlusRounded1c(),
|
||||
JapaneseFontChoice.zenKurenaido => GoogleFonts.zenTokyoZoo(),
|
||||
JapaneseFontChoice.system => const TextStyle(),
|
||||
};
|
||||
|
||||
static Map<JapaneseFontChoice, String> get _fontToName => {
|
||||
JapaneseFontChoice.system: 'System Default',
|
||||
JapaneseFontChoice.droidSansJapanese: 'Droid Sans Japanese',
|
||||
JapaneseFontChoice.notoSansJapanese: 'Noto Sans Japanese',
|
||||
JapaneseFontChoice.notoSerifJapanese: 'Noto Serif Japanese',
|
||||
JapaneseFontChoice.hinaMincho: 'Hina Mincho',
|
||||
JapaneseFontChoice.ibmPlexSansJP: 'IBM Plex Sans JP',
|
||||
JapaneseFontChoice.kleeOne: 'Klee One',
|
||||
JapaneseFontChoice.kosugi: 'Kosugi',
|
||||
JapaneseFontChoice.mPlus2: 'M PLUS 2',
|
||||
JapaneseFontChoice.mPlusRounded1c: 'M PLUS Rounded 1c',
|
||||
JapaneseFontChoice.zenKurenaido: 'Zen Kurenaido',
|
||||
};
|
||||
|
||||
static Map<String, JapaneseFontChoice> get _nameToFont =>
|
||||
_fontToName.map((k, v) => MapEntry(v, k));
|
||||
|
||||
String get name => _fontToName[this]!;
|
||||
|
||||
@override
|
||||
String serializeSetting(JapaneseFontChoice value) => _fontToName[value]!;
|
||||
|
||||
@override
|
||||
JapaneseFontChoice deserializeSetting(String s) => _nameToFont[s]!;
|
||||
}
|
||||
|
||||
const Map<String, dynamic> _defaults = {
|
||||
'incognitoModeEnabled': false,
|
||||
'romajiEnabled': false,
|
||||
'darkThemeEnabled': false,
|
||||
'autoThemeEnabled': true,
|
||||
'japaneseFont': JapaneseFont.droidSansJapanese,
|
||||
'reduceKanjiDrawingBoardSize': false,
|
||||
'quickAddLibraryList': null,
|
||||
};
|
||||
|
||||
bool _getSettingOrDefault(String settingName) =>
|
||||
_prefs.getBool(settingName) ?? _defaults[settingName];
|
||||
|
||||
bool get incognitoModeEnabled => _getSettingOrDefault('incognitoModeEnabled');
|
||||
bool get romajiEnabled => _getSettingOrDefault('romajiEnabled');
|
||||
bool get darkThemeEnabled => _getSettingOrDefault('darkThemeEnabled');
|
||||
bool get autoThemeEnabled => _getSettingOrDefault('autoThemeEnabled');
|
||||
bool get reduceKanjiDrawingBoardSize =>
|
||||
_getSettingOrDefault('reduceKanjiDrawingBoardSize');
|
||||
JapaneseFont get japaneseFont {
|
||||
final int? i = _prefs.getInt('japaneseFont');
|
||||
return (i != null) ? JapaneseFont.values[i] : _defaults['japaneseFont'];
|
||||
class JapaneseFont extends SharedPrefItem<JapaneseFontChoice> {
|
||||
JapaneseFont() : super('japaneseFont', JapaneseFontChoice.droidSansJapanese);
|
||||
}
|
||||
|
||||
String? get quickAddLibraryList =>
|
||||
_prefs.getString('quickAddLibraryList') ?? _defaults['quickAddLibraryList'];
|
||||
|
||||
set incognitoModeEnabled(bool b) => _prefs.setBool('incognitoModeEnabled', b);
|
||||
set romajiEnabled(bool b) => _prefs.setBool('romajiEnabled', b);
|
||||
set darkThemeEnabled(bool b) => _prefs.setBool('darkThemeEnabled', b);
|
||||
set autoThemeEnabled(bool b) => _prefs.setBool('autoThemeEnabled', b);
|
||||
set reduceKanjiDrawingBoardSize(bool b) =>
|
||||
_prefs.setBool('reduceKanjiDrawingBoardSize', b);
|
||||
set japaneseFont(JapaneseFont jf) => _prefs.setInt('japaneseFont', jf.index);
|
||||
set quickAddLibraryList(String? s) => s == null
|
||||
? _prefs.remove('quickAddLibraryList')
|
||||
: _prefs.setString('quickAddLibraryList', s);
|
||||
final japaneseFont = JapaneseFont();
|
||||
|
||||
@@ -334,10 +334,10 @@ class ThemeController {
|
||||
|
||||
factory ThemeController.create() {
|
||||
AppThemeMode initialMode;
|
||||
if (autoThemeEnabled) {
|
||||
if (autoThemeEnabled.value) {
|
||||
initialMode = AppThemeMode.system;
|
||||
} else {
|
||||
initialMode = darkThemeEnabled ? AppThemeMode.dark : AppThemeMode.light;
|
||||
initialMode = darkThemeEnabled.value ? AppThemeMode.dark : AppThemeMode.light;
|
||||
}
|
||||
|
||||
return ThemeController(initialMode);
|
||||
@@ -346,24 +346,24 @@ class ThemeController {
|
||||
void setThemeMode(AppThemeMode mode) {
|
||||
if (mode != themeMode.value) {
|
||||
if (mode == AppThemeMode.system) {
|
||||
autoThemeEnabled = true;
|
||||
autoThemeEnabled.value = true;
|
||||
} else {
|
||||
autoThemeEnabled = false;
|
||||
darkThemeEnabled = mode == AppThemeMode.dark;
|
||||
autoThemeEnabled.value = false;
|
||||
darkThemeEnabled.value = mode == AppThemeMode.dark;
|
||||
}
|
||||
themeMode.value = mode;
|
||||
}
|
||||
}
|
||||
|
||||
void updateThemeMode() {
|
||||
if (autoThemeEnabled) {
|
||||
if (autoThemeEnabled.value) {
|
||||
final platformBrightness =
|
||||
WidgetsBinding.instance.platformDispatcher.platformBrightness;
|
||||
themeMode.value = platformBrightness == Brightness.dark
|
||||
? AppThemeMode.dark
|
||||
: AppThemeMode.light;
|
||||
} else {
|
||||
themeMode.value = darkThemeEnabled
|
||||
themeMode.value = darkThemeEnabled.value
|
||||
? AppThemeMode.dark
|
||||
: AppThemeMode.light;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user