From 153197d900b378d0500ab5b8bb4a3c650d13e3a3 Mon Sep 17 00:00:00 2001 From: realth000 Date: Fri, 4 Oct 2024 23:03:52 +0800 Subject: [PATCH] feat(*): saving more data types and allow disable window configs * Allow saving the following data types into database: * DateTime: Before this commit, only part of `DateTime` support. * Offset. * Size. * Allow disable `window_manager` features usage by adding cmdline arg `--no-window-configs`. * This features is useful when want to disable those related fetures such as in a tiling window manager environment or window became. missing due to `setPosition` to a out-of-bound position after monitor layout changed, which will add in near future. * When applying this cmdline arg, window title, window postion and window size use default values and not remembered. * This disabling feature (as well as window fetures) only available on desktop platforms. --- lib/app.dart | 38 +++++++++++++-- lib/cmd.dart | 35 ++++++++++++++ lib/features/settings/bloc/settings_bloc.dart | 46 +++++-------------- .../repositories/settings_repository.dart | 10 ++++ lib/features/settings/view/settings_page.dart | 38 +++++++-------- lib/instance.dart | 8 ++++ lib/main.dart | 10 ++-- .../models/convertable/convertable.dart | 7 +++ .../models/convertable/offset.dart | 22 +++++++++ .../models/convertable/size.dart | 22 +++++++++ .../models/database/dao/cookie.dart | 7 +++ .../models/database/dao/dao.dart | 2 + .../models/database/dao/settings.dart | 36 ++++++++++++++- .../models/database/database.dart | 2 +- .../models/database/schema/cookie.dart | 5 +- .../models/database/schema/schema.dart | 1 + .../models/database/schema/settings.dart | 9 +++- .../storage_provider/storage_provider.dart | 25 ++++++++++ lib/utils/window_configs.dart | 15 ++++++ pubspec.lock | 2 +- pubspec.yaml | 1 + 21 files changed, 275 insertions(+), 66 deletions(-) create mode 100644 lib/cmd.dart create mode 100644 lib/shared/providers/storage_provider/models/convertable/convertable.dart create mode 100644 lib/shared/providers/storage_provider/models/convertable/offset.dart create mode 100644 lib/shared/providers/storage_provider/models/convertable/size.dart create mode 100644 lib/utils/window_configs.dart diff --git a/lib/app.dart b/lib/app.dart index 313a5d6b..e08ff75e 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -22,9 +22,10 @@ import 'package:tsdm_client/shared/providers/storage_provider/storage_provider.d import 'package:tsdm_client/shared/repositories/forum_home_repository/forum_home_repository.dart'; import 'package:tsdm_client/shared/repositories/fragments_repository/fragments_repository.dart'; import 'package:tsdm_client/themes/app_themes.dart'; +import 'package:window_manager/window_manager.dart'; /// Main app for tsdm_client. -class App extends StatelessWidget { +class App extends StatefulWidget { /// Constructor. const App(this.color, this.themeModeIndex, {super.key}); @@ -34,6 +35,23 @@ class App extends StatelessWidget { /// Initial theme mode index. final int themeModeIndex; + @override + State createState() => _AppState(); +} + +class _AppState extends State with WindowListener { + @override + void initState() { + super.initState(); + windowManager.addListener(this); + } + + @override + void dispose() { + windowManager.removeListener(this); + super.dispose(); + } + @override Widget build(BuildContext context) { return MultiRepositoryProvider( @@ -87,8 +105,8 @@ class App extends StatelessWidget { ], child: BlocProvider( create: (context) => ThemeCubit( - accentColor: color >= 0 ? Color(color) : null, - themeModeIndex: themeModeIndex, + accentColor: widget.color >= 0 ? Color(widget.color) : null, + themeModeIndex: widget.themeModeIndex, ), child: BlocBuilder( buildWhen: (prev, curr) => prev != curr, @@ -114,4 +132,18 @@ class App extends StatelessWidget { ), ); } + + @override + Future onWindowMove() async { + super.onWindowMove(); + final x = await windowManager.getPosition(); + debugPrint('>>> window moved to $x'); + } + + @override + Future onWindowResize() async { + super.onWindowResize(); + final x = await windowManager.getSize(); + debugPrint('>>> window size is $x'); + } } diff --git a/lib/cmd.dart b/lib/cmd.dart new file mode 100644 index 00000000..952d965b --- /dev/null +++ b/lib/cmd.dart @@ -0,0 +1,35 @@ +import 'package:args/args.dart'; +import 'package:tsdm_client/instance.dart'; + +/// All flags in cmdline. +abstract class Flags { + /// Disable window related configs, including window size, window title and + /// window position. + /// + /// Set to false if needed, as in recovery mode. + static const noWindowConfigs = 'no-window-configs'; +} + +/// Cmdline arguments parsed result. +class CmdArgs { + /// Constructor. + const CmdArgs({ + required this.noWindowConfigs, + }); + + /// Disable window related configs. + /// + /// Set to `true` will disable window_manager related features. + /// Also the **ONLY** way to disable it. + final bool noWindowConfigs; +} + +/// Parse cmdline [args] into global variable [cmdArgs]. +void parseCmdArgs(List args) { + final parser = ArgParser()..addFlag(Flags.noWindowConfigs, negatable: false); + + final argsResult = parser.parse(args); + cmdArgs = CmdArgs( + noWindowConfigs: argsResult.flag(Flags.noWindowConfigs), + ); +} diff --git a/lib/features/settings/bloc/settings_bloc.dart b/lib/features/settings/bloc/settings_bloc.dart index 41316312..6154aea6 100644 --- a/lib/features/settings/bloc/settings_bloc.dart +++ b/lib/features/settings/bloc/settings_bloc.dart @@ -11,11 +11,8 @@ import 'package:tsdm_client/utils/logger.dart'; part 'settings_bloc.mapper.dart'; part 'settings_event.dart'; - part 'settings_state.dart'; -const _scrollDebounceDuration = Duration(milliseconds: 300); - /// Emitter. typedef _Emitter = Emitter; @@ -42,39 +39,21 @@ class SettingsBloc extends Bloc with LoggerMixin { _settingsMapSub = _settingsRepository.settings .listen((settings) => add(SettingsMapChanged(settings))); - on(_onSettingsMapChanged); - on( - _onSettingsScrollOffsetChanged, - transformer: debounce(_scrollDebounceDuration), - ); on( (event, emit) async => switch (event) { final SettingsMapChanged e => _onSettingsMapChanged(e, emit), final SettingsScrollOffsetChanged e => _onSettingsScrollOffsetChanged(e, emit), - final SettingsValueChanged e => _onSettingsValueChanged( - e, - emit, - ), - final SettingsValueChanged e => _onSettingsValueChanged( - e, - emit, - ), - final SettingsValueChanged e => _onSettingsValueChanged( - e, - emit, - ), - final SettingsValueChanged e => _onSettingsValueChanged( - e, - emit, - ), - final SettingsValueChanged e => - _onSettingsValueChanged( - e, - emit, - ), - final SettingsValueChanged _ => - throw Exception('Unsupported settings change event type'), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => _onValueChanged(e), + final SettingsValueChanged e => + throw Exception('Unsupported settings change event ' + 'type(${e.runtimeType}): $e'), }, ); } @@ -98,11 +77,10 @@ class SettingsBloc extends Bloc with LoggerMixin { _fragmentsRepository.settingsPageScrollOffset = event.offset; } - Future _onSettingsValueChanged( + Future _onValueChanged( SettingsValueChanged event, - _Emitter emit, ) async { - debug('settings value changed: ${event.settings.name}: ${event.value}'); + debug('settings value changed: ${event.settings.name}<$T>: ${event.value}'); await _settingsRepository.setValue(event.settings, event.value); } diff --git a/lib/features/settings/repositories/settings_repository.dart b/lib/features/settings/repositories/settings_repository.dart index 790b3f32..971f6e82 100644 --- a/lib/features/settings/repositories/settings_repository.dart +++ b/lib/features/settings/repositories/settings_repository.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io' if (dart.libaray.js) 'package:web/web.dart'; +import 'dart:ui'; import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; @@ -28,6 +29,9 @@ extension _ExtractExt on List { double => v.doubleValue, String => v.stringValue, bool => v.boolValue, + DateTime => v.dateTimeValue, + Offset => v.offsetValue, + Size => v.sizeValue, _ => null, } ?? settings.defaultValue) as T; @@ -127,6 +131,9 @@ final class SettingsRepository with LoggerMixin { double => _storage.getDouble(name), String => _storage.getString(name), bool => _storage.getBool(name), + DateTime => _storage.getDateTime(name), + Offset => _storage.getOffset(name), + Size => _storage.getSize(name), _ => () { error('failed to getValue for key $key: unsupported type $T'); return null; @@ -156,6 +163,9 @@ final class SettingsRepository with LoggerMixin { double => _storage.saveDouble(name, value as double), String => _storage.saveString(name, value as String), bool => _storage.saveBool(name, value: value as bool), + DateTime => _storage.saveDateTime(name, value as DateTime), + Offset => _storage.saveOffset(name, value as Offset), + Size => _storage.saveSize(name, value as Size), final t => () { error('failed to save settings for key $key:' ' unsupported type in storage: $t'); diff --git a/lib/features/settings/view/settings_page.dart b/lib/features/settings/view/settings_page.dart index 28c80f87..f6261837 100644 --- a/lib/features/settings/view/settings_page.dart +++ b/lib/features/settings/view/settings_page.dart @@ -1,4 +1,5 @@ import 'package:collection/collection.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; @@ -23,11 +24,11 @@ import 'package:tsdm_client/shared/providers/checkin_provider/models/check_in_fe import 'package:tsdm_client/utils/platform.dart'; import 'package:tsdm_client/utils/show_bottom_sheet.dart'; import 'package:tsdm_client/utils/show_toast.dart'; +import 'package:tsdm_client/utils/window_configs.dart'; import 'package:tsdm_client/widgets/color_palette.dart'; import 'package:tsdm_client/widgets/section_list_tile.dart'; import 'package:tsdm_client/widgets/section_switch_list_tile.dart'; import 'package:tsdm_client/widgets/section_title_text.dart'; -import 'package:window_manager/window_manager.dart'; /// Settings page of the app. class SettingsPage extends StatefulWidget { @@ -165,10 +166,7 @@ class _SettingsPageState extends State { if (localeGroup.$2) { // Use system language. LocaleSettings.useDeviceLocale(); - if (isDesktop) { - await windowManager - .setTitle(LocaleSettings.currentLocale.translations.appName); - } + await desktopUpdateWindowTitle(); if (!context.mounted) { return; } @@ -178,10 +176,7 @@ class _SettingsPageState extends State { return; } LocaleSettings.setLocale(localeGroup.$1!); - if (isDesktop) { - await windowManager - .setTitle(LocaleSettings.currentLocale.translations.appName); - } + await desktopUpdateWindowTitle(); if (!context.mounted) { return; } @@ -450,18 +445,19 @@ class _SettingsPageState extends State { final tr = context.t.settingsPage.advancedSection; return [ SectionTitleText(tr.title), - SectionListTile( - leading: const Icon(Icons.developer_mode_outlined), - title: const Text('DEBUG SHOWCASE'), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const DebugShowcasePage(), - ), - ); - }, - ), + if (!kReleaseMode) + SectionListTile( + leading: const Icon(Icons.developer_mode_outlined), + title: const Text('DEBUG SHOWCASE'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const DebugShowcasePage(), + ), + ); + }, + ), SectionSwitchListTile( secondary: Icon(MdiIcons.networkOutline), title: Text(tr.useProxy), diff --git a/lib/instance.dart b/lib/instance.dart index 733ebef1..70dbf6da 100644 --- a/lib/instance.dart +++ b/lib/instance.dart @@ -1,8 +1,16 @@ import 'package:get_it/get_it.dart'; import 'package:talker_flutter/talker_flutter.dart'; +import 'package:tsdm_client/cmd.dart'; /// Global service locator instance. final getIt = GetIt.instance; /// Global logger instance. final talker = TalkerFlutter.init(); + +/// Global cmdline args. +/// +/// Only used in desktop platforms. +/// +/// Init in [parseCmdArgs] +late final CmdArgs cmdArgs; diff --git a/lib/main.dart b/lib/main.dart index 038af01f..a193062e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:responsive_framework/responsive_framework.dart'; import 'package:system_theme/system_theme.dart'; import 'package:tsdm_client/app.dart'; +import 'package:tsdm_client/cmd.dart'; import 'package:tsdm_client/constants/layout.dart'; import 'package:tsdm_client/features/settings/repositories/settings_repository.dart'; import 'package:tsdm_client/i18n/strings.g.dart'; @@ -10,9 +11,12 @@ import 'package:tsdm_client/instance.dart'; import 'package:tsdm_client/shared/models/models.dart'; import 'package:tsdm_client/shared/providers/providers.dart'; import 'package:tsdm_client/utils/platform.dart'; +import 'package:tsdm_client/utils/window_configs.dart'; import 'package:window_manager/window_manager.dart'; -Future main() async { +Future main(List args) async { + parseCmdArgs(args); + talker.debug('start app...'); WidgetsFlutterBinding.ensureInitialized(); await initProviders(); @@ -30,8 +34,8 @@ Future main() async { if (isDesktop) { await windowManager.ensureInitialized(); - await windowManager - .setTitle(LocaleSettings.currentLocale.translations.appName); + await desktopUpdateWindowTitle(); + await windowManager.center(); } // System color. diff --git a/lib/shared/providers/storage_provider/models/convertable/convertable.dart b/lib/shared/providers/storage_provider/models/convertable/convertable.dart new file mode 100644 index 00000000..574a2b2a --- /dev/null +++ b/lib/shared/providers/storage_provider/models/convertable/convertable.dart @@ -0,0 +1,7 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:drift/drift.dart'; + +part 'offset.dart'; +part 'size.dart'; diff --git a/lib/shared/providers/storage_provider/models/convertable/offset.dart b/lib/shared/providers/storage_provider/models/convertable/offset.dart new file mode 100644 index 00000000..4cc37094 --- /dev/null +++ b/lib/shared/providers/storage_provider/models/convertable/offset.dart @@ -0,0 +1,22 @@ +part of 'convertable.dart'; + +/// Converter between [Offset] and [String]. +class OffsetConverter extends TypeConverter { + /// Internal constructor. + const OffsetConverter(); + + static const _keyDx = 'dx'; + static const _keyDy = 'dy'; + + @override + Offset fromSql(String fromDb) { + final jsonMap = jsonDecode(fromDb) as Map; + return Offset(jsonMap[_keyDx]!, jsonMap[_keyDy]!); + } + + @override + String toSql(Offset value) => jsonEncode({ + _keyDx: value.dx, + _keyDy: value.dy, + }); +} diff --git a/lib/shared/providers/storage_provider/models/convertable/size.dart b/lib/shared/providers/storage_provider/models/convertable/size.dart new file mode 100644 index 00000000..4ce45a3d --- /dev/null +++ b/lib/shared/providers/storage_provider/models/convertable/size.dart @@ -0,0 +1,22 @@ +part of 'convertable.dart'; + +/// Converter between [Size] and [String]. +class SizeConverter extends TypeConverter { + /// Constructor. + const SizeConverter(); + + static const _keyWidth = 'width'; + static const _keyHeight = 'height'; + + @override + Size fromSql(String fromDb) { + final jsonMap = jsonDecode(fromDb) as Map; + return Size(jsonMap[_keyWidth]!, jsonMap[_keyHeight]!); + } + + @override + String toSql(Size value) => jsonEncode({ + _keyWidth: value.width, + _keyHeight: value.height, + }); +} diff --git a/lib/shared/providers/storage_provider/models/database/dao/cookie.dart b/lib/shared/providers/storage_provider/models/database/dao/cookie.dart index 9861acf7..4e77a9fc 100644 --- a/lib/shared/providers/storage_provider/models/database/dao/cookie.dart +++ b/lib/shared/providers/storage_provider/models/database/dao/cookie.dart @@ -48,4 +48,11 @@ final class CookieDao extends DatabaseAccessor Future deleteCookieByEmail(String email) async { return (delete(cookie)..where((e) => e.email.equals(email))).go(); } + + /// Update the last checkin time for user [uid]. + Future updateLastCheckinTime(int uid, DateTime datetime) async { + return (update(cookie)..where((e) => e.uid.equals(uid))).write( + CookieCompanion(lastCheckin: Value(datetime)), + ); + } } diff --git a/lib/shared/providers/storage_provider/models/database/dao/dao.dart b/lib/shared/providers/storage_provider/models/database/dao/dao.dart index 4fdef8af..136d75ed 100644 --- a/lib/shared/providers/storage_provider/models/database/dao/dao.dart +++ b/lib/shared/providers/storage_provider/models/database/dao/dao.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:drift/drift.dart'; import 'package:tsdm_client/shared/providers/storage_provider/models/database/database.dart'; import 'package:tsdm_client/shared/providers/storage_provider/models/database/schema/schema.dart'; diff --git a/lib/shared/providers/storage_provider/models/database/dao/settings.dart b/lib/shared/providers/storage_provider/models/database/dao/settings.dart index 53c72724..def5003d 100644 --- a/lib/shared/providers/storage_provider/models/database/dao/settings.dart +++ b/lib/shared/providers/storage_provider/models/database/dao/settings.dart @@ -20,6 +20,9 @@ final class SettingsDao extends DatabaseAccessor /// * int /// * bool /// * double + /// * [DateTime] + /// * [Offset] + /// * [Size] Future getValueByName(String name) async { final value = await (select(settings)..where((e) => e.name.equals(name))) .getSingleOrNull(); @@ -35,12 +38,28 @@ final class SettingsDao extends DatabaseAccessor return value.boolValue! as T; } else if (T == double) { return value.doubleValue! as T; + } else if (T == DateTime) { + return value.dateTimeValue! as T; + } else if (T == Offset) { + return value.offsetValue! as T; + } else if (T == Size) { + return value.sizeValue! as T; } - info('failed to get value by name "$name": unsupported type $T'); + error('failed to get value by name "$name": unsupported type $T'); return null; } /// Save [value] of name [name] + /// + /// Supported [T]: + /// + /// * [String] + /// * int + /// * bool + /// * double + /// * [DateTime] + /// * [Offset] + /// * [Size] Future setValue(String name, T value) async { final SettingsCompanion companion; if (T == String) { @@ -63,6 +82,21 @@ final class SettingsDao extends DatabaseAccessor name: Value(name), doubleValue: Value(value as double), ); + } else if (T == DateTime) { + companion = SettingsCompanion( + name: Value(name), + dateTimeValue: Value(value as DateTime), + ); + } else if (T == Offset) { + companion = SettingsCompanion( + name: Value(name), + offsetValue: Value(value as Offset), + ); + } else if (T == Size) { + companion = SettingsCompanion( + name: Value(name), + sizeValue: Value(value as Size), + ); } else { // Unsupported types. error('intend to save unsupported settings type: ' diff --git a/lib/shared/providers/storage_provider/models/database/database.dart b/lib/shared/providers/storage_provider/models/database/database.dart index bbd87e91..cdd0e31f 100644 --- a/lib/shared/providers/storage_provider/models/database/database.dart +++ b/lib/shared/providers/storage_provider/models/database/database.dart @@ -25,7 +25,7 @@ final class AppDatabase extends _$AppDatabase with LoggerMixin { AppDatabase() : super(conn.connect()); @override - int get schemaVersion => 2; + int get schemaVersion => 3; @override MigrationStrategy get migration => MigrationStrategy( diff --git a/lib/shared/providers/storage_provider/models/database/schema/cookie.dart b/lib/shared/providers/storage_provider/models/database/schema/cookie.dart index ab419812..35a4e2ba 100644 --- a/lib/shared/providers/storage_provider/models/database/schema/cookie.dart +++ b/lib/shared/providers/storage_provider/models/database/schema/cookie.dart @@ -15,6 +15,9 @@ class Cookie extends Table { /// Cookie value. TextColumn get cookie => text()(); + /// Last checkin time. + DateTimeColumn get lastCheckin => dateTime()(); + @override - Set>? get primaryKey => {uid}; + Set> get primaryKey => {uid}; } diff --git a/lib/shared/providers/storage_provider/models/database/schema/schema.dart b/lib/shared/providers/storage_provider/models/database/schema/schema.dart index 91d67876..7066658f 100644 --- a/lib/shared/providers/storage_provider/models/database/schema/schema.dart +++ b/lib/shared/providers/storage_provider/models/database/schema/schema.dart @@ -1,4 +1,5 @@ import 'package:drift/drift.dart'; +import 'package:tsdm_client/shared/providers/storage_provider/models/convertable/convertable.dart'; part 'cookie.dart'; part 'image_cache.dart'; diff --git a/lib/shared/providers/storage_provider/models/database/schema/settings.dart b/lib/shared/providers/storage_provider/models/database/schema/settings.dart index b931f14f..71ee52ad 100644 --- a/lib/shared/providers/storage_provider/models/database/schema/settings.dart +++ b/lib/shared/providers/storage_provider/models/database/schema/settings.dart @@ -23,6 +23,13 @@ class Settings extends Table { /// [DateTime] type value. DateTimeColumn get dateTimeValue => dateTime().nullable()(); + /// Ui `Size` type value. + TextColumn get sizeValue => text().map(const SizeConverter()).nullable()(); + + /// Ui `Offset` type value. + TextColumn get offsetValue => + text().map(const OffsetConverter()).nullable()(); + @override - Set>? get primaryKey => {name}; + Set> get primaryKey => {name}; } diff --git a/lib/shared/providers/storage_provider/storage_provider.dart b/lib/shared/providers/storage_provider/storage_provider.dart index c52e1412..9889fbd5 100644 --- a/lib/shared/providers/storage_provider/storage_provider.dart +++ b/lib/shared/providers/storage_provider/storage_provider.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:ui'; import 'package:collection/collection.dart'; import 'package:drift/drift.dart'; @@ -264,6 +265,30 @@ class StorageProvider with LoggerMixin { await SettingsDao(_db).setValue(key, value); } + /// Get [DateTime] type value of specified key. + Future getDateTime(String key) async => + SettingsDao(_db).getValueByName(key); + + /// Save [DateTime] type value of specified key. + Future saveDateTime(String key, DateTime value) async => + SettingsDao(_db).setValue(key, value); + + /// Get [Offset] type value of specified key. + Future getOffset(String key) async => + SettingsDao(_db).getValueByName(key); + + /// Save [Offset] type value of specified key. + Future saveOffset(String key, Offset value) async => + SettingsDao(_db).setValue(key, value); + + /// Get [Size] type value of specified key. + Future getSize(String key) async => + SettingsDao(_db).getValueByName(key); + + /// Save [Size] type value of specified key. + Future saveSize(String key, Size value) async => + SettingsDao(_db).setValue(key, value); + /// Delete the given record from database. Future deleteKey(String key) async { await SettingsDao(_db).deleteByName(key); diff --git a/lib/utils/window_configs.dart b/lib/utils/window_configs.dart new file mode 100644 index 00000000..b5bd2185 --- /dev/null +++ b/lib/utils/window_configs.dart @@ -0,0 +1,15 @@ +import 'package:tsdm_client/i18n/strings.g.dart'; +import 'package:tsdm_client/instance.dart'; +import 'package:tsdm_client/utils/platform.dart'; +import 'package:window_manager/window_manager.dart'; + +/// Update window title according to current using locale. +/// +/// Only available on desktop platforms. +Future desktopUpdateWindowTitle() async { + if (isDesktop && !cmdArgs.noWindowConfigs) { + await windowManager + .setTitle(LocaleSettings.currentLocale.translations.appName); + talker.debug('set window title with current locale'); + } +} diff --git a/pubspec.lock b/pubspec.lock index 3babf362..ff48467d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -47,7 +47,7 @@ packages: source: hosted version: "3.6.1" args: - dependency: transitive + dependency: "direct main" description: name: args sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" diff --git a/pubspec.yaml b/pubspec.yaml index 29acccae..24047e41 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,6 +14,7 @@ environment: dependencies: # Workaround for dart_mappable build issue ansicolor: any + args: ^2.5.0 bbob_dart: ^0.2.1 bloc: ^8.1.4 chat_bottom_container: ^0.2.0