diff --git a/firka/lib/helpers/db/models/app_settings_model.g.dart b/firka/lib/helpers/db/models/app_settings_model.g.dart index 2a4cb01..c8e3a80 100644 --- a/firka/lib/helpers/db/models/app_settings_model.g.dart +++ b/firka/lib/helpers/db/models/app_settings_model.g.dart @@ -26,6 +26,16 @@ const AppSettingsModelSchema = CollectionSchema( id: 1, name: r'valueDouble', type: IsarType.double, + ), + r'valueIndex': PropertySchema( + id: 2, + name: r'valueIndex', + type: IsarType.long, + ), + r'valueString': PropertySchema( + id: 3, + name: r'valueString', + type: IsarType.string, ) }, estimateSize: _appSettingsModelEstimateSize, @@ -48,6 +58,12 @@ int _appSettingsModelEstimateSize( Map> allOffsets, ) { var bytesCount = offsets.last; + { + final value = object.valueString; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } return bytesCount; } @@ -59,6 +75,8 @@ void _appSettingsModelSerialize( ) { writer.writeBool(offsets[0], object.valueBool); writer.writeDouble(offsets[1], object.valueDouble); + writer.writeLong(offsets[2], object.valueIndex); + writer.writeString(offsets[3], object.valueString); } AppSettingsModel _appSettingsModelDeserialize( @@ -71,6 +89,8 @@ AppSettingsModel _appSettingsModelDeserialize( object.id = id; object.valueBool = reader.readBoolOrNull(offsets[0]); object.valueDouble = reader.readDoubleOrNull(offsets[1]); + object.valueIndex = reader.readLongOrNull(offsets[2]); + object.valueString = reader.readStringOrNull(offsets[3]); return object; } @@ -85,6 +105,10 @@ P _appSettingsModelDeserializeProp

( return (reader.readBoolOrNull(offset)) as P; case 1: return (reader.readDoubleOrNull(offset)) as P; + case 2: + return (reader.readLongOrNull(offset)) as P; + case 3: + return (reader.readStringOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); } @@ -369,6 +393,234 @@ extension AppSettingsModelQueryFilter )); }); } + + QueryBuilder + valueIndexIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'valueIndex', + )); + }); + } + + QueryBuilder + valueIndexIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'valueIndex', + )); + }); + } + + QueryBuilder + valueIndexEqualTo(int? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'valueIndex', + value: value, + )); + }); + } + + QueryBuilder + valueIndexGreaterThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'valueIndex', + value: value, + )); + }); + } + + QueryBuilder + valueIndexLessThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'valueIndex', + value: value, + )); + }); + } + + QueryBuilder + valueIndexBetween( + int? lower, + int? upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'valueIndex', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + valueStringIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'valueString', + )); + }); + } + + QueryBuilder + valueStringIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'valueString', + )); + }); + } + + QueryBuilder + valueStringEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'valueString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'valueString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'valueString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'valueString', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'valueString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'valueString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'valueString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'valueString', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + valueStringIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'valueString', + value: '', + )); + }); + } + + QueryBuilder + valueStringIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'valueString', + value: '', + )); + }); + } } extension AppSettingsModelQueryObject @@ -406,6 +658,34 @@ extension AppSettingsModelQuerySortBy return query.addSortBy(r'valueDouble', Sort.desc); }); } + + QueryBuilder + sortByValueIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueIndex', Sort.asc); + }); + } + + QueryBuilder + sortByValueIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueIndex', Sort.desc); + }); + } + + QueryBuilder + sortByValueString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueString', Sort.asc); + }); + } + + QueryBuilder + sortByValueStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueString', Sort.desc); + }); + } } extension AppSettingsModelQuerySortThenBy @@ -450,6 +730,34 @@ extension AppSettingsModelQuerySortThenBy return query.addSortBy(r'valueDouble', Sort.desc); }); } + + QueryBuilder + thenByValueIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueIndex', Sort.asc); + }); + } + + QueryBuilder + thenByValueIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueIndex', Sort.desc); + }); + } + + QueryBuilder + thenByValueString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueString', Sort.asc); + }); + } + + QueryBuilder + thenByValueStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'valueString', Sort.desc); + }); + } } extension AppSettingsModelQueryWhereDistinct @@ -467,6 +775,20 @@ extension AppSettingsModelQueryWhereDistinct return query.addDistinctBy(r'valueDouble'); }); } + + QueryBuilder + distinctByValueIndex() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'valueIndex'); + }); + } + + QueryBuilder + distinctByValueString({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'valueString', caseSensitive: caseSensitive); + }); + } } extension AppSettingsModelQueryProperty @@ -489,4 +811,17 @@ extension AppSettingsModelQueryProperty return query.addPropertyName(r'valueDouble'); }); } + + QueryBuilder valueIndexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'valueIndex'); + }); + } + + QueryBuilder + valueStringProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'valueString'); + }); + } } diff --git a/firka/lib/helpers/settings/setting.dart b/firka/lib/helpers/settings/setting.dart index 8afdd8e..770919c 100644 --- a/firka/lib/helpers/settings/setting.dart +++ b/firka/lib/helpers/settings/setting.dart @@ -5,14 +5,14 @@ import 'package:firka/ui/widget/firka_icon.dart'; import 'package:isar/isar.dart'; import 'package:majesticons_flutter/majesticons_flutter.dart'; -const bellRing = 1_001; -const rounding1 = 1_002; -const rounding2 = 1_003; -const rounding3 = 1_004; -const rounding4 = 1_005; -const classAvgOnGraph = 1_006; -const leftHandedMode = 1_007; -const language = 1_008; +const bellRing = 1001; +const rounding1 = 1002; +const rounding2 = 1003; +const rounding3 = 1004; +const rounding4 = 1005; +const classAvgOnGraph = 1006; +const leftHandedMode = 1007; +const language = 1008; class SettingsStore { LinkedHashMap items = LinkedHashMap.of({}); @@ -81,13 +81,13 @@ class SettingsStore { Future save(IsarCollection model) async { for (var item in items.values) { - item.save(model); + await item.save(model); } } Future load(IsarCollection model) async { for (var item in items.values) { - item.load(model); + await item.load(model); } } } @@ -97,6 +97,10 @@ extension SettingExt on LinkedHashMap { return (this[key] as SettingsGroup).children; } + LinkedHashMap subGroup(String key) { + return (this[key] as SettingsSubGroup).children; + } + String string(String key) { return (this[key] as SettingsString).value; } @@ -129,9 +133,9 @@ class SettingsItem { SettingsItem(this.key, this.iconType, this.iconData); - void save(IsarCollection model) {} + Future save(IsarCollection model) async {} - void load(IsarCollection model) {} + Future load(IsarCollection model) async {} } class SettingsGroup implements SettingsItem { @@ -146,16 +150,16 @@ class SettingsGroup implements SettingsItem { SettingsGroup(this.key, this.children); @override - void load(IsarCollection model) { + Future load(IsarCollection model) async { for (var item in children.values) { - item.load(model); + await item.load(model); } } @override - void save(IsarCollection model) { + Future save(IsarCollection model) async { for (var item in children.values) { - item.save(model); + await item.save(model); } } } @@ -174,16 +178,16 @@ class SettingsSubGroup implements SettingsItem { this.key, this.iconType, this.iconData, this.title, this.children); @override - void load(IsarCollection model) { + Future load(IsarCollection model) async { for (var item in children.values) { - item.load(model); + await item.load(model); } } @override - void save(IsarCollection model) { + Future save(IsarCollection model) async { for (var item in children.values) { - item.save(model); + await item.save(model); } } } @@ -200,10 +204,10 @@ class SettingsPadding implements SettingsItem { SettingsPadding(this.key, this.padding); @override - void load(IsarCollection model) {} + Future load(IsarCollection model) async {} @override - void save(IsarCollection model) {} + Future save(IsarCollection model) async {} } class SettingsHeader implements SettingsItem { @@ -218,10 +222,10 @@ class SettingsHeader implements SettingsItem { SettingsHeader(this.key, this.title); @override - void load(IsarCollection model) {} + Future load(IsarCollection model) async {} @override - void save(IsarCollection model) {} + Future save(IsarCollection model) async {} } class SettingsHeaderSmall implements SettingsItem { @@ -236,10 +240,10 @@ class SettingsHeaderSmall implements SettingsItem { SettingsHeaderSmall(this.key, this.title); @override - void load(IsarCollection model) {} + Future load(IsarCollection model) async {} @override - void save(IsarCollection model) {} + Future save(IsarCollection model) async {} } class SettingsSubtitle implements SettingsItem { @@ -254,10 +258,10 @@ class SettingsSubtitle implements SettingsItem { SettingsSubtitle(this.key, this.title); @override - void load(IsarCollection model) {} + Future load(IsarCollection model) async {} @override - void save(IsarCollection model) {} + Future save(IsarCollection model) async {} } class SettingsBoolean implements SettingsItem { @@ -275,8 +279,8 @@ class SettingsBoolean implements SettingsItem { this.key, this.iconType, this.iconData, this.title, this.defaultValue); @override - void load(IsarCollection model) { - var v = model.getSync(key); + Future load(IsarCollection model) async { + var v = await model.get(key); if (v == null || v.valueBool == null) { value = defaultValue; } else { @@ -285,12 +289,12 @@ class SettingsBoolean implements SettingsItem { } @override - void save(IsarCollection model) { + Future save(IsarCollection model) async { var v = AppSettingsModel(); v.id = key; v.valueBool = value; - model.put(v); + await model.put(v); } } @@ -309,22 +313,22 @@ class SettingsItemsRadio implements SettingsItem { this.key, this.iconType, this.iconData, this.values, this.defaultIndex); @override - void load(IsarCollection model) { - var v = model.getSync(key); + Future load(IsarCollection model) async { + var v = await model.get(key); if (v == null || v.valueIndex == null) { - activeIndex = v!.valueIndex!; - } else { activeIndex = defaultIndex; + } else { + activeIndex = v.valueIndex!; } } @override - void save(IsarCollection model) { + Future save(IsarCollection model) async { var v = AppSettingsModel(); v.id = key; v.valueIndex = activeIndex; - model.put(v); + await model.put(v); } } @@ -343,8 +347,8 @@ class SettingsDouble implements SettingsItem { this.key, this.iconType, this.iconData, this.title, this.defaultValue); @override - void load(IsarCollection model) { - var v = model.getSync(key); + Future load(IsarCollection model) async { + var v = await model.get(key); if (v == null || v.valueDouble == null) { value = defaultValue; } else { @@ -353,12 +357,12 @@ class SettingsDouble implements SettingsItem { } @override - void save(IsarCollection model) { + Future save(IsarCollection model) async { var v = AppSettingsModel(); v.id = key; v.valueDouble = value; - model.put(v); + await model.put(v); } } @@ -377,8 +381,8 @@ class SettingsString implements SettingsItem { this.key, this.iconType, this.iconData, this.title, this.defaultValue); @override - void load(IsarCollection model) { - var v = model.getSync(key); + Future load(IsarCollection model) async { + var v = await model.get(key); if (v == null || v.valueString == null) { value = defaultValue; } else { @@ -387,11 +391,11 @@ class SettingsString implements SettingsItem { } @override - void save(IsarCollection model) { + Future save(IsarCollection model) async { var v = AppSettingsModel(); v.id = key; v.valueString = value; - model.put(v); + await model.put(v); } } diff --git a/firka/lib/main.dart b/firka/lib/main.dart index 2f117f3..2ab571a 100644 --- a/firka/lib/main.dart +++ b/firka/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io'; +import 'dart:ui' as ui; import 'package:dio/dio.dart'; import 'package:firka/helpers/api/client/kreta_client.dart'; @@ -28,6 +29,8 @@ import 'package:watch_connectivity/watch_connectivity.dart'; import 'helpers/db/models/homework_cache_model.dart'; import 'l10n/app_localizations.dart'; +import 'l10n/app_localizations_de.dart'; +import 'l10n/app_localizations_en.dart'; Isar? isarInit; final GlobalKey navigatorKey = GlobalKey(); @@ -86,6 +89,34 @@ Future initializeApp() async { l10n: AppLocalizationsHu(), ); + await init.settings.load(init.isar.appSettingsModels); + switch ((init.settings.group("settings").subGroup("application")["language"] + as SettingsItemsRadio) + .activeIndex) { + case 1: // hu + init.l10n = AppLocalizationsHu(); + break; + case 2: // en + init.l10n = AppLocalizationsEn(); + break; + case 3: // de + init.l10n = AppLocalizationsDe(); + break; + default: // auto + switch (ui.window.locale.languageCode) { + case 'hu': + init.l10n = AppLocalizationsHu(); + break; + case 'en': + init.l10n = AppLocalizationsEn(); + break; + case 'de': + init.l10n = AppLocalizationsDe(); + break; + } + break; + } + resetOldTimeTableCache(isar); resetOldHomeworkCache(isar); diff --git a/firka/lib/ui/phone/screens/settings/settings_screen.dart b/firka/lib/ui/phone/screens/settings/settings_screen.dart index 597972f..355dd5c 100644 --- a/firka/lib/ui/phone/screens/settings/settings_screen.dart +++ b/firka/lib/ui/phone/screens/settings/settings_screen.dart @@ -120,13 +120,13 @@ class _SettingsScreenState extends State { Switch( value: item.value, activeColor: appStyle.colors.accent, - onChanged: (v) { + onChanged: (v) async { setState(() { item.value = v; }); - widget.data.isar.writeTxn(() async { - item.save(widget.data.isar.appSettingsModels); + await widget.data.isar.writeTxn(() async { + await item.save(widget.data.isar.appSettingsModels); }); }) ], @@ -147,14 +147,15 @@ class _SettingsScreenState extends State { (Set states) { return appStyle.colors.secondary; }), - onChanged: (_) { + onChanged: (_) async { setState(() { item.activeIndex = i; }); - widget.data.isar.writeTxn(() async { - item.save(widget.data.isar.appSettingsModels); + await widget.data.isar.writeTxn(() async { + await item.save(widget.data.isar.appSettingsModels); }); + debugPrint('Settings saved'); }) ])); }