diff --git a/lib/app.dart b/lib/app.dart index efb80d4..a0976dc 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,4 +1,5 @@ import 'package:animated_theme_switcher/animated_theme_switcher.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -9,7 +10,8 @@ import 'router/router.dart'; class VeilidChatApp extends ConsumerWidget { const VeilidChatApp({ - required this.theme, super.key, + required this.theme, + super.key, }); final ThemeData theme; @@ -23,23 +25,24 @@ class VeilidChatApp extends ConsumerWidget { return ThemeProvider( initTheme: theme, builder: (_, theme) => LocalizationProvider( - state: LocalizationProvider.of(context).state, - child: MaterialApp.router( - debugShowCheckedModeBanner: false, - routerConfig: router, - title: translate('app.title'), - theme: theme, - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - FormBuilderLocalizations.delegate, - localizationDelegate - ], - supportedLocales: localizationDelegate.supportedLocales, - locale: localizationDelegate.currentLocale, - )), + state: LocalizationProvider.of(context).state, + child: MaterialApp.router( + debugShowCheckedModeBanner: false, + routerConfig: router, + title: translate('app.title'), + theme: theme, + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + FormBuilderLocalizations.delegate, + localizationDelegate + ], + supportedLocales: localizationDelegate.supportedLocales, + locale: localizationDelegate.currentLocale, + )), ); } + @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/lib/log/loggy.dart b/lib/log/loggy.dart index 3675cb3..cee5443 100644 --- a/lib/log/loggy.dart +++ b/lib/log/loggy.dart @@ -67,7 +67,7 @@ class CallbackPrinter extends LoggyPrinter { callback?.call(record); } - void setCallback(Function(LogRecord)? cb) { + void setCallback(void Function(LogRecord)? cb) { callback = cb; } } @@ -80,9 +80,9 @@ extension TraceLoggy on Loggy { } LogOptions getLogOptions(LogLevel? level) => LogOptions( - level ?? LogLevel.all, - stackTraceLevel: LogLevel.error, - ); + level ?? LogLevel.all, + stackTraceLevel: LogLevel.error, + ); class RootLoggy implements LoggyType { @override diff --git a/lib/log/state_logger.dart b/lib/log/state_logger.dart index 045a983..973b5f9 100644 --- a/lib/log/state_logger.dart +++ b/lib/log/state_logger.dart @@ -5,12 +5,13 @@ class StateLogger extends ProviderObserver { const StateLogger(); @override void didUpdateProvider( - ProviderBase provider, + ProviderBase provider, Object? previousValue, Object? newValue, ProviderContainer container, ) { - log.debug('''{ + log.debug(''' +{ provider: ${provider.name ?? provider.runtimeType}, oldValue: $previousValue, newValue: $newValue diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart index 7b831c1..6e20cee 100644 --- a/lib/pages/new_account.dart +++ b/lib/pages/new_account.dart @@ -1,4 +1,5 @@ import 'package:awesome_extensions/awesome_extensions.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -33,11 +34,11 @@ class NewAccountPageState extends ConsumerState { final localAccounts = ref.read(localAccountsProvider.notifier); final logins = ref.read(loginsProvider.notifier); - final profile = proto.Profile(); - profile.name = _formKey.currentState!.fields[formFieldName]!.value; - profile.title = _formKey.currentState!.fields[formFieldTitle]!.value; - final account = proto.Account(); - account.profile = profile; + final profile = proto.Profile() + ..name = _formKey.currentState!.fields[formFieldName]!.value as String + ..title = + _formKey.currentState!.fields[formFieldTitle]!.value as String; + final account = proto.Account()..profile = profile; final localAccount = await localAccounts.newAccount( identityMaster: imws.identityMaster, identitySecret: imws.identitySecret, @@ -46,65 +47,67 @@ class NewAccountPageState extends ConsumerState { // Log in the new account by default with no pin final ok = await logins .loginWithNone(localAccount.identityMaster.masterRecordKey); - assert(ok == true); - } catch (e) { + assert(ok == true, 'login with none should never fail'); + } on Exception catch (_) { await imws.delete(); rethrow; } } Widget _newAccountForm(BuildContext context, - {required Future Function(GlobalKey) onSubmit}) => FormBuilder( - key: _formKey, - child: ListView( - children: [ - Text(translate('new_account_page.header')) - .textStyle(context.headlineSmall) - .paddingSymmetric(vertical: 16), - FormBuilderTextField( - autofocus: true, - name: formFieldName, - decoration: - InputDecoration(hintText: translate('account.form_name')), - maxLength: 64, - // The validator receives the text that the user has entered. - validator: FormBuilderValidators.compose([ - FormBuilderValidators.required(), - ]), - ), - FormBuilderTextField( - name: formFieldTitle, - maxLength: 64, - decoration: - InputDecoration(hintText: translate('account.form_title')), - ), - Row(children: [ - const Spacer(), - Text(translate('new_account_page.instructions')) - .toCenter() - .flexible(flex: 6), - const Spacer(), - ]).paddingSymmetric(vertical: 4), - ElevatedButton( - onPressed: () async { - if (_formKey.currentState?.saveAndValidate() ?? false) { - setState(() { - isInAsyncCall = true; - }); - try { - await onSubmit(_formKey); - } finally { + {required Future Function(GlobalKey) + onSubmit}) => + FormBuilder( + key: _formKey, + child: ListView( + children: [ + Text(translate('new_account_page.header')) + .textStyle(context.headlineSmall) + .paddingSymmetric(vertical: 16), + FormBuilderTextField( + autofocus: true, + name: formFieldName, + decoration: + InputDecoration(hintText: translate('account.form_name')), + maxLength: 64, + // The validator receives the text that the user has entered. + validator: FormBuilderValidators.compose([ + FormBuilderValidators.required(), + ]), + ), + FormBuilderTextField( + name: formFieldTitle, + maxLength: 64, + decoration: + InputDecoration(hintText: translate('account.form_title')), + ), + Row(children: [ + const Spacer(), + Text(translate('new_account_page.instructions')) + .toCenter() + .flexible(flex: 6), + const Spacer(), + ]).paddingSymmetric(vertical: 4), + ElevatedButton( + onPressed: () async { + if (_formKey.currentState?.saveAndValidate() ?? false) { setState(() { - isInAsyncCall = false; + isInAsyncCall = true; }); + try { + await onSubmit(_formKey); + } finally { + setState(() { + isInAsyncCall = false; + }); + } } - } - }, - child: Text(translate('new_account_page.create')), - ).paddingSymmetric(vertical: 4).alignAtCenterRight(), - ], - ), - ); + }, + child: Text(translate('new_account_page.create')), + ).paddingSymmetric(vertical: 4).alignAtCenterRight(), + ], + ), + ); @override Widget build(BuildContext context) { @@ -125,7 +128,7 @@ class NewAccountPageState extends ConsumerState { FocusScope.of(context).unfocus(); try { await createAccount(); - } catch (e) { + } on Exception catch (e) { await QuickAlert.show( context: context, type: QuickAlertType.error, @@ -140,6 +143,7 @@ class NewAccountPageState extends ConsumerState { ).paddingSymmetric(horizontal: 24, vertical: 8), ).withModalHUD(context, displayModalHUD); } + @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/lib/theming/theme_service.dart b/lib/theming/theme_service.dart index eabce29..b3b0c44 100644 --- a/lib/theming/theme_service.dart +++ b/lib/theming/theme_service.dart @@ -26,12 +26,12 @@ class ThemeService { final isPlatformDark = WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark; - themeName = isPlatformDark ? 'light' : 'dark'; + themeName = isPlatformDark ? 'dark' : 'light'; } return themeName; } - ThemeData? get initial { + ThemeData get initial { var themeName = prefs.getString('theme'); if (themeName == null) { final isPlatformDark = @@ -39,15 +39,15 @@ class ThemeService { Brightness.dark; themeName = isPlatformDark ? 'dark' : 'light'; } - return allThemes[themeName]; + return allThemes[themeName] ?? allThemes['light']!; } - save(String newThemeName) { + Future save(String newThemeName) async { final currentThemeName = prefs.getString('theme'); if (currentThemeName != null) { - prefs.setString('previousThemeName', currentThemeName); + await prefs.setString('previousThemeName', currentThemeName); } - prefs.setString('theme', newThemeName); + await prefs.setString('theme', newThemeName); } ThemeData getByName(String name) => allThemes[name]!; diff --git a/lib/tools/json_tools.dart b/lib/tools/json_tools.dart index b5b3259..be69102 100644 --- a/lib/tools/json_tools.dart +++ b/lib/tools/json_tools.dart @@ -1,14 +1,15 @@ import 'dart:convert'; import 'dart:typed_data'; -T jsonDecodeBytes( - T Function(Map) fromJson, Uint8List data) => fromJson(jsonDecode(utf8.decode(data))); +T jsonDecodeBytes(T Function(dynamic) fromJson, Uint8List data) => + fromJson(jsonDecode(utf8.decode(data))); Uint8List jsonEncodeBytes(Object? object, - {Object? Function(Object?)? toEncodable}) => Uint8List.fromList( - utf8.encode(jsonEncode(object, toEncodable: toEncodable))); + {Object? Function(Object?)? toEncodable}) => + Uint8List.fromList( + utf8.encode(jsonEncode(object, toEncodable: toEncodable))); -Future jsonUpdateBytes(T Function(Map) fromJson, +Future jsonUpdateBytes(T Function(dynamic) fromJson, Uint8List oldBytes, Future Function(T) update) async { final oldObj = fromJson(jsonDecode(utf8.decode(oldBytes))); final newObj = await update(oldObj); @@ -16,7 +17,9 @@ Future jsonUpdateBytes(T Function(Map) fromJson, } Future Function(Uint8List) jsonUpdate( - T Function(Map) fromJson, Future Function(T) update) => (oldBytes) => jsonUpdateBytes(fromJson, oldBytes, update); + T Function(dynamic) fromJson, Future Function(T) update) => + (oldBytes) => jsonUpdateBytes(fromJson, oldBytes, update); T Function(Object?) genericFromJson( - T Function(Map) fromJsonMap) => (json) => fromJsonMap(json as Map); + T Function(Map) fromJsonMap) => + (json) => fromJsonMap(json! as Map); diff --git a/lib/tools/widget_helpers.dart b/lib/tools/widget_helpers.dart index bafd784..144a8f6 100644 --- a/lib/tools/widget_helpers.dart +++ b/lib/tools/widget_helpers.dart @@ -3,19 +3,20 @@ import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; extension BorderExt on Widget { - Container debugBorder() => DecoratedBox( - decoration: BoxDecoration(border: Border.all(color: Colors.redAccent)), - child: this); + DecoratedBox debugBorder() => DecoratedBox( + decoration: BoxDecoration(border: Border.all(color: Colors.redAccent)), + child: this); } extension ModalProgressExt on Widget { - BlurryModalProgressHUD withModalHUD(BuildContext context, bool isLoading) => BlurryModalProgressHUD( - inAsyncCall: isLoading, - blurEffectIntensity: 4, - progressIndicator: SpinKitFoldingCube( - color: Theme.of(context).highlightColor, - size: 90, - ), - color: Theme.of(context).shadowColor, - child: this); + BlurryModalProgressHUD withModalHUD(BuildContext context, bool isLoading) => + BlurryModalProgressHUD( + inAsyncCall: isLoading, + blurEffectIntensity: 4, + progressIndicator: SpinKitFoldingCube( + color: Theme.of(context).highlightColor, + size: 90, + ), + color: Theme.of(context).shadowColor, + child: this); } diff --git a/lib/veilid_support/dht_record.dart b/lib/veilid_support/dht_record.dart index e02c340..e529c66 100644 --- a/lib/veilid_support/dht_record.dart +++ b/lib/veilid_support/dht_record.dart @@ -7,7 +7,6 @@ import '../tools/tools.dart'; import 'veilid_support.dart'; class DHTRecord { - DHTRecord( {required VeilidRoutingContext dhtctx, required DHTRecordDescriptor recordDescriptor, @@ -46,8 +45,7 @@ class DHTRecord { static Future openRead( VeilidRoutingContext dhtctx, TypedKey recordKey, {int defaultSubkey = 0, DHTRecordCrypto? crypto}) async { - final recordDescriptor = - await dhtctx.openDHTRecord(recordKey, null); + final recordDescriptor = await dhtctx.openDHTRecord(recordKey, null); final rec = DHTRecord( dhtctx: dhtctx, recordDescriptor: recordDescriptor, @@ -64,8 +62,7 @@ class DHTRecord { int defaultSubkey = 0, DHTRecordCrypto? crypto, }) async { - final recordDescriptor = - await dhtctx.openDHTRecord(recordKey, writer); + final recordDescriptor = await dhtctx.openDHTRecord(recordKey, writer); final rec = DHTRecord( dhtctx: dhtctx, recordDescriptor: recordDescriptor, @@ -112,7 +109,7 @@ class DHTRecord { final out = await scopeFunction(this); await close(); return out; - } catch (_) { + } on Exception catch (_) { await delete(); rethrow; } @@ -128,7 +125,7 @@ class DHTRecord { return _crypto.decrypt(valueData.data, subkey); } - Future getJson(T Function(Map) fromJson, + Future getJson(T Function(dynamic) fromJson, {int subkey = -1, bool forceRefresh = false}) async { final data = await get(subkey: subkey, forceRefresh: forceRefresh); if (data == null) { @@ -177,17 +174,20 @@ class DHTRecord { } while (valueData != null); } - Future eventualWriteJson(T newValue, {int subkey = -1}) => eventualWriteBytes(jsonEncodeBytes(newValue), subkey: subkey); + Future eventualWriteJson(T newValue, {int subkey = -1}) => + eventualWriteBytes(jsonEncodeBytes(newValue), subkey: subkey); Future eventualWriteProtobuf(T newValue, - {int subkey = -1}) => eventualWriteBytes(newValue.writeToBuffer(), subkey: subkey); + {int subkey = -1}) => + eventualWriteBytes(newValue.writeToBuffer(), subkey: subkey); Future eventualUpdateJson( - T Function(Map) fromJson, Future Function(T) update, - {int subkey = -1}) => eventualUpdateBytes(jsonUpdate(fromJson, update), subkey: subkey); + T Function(dynamic) fromJson, Future Function(T) update, + {int subkey = -1}) => + eventualUpdateBytes(jsonUpdate(fromJson, update), subkey: subkey); Future eventualUpdateProtobuf( - T Function(List) fromBuffer, Future Function(T) update, - {int subkey = -1}) => eventualUpdateBytes(protobufUpdate(fromBuffer, update), - subkey: subkey); + T Function(List) fromBuffer, Future Function(T) update, + {int subkey = -1}) => + eventualUpdateBytes(protobufUpdate(fromBuffer, update), subkey: subkey); }