From 96d95f528db07d309414f48880c91bc8c7068220 Mon Sep 17 00:00:00 2001 From: Garrett Watson Date: Mon, 13 Nov 2023 12:14:17 -0500 Subject: [PATCH] chore: update formatting to use 120 char line length --- lib/clients/audio_cache_client.dart | 6 +- lib/clients/notification_client.dart | 28 +-- lib/main.dart | 61 ++---- .../inventory/inventory_browser_app_bar.dart | 94 +++------ lib/widgets/login_screen.dart | 69 ++----- .../messages/message_audio_player.dart | 54 ++--- lib/widgets/messages/message_input_bar.dart | 193 +++++------------- lib/widgets/messages/messages_list.dart | 31 +-- .../messages/messages_session_header.dart | 16 +- .../sessions/session_list_app_bar.dart | 5 +- lib/widgets/settings_app_bar.dart | 1 - test/widget_test.dart | 1 - 12 files changed, 171 insertions(+), 388 deletions(-) diff --git a/lib/clients/audio_cache_client.dart b/lib/clients/audio_cache_client.dart index bb461df..619b0ab 100644 --- a/lib/clients/audio_cache_client.dart +++ b/lib/clients/audio_cache_client.dart @@ -18,8 +18,7 @@ class AudioCacheClient { final file = File("${directory.path}/$fileName.ogg"); if (!await file.exists()) { await file.create(recursive: true); - final response = - await http.get(Uri.parse(Aux.resdbToHttp(clip.assetUri))); + final response = await http.get(Uri.parse(Aux.resdbToHttp(clip.assetUri))); ApiClient.checkResponseCode(response); await file.writeAsBytes(response.bodyBytes); } @@ -31,8 +30,7 @@ class AudioCacheClient { } if (!wavFileExists) { await wavFile.create(recursive: true); - await FFmpegKit.executeAsync( - "-y -acodec libvorbis -i ${file.path} -acodec pcm_s16le ${wavFile.path}"); + await FFmpegKit.executeAsync("-y -acodec libvorbis -i ${file.path} -acodec pcm_s16le ${wavFile.path}"); } return wavFile; } diff --git a/lib/clients/notification_client.dart b/lib/clients/notification_client.dart index 874c6fa..812cdde 100644 --- a/lib/clients/notification_client.dart +++ b/lib/clients/notification_client.dart @@ -1,8 +1,7 @@ import 'dart:convert'; import 'package:collection/collection.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart' - as fln; +import 'package:flutter_local_notifications/flutter_local_notifications.dart' as fln; import 'package:recon/auxiliary.dart'; import 'package:recon/models/message.dart'; import 'package:recon/models/session.dart'; @@ -12,8 +11,7 @@ class NotificationChannel { final String name; final String description; - const NotificationChannel( - {required this.name, required this.id, required this.description}); + const NotificationChannel({required this.name, required this.id, required this.description}); } class NotificationClient { @@ -23,18 +21,15 @@ class NotificationClient { description: "Messages received from your friends", ); - final fln.FlutterLocalNotificationsPlugin _notifier = - fln.FlutterLocalNotificationsPlugin() - ..initialize(const fln.InitializationSettings( - android: fln.AndroidInitializationSettings("ic_notification"), - iOS: fln.DarwinInitializationSettings(), - macOS: fln.DarwinInitializationSettings(), - linux: - fln.LinuxInitializationSettings(defaultActionName: "Open ReCon"), - )); + final fln.FlutterLocalNotificationsPlugin _notifier = fln.FlutterLocalNotificationsPlugin() + ..initialize(const fln.InitializationSettings( + android: fln.AndroidInitializationSettings("ic_notification"), + iOS: fln.DarwinInitializationSettings(), + macOS: fln.DarwinInitializationSettings(), + linux: fln.LinuxInitializationSettings(defaultActionName: "Open ReCon"), + )); - Future showUnreadMessagesNotification( - Iterable messages) async { + Future showUnreadMessagesNotification(Iterable messages) async { if (messages.isEmpty) return; final bySender = groupBy(messages, (p0) => p0.senderId); @@ -73,8 +68,7 @@ class NotificationClient { break; case MessageType.sessionInvite: try { - final session = - Session.fromMap(jsonDecode(message.content)); + final session = Session.fromMap(jsonDecode(message.content)); content = "Session Invite to ${session.name}"; } catch (e) { content = "Session Invite"; diff --git a/lib/main.dart b/lib/main.dart index 98493e2..8de17ae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,23 +38,19 @@ void main() async { ), ); - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge, - overlays: [SystemUiOverlay.top]); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge, overlays: [SystemUiOverlay.top]); await Hive.initFlutter(); final dateFormat = DateFormat.Hms(); - Logger.root.onRecord.listen((event) => log( - "${dateFormat.format(event.time)}: ${event.message}", - name: event.loggerName, - time: event.time)); + Logger.root.onRecord.listen( + (event) => log("${dateFormat.format(event.time)}: ${event.message}", name: event.loggerName, time: event.time)); final settingsClient = SettingsClient(); await settingsClient.loadSettings(); - final newSettings = settingsClient.currentSettings.copyWith( - machineId: settingsClient.currentSettings.machineId.valueOrDefault); - await settingsClient - .changeSettings(newSettings); // Save generated machineId to disk + final newSettings = + settingsClient.currentSettings.copyWith(machineId: settingsClient.currentSettings.machineId.valueOrDefault); + await settingsClient.changeSettings(newSettings); // Save generated machineId to disk AuthenticationData cachedAuth = AuthenticationData.unauthenticated(); try { @@ -63,15 +59,11 @@ void main() async { // Ignore } - runApp( - ReCon(settingsClient: settingsClient, cachedAuthentication: cachedAuth)); + runApp(ReCon(settingsClient: settingsClient, cachedAuthentication: cachedAuth)); } class ReCon extends StatefulWidget { - const ReCon( - {required this.settingsClient, - required this.cachedAuthentication, - super.key}); + const ReCon({required this.settingsClient, required this.cachedAuthentication, super.key}); final SettingsClient settingsClient; final AuthenticationData cachedAuthentication; @@ -81,8 +73,7 @@ class ReCon extends StatefulWidget { } class _ReConState extends State { - final Typography _typography = - Typography.material2021(platform: defaultTargetPlatform); + final Typography _typography = Typography.material2021(platform: defaultTargetPlatform); final ReceivePort _port = ReceivePort(); late AuthenticationData _authData = widget.cachedAuthentication; bool _checkedForUpdate = false; @@ -105,8 +96,7 @@ class _ReConState extends State { } try { - lastDismissedSem = SemVer.fromString( - settings.currentSettings.lastDismissedVersion.valueOrDefault); + lastDismissedSem = SemVer.fromString(settings.currentSettings.lastDismissedVersion.valueOrDefault); } catch (_) { lastDismissedSem = SemVer.zero(); } @@ -121,9 +111,7 @@ class _ReConState extends State { return; } - if (remoteSem > currentSem && - navigator.overlay?.context != null && - context.mounted) { + if (remoteSem > currentSem && navigator.overlay?.context != null && context.mounted) { showDialog( context: navigator.overlay!.context, builder: (context) { @@ -141,8 +129,7 @@ class _ReConState extends State { void initState() { super.initState(); - IsolateNameServer.registerPortWithName( - _port.sendPort, 'downloader_send_port'); + IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port'); _port.listen((dynamic data) { // Not useful yet? idk... // String id = data[0]; @@ -176,26 +163,21 @@ class _ReConState extends State { Phoenix.rebirth(context); }, child: DynamicColorBuilder( - builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) => - MaterialApp( + builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) => MaterialApp( debugShowCheckedModeBanner: false, title: 'ReCon', theme: ThemeData( useMaterial3: true, textTheme: _typography.black, - colorScheme: lightDynamic ?? - ColorScheme.fromSeed( - seedColor: Colors.purple, brightness: Brightness.light), + colorScheme: + lightDynamic ?? ColorScheme.fromSeed(seedColor: Colors.purple, brightness: Brightness.light), ), darkTheme: ThemeData( useMaterial3: true, textTheme: _typography.white, - colorScheme: darkDynamic ?? - ColorScheme.fromSeed( - seedColor: Colors.purple, brightness: Brightness.dark), + colorScheme: darkDynamic ?? ColorScheme.fromSeed(seedColor: Colors.purple, brightness: Brightness.dark), ), - themeMode: ThemeMode.values[widget - .settingsClient.currentSettings.themeMode.valueOrDefault], + themeMode: ThemeMode.values[widget.settingsClient.currentSettings.themeMode.valueOrDefault], home: Builder( // Builder is necessary here since we need a context which has access to the ClientHolder builder: (context) { @@ -208,8 +190,7 @@ class _ReConState extends State { create: (context) => MessagingClient( apiClient: clientHolder.apiClient, settingsClient: clientHolder.settingsClient, - notificationClient: - clientHolder.notificationClient, + notificationClient: clientHolder.notificationClient, ), ), ChangeNotifierProvider( @@ -226,15 +207,13 @@ class _ReConState extends State { ], child: AnnotatedRegion( value: SystemUiOverlayStyle( - statusBarColor: - Theme.of(context).colorScheme.surfaceVariant, + statusBarColor: Theme.of(context).colorScheme.surfaceVariant, ), child: const Home(), ), ) : LoginScreen( - onLoginSuccessful: - (AuthenticationData authData) async { + onLoginSuccessful: (AuthenticationData authData) async { if (authData.isAuthenticated) { setState(() { _authData = authData; diff --git a/lib/widgets/inventory/inventory_browser_app_bar.dart b/lib/widgets/inventory/inventory_browser_app_bar.dart index 4a83366..93eab10 100644 --- a/lib/widgets/inventory/inventory_browser_app_bar.dart +++ b/lib/widgets/inventory/inventory_browser_app_bar.dart @@ -28,8 +28,7 @@ class _InventoryBrowserAppBarState extends State { final id = event.task.taskId; final status = event is TaskStatusUpdate ? event.status : null; final progress = event is TaskProgressUpdate ? event.progress : null; - final SendPort? send = - IsolateNameServer.lookupPortByName('downloader_send_port'); + final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port'); send?.send([id, status, progress]); } @@ -74,9 +73,7 @@ class _InventoryBrowserAppBarState extends State { style: TextStyle( color: iClient.sortReverse == false ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface, + : Theme.of(context).colorScheme.onSurface, ), ), ], @@ -89,9 +86,7 @@ class _InventoryBrowserAppBarState extends State { Icon(Icons.arrow_downward, color: iClient.sortReverse == true ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface), + : Theme.of(context).colorScheme.onSurface), const SizedBox( width: 8, ), @@ -100,9 +95,7 @@ class _InventoryBrowserAppBarState extends State { style: TextStyle( color: iClient.sortReverse == true ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface, + : Theme.of(context).colorScheme.onSurface, ), ), ], @@ -128,27 +121,18 @@ class _InventoryBrowserAppBarState extends State { Icon( e.icon, color: iClient.sortMode == e - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface, + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface, ), const SizedBox( width: 8, ), Text( - toBeginningOfSentenceCase(e.name) ?? - e.name, + toBeginningOfSentenceCase(e.name) ?? e.name, style: TextStyle( color: iClient.sortMode == e - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface, + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface, ), ) ], @@ -173,8 +157,7 @@ class _InventoryBrowserAppBarState extends State { actions: [ if (iClient.selectedRecordCount == 1 && (iClient.selectedRecords.firstOrNull?.isLink == true || - iClient.selectedRecords.firstOrNull?.isItem == - true)) + iClient.selectedRecords.firstOrNull?.isItem == true)) IconButton( onPressed: () { Share.share(iClient.selectedRecords.first.assetUri); @@ -186,12 +169,8 @@ class _InventoryBrowserAppBarState extends State { onPressed: () async { final selectedRecords = iClient.selectedRecords; - final assetUris = selectedRecords - .map((record) => record.assetUri) - .toList(); - final thumbUris = selectedRecords - .map((record) => record.thumbnailUri) - .toList(); + final assetUris = selectedRecords.map((record) => record.assetUri).toList(); + final thumbUris = selectedRecords.map((record) => record.thumbnailUri).toList(); final selectedUris = await showDialog>( context: context, @@ -232,8 +211,7 @@ class _InventoryBrowserAppBarState extends State { ); if (selectedUris == null) return; - final directory = await FilePicker.platform - .getDirectoryPath(dialogTitle: "Download to..."); + final directory = await FilePicker.platform.getDirectoryPath(dialogTitle: "Download to..."); if (directory == null) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( @@ -248,17 +226,14 @@ class _InventoryBrowserAppBarState extends State { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: - Text("Selected directory is invalid"), + content: Text("Selected directory is invalid"), ), ); } return; } for (var record in selectedRecords) { - final uri = selectedUris == thumbUris - ? record.thumbnailUri - : record.assetUri; + final uri = selectedUris == thumbUris ? record.thumbnailUri : record.assetUri; final filename = "${record.id.split("-")[1]}-${record.formattedName.toString()}${extension(uri)}"; final downloadTask = DownloadTask( @@ -268,22 +243,18 @@ class _InventoryBrowserAppBarState extends State { filename: filename, updates: Updates.statusAndProgress, ); - await FileDownloader() - .enqueue(downloadTask) - .then((b) { + await FileDownloader().enqueue(downloadTask).then((b) { if (context.mounted) { if (b) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - "Downloaded ${record.formattedName.toString()}"), + content: Text("Downloaded ${record.formattedName.toString()}"), ), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - "Failed to download ${record.formattedName.toString()}"), + content: Text("Failed to download ${record.formattedName.toString()}"), ), ); } @@ -317,10 +288,8 @@ class _InventoryBrowserAppBarState extends State { title: Text(iClient.selectedRecordCount == 1 ? "Really delete this Record?" : "Really delete ${iClient.selectedRecordCount} Records?"), - content: const Text( - "This action cannot be undone!"), - actionsAlignment: - MainAxisAlignment.spaceBetween, + content: const Text("This action cannot be undone!"), + actionsAlignment: MainAxisAlignment.spaceBetween, actions: [ TextButton( onPressed: loading @@ -336,8 +305,7 @@ class _InventoryBrowserAppBarState extends State { if (loading) const SizedBox.square( dimension: 16, - child: CircularProgressIndicator( - strokeWidth: 2), + child: CircularProgressIndicator(strokeWidth: 2), ), const SizedBox( width: 4, @@ -350,16 +318,12 @@ class _InventoryBrowserAppBarState extends State { loading = true; }); try { - await iClient - .deleteSelectedRecords(); + await iClient.deleteSelectedRecords(); } catch (e) { if (context.mounted) { - ScaffoldMessenger.of( - context) - .showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - "Failed to delete one or more records: $e"), + content: Text("Failed to delete one or more records: $e"), ), ); } @@ -368,16 +332,12 @@ class _InventoryBrowserAppBarState extends State { }); } if (context.mounted) { - Navigator.of(context) - .pop(true); + Navigator.of(context).pop(true); } - iClient - .reloadCurrentDirectory(); + iClient.reloadCurrentDirectory(); }, style: TextButton.styleFrom( - foregroundColor: Theme.of(context) - .colorScheme - .error, + foregroundColor: Theme.of(context).colorScheme.error, ), child: const Text("Delete"), ), diff --git a/lib/widgets/login_screen.dart b/lib/widgets/login_screen.dart index ac82ab7..449340f 100644 --- a/lib/widgets/login_screen.dart +++ b/lib/widgets/login_screen.dart @@ -83,10 +83,8 @@ class _LoginScreenState extends State { _error = "Please enter your 2FA-Code"; _totpFocusNode.requestFocus(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration(milliseconds: 400), - curve: Curves.easeOutCirc); + _scrollController.animateTo(_scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 400), curve: Curves.easeOutCirc); }); } else { _error = "The given 2FA code is not valid."; @@ -115,16 +113,14 @@ class _LoginScreenState extends State { context: context, builder: (context) { return AlertDialog( - title: const Text( - "This app needs to ask your permission to send background notifications."), + title: const Text("This app needs to ask your permission to send background notifications."), content: const Text("Are you okay with that?"), actions: [ TextButton( onPressed: () async { Navigator.of(context).pop(); - await settingsClient.changeSettings(settingsClient - .currentSettings - .copyWith(notificationsDenied: true)); + await settingsClient + .changeSettings(settingsClient.currentSettings.copyWith(notificationsDenied: true)); }, child: const Text("No"), ), @@ -133,31 +129,21 @@ class _LoginScreenState extends State { Navigator.of(context).pop(); final requestResult = switch (Platform.operatingSystem) { "android" => await notificationManager - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() + .resolvePlatformSpecificImplementation() ?.requestNotificationsPermission(), - "fuschia" => - null, // "fuschia" is not supported by flutter_local_notifications + "fuschia" => null, // "fuschia" is not supported by flutter_local_notifications "ios" => await notificationManager - .resolvePlatformSpecificImplementation< - IOSFlutterLocalNotificationsPlugin>() - ?.requestPermissions( - alert: true, badge: true, sound: true), + .resolvePlatformSpecificImplementation() + ?.requestPermissions(alert: true, badge: true, sound: true), "linux" => null, // don't want to deal with this right now "macos" => await notificationManager - .resolvePlatformSpecificImplementation< - MacOSFlutterLocalNotificationsPlugin>() - ?.requestPermissions( - alert: true, badge: true, sound: true), - "windows" => - null, // also don't want to deal with this right now + .resolvePlatformSpecificImplementation() + ?.requestPermissions(alert: true, badge: true, sound: true), + "windows" => null, // also don't want to deal with this right now _ => null, }; - await settingsClient.changeSettings( - settingsClient.currentSettings.copyWith( - notificationsDenied: requestResult == null - ? false - : !requestResult)); + await settingsClient.changeSettings(settingsClient.currentSettings + .copyWith(notificationsDenied: requestResult == null ? false : !requestResult)); }, child: const Text("Yes"), ) @@ -183,8 +169,7 @@ class _LoginScreenState extends State { Padding( padding: const EdgeInsets.symmetric(vertical: 64), child: Center( - child: Text("Sign In", - style: Theme.of(context).textTheme.headlineMedium), + child: Text("Sign In", style: Theme.of(context).textTheme.headlineMedium), ), ), Padding( @@ -193,8 +178,7 @@ class _LoginScreenState extends State { controller: _usernameController, onEditingComplete: () => _passwordFocusNode.requestFocus(), decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric(vertical: 20, horizontal: 24), + contentPadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 24), border: OutlineInputBorder( borderRadius: BorderRadius.circular(32), ), @@ -210,26 +194,22 @@ class _LoginScreenState extends State { onEditingComplete: submit, obscureText: true, decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric(vertical: 20, horizontal: 24), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(32)), + contentPadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 24), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(32)), labelText: 'Password', ), ), ), if (_needsTotp) Padding( - padding: - const EdgeInsets.symmetric(vertical: 16, horizontal: 64), + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 64), child: TextField( controller: _totpController, focusNode: _totpFocusNode, onEditingComplete: submit, obscureText: false, decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric( - vertical: 20, horizontal: 24), + contentPadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 24), border: OutlineInputBorder( borderRadius: BorderRadius.circular(32), ), @@ -252,13 +232,8 @@ class _LoginScreenState extends State { opacity: _errorOpacity, duration: const Duration(milliseconds: 200), child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 16, horizontal: 64), - child: Text(_error, - style: Theme.of(context) - .textTheme - .labelMedium - ?.copyWith(color: Colors.red)), + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 64), + child: Text(_error, style: Theme.of(context).textTheme.labelMedium?.copyWith(color: Colors.red)), ), ), ) diff --git a/lib/widgets/messages/message_audio_player.dart b/lib/widgets/messages/message_audio_player.dart index 8d1e3b5..f8e67f7 100644 --- a/lib/widgets/messages/message_audio_player.dart +++ b/lib/widgets/messages/message_audio_player.dart @@ -9,8 +9,7 @@ import 'package:recon/models/message.dart'; import 'package:recon/widgets/messages/message_state_indicator.dart'; class MessageAudioPlayer extends StatefulWidget { - const MessageAudioPlayer( - {required this.message, this.foregroundColor, super.key}); + const MessageAudioPlayer({required this.message, this.foregroundColor, super.key}); final Message message; final Color? foregroundColor; @@ -19,8 +18,7 @@ class MessageAudioPlayer extends StatefulWidget { State createState() => _MessageAudioPlayerState(); } -class _MessageAudioPlayerState extends State - with WidgetsBindingObserver { +class _MessageAudioPlayerState extends State with WidgetsBindingObserver { final AudioPlayer _audioPlayer = AudioPlayer(); Future? _audioFileFuture; double _sliderValue = 0; @@ -43,8 +41,7 @@ class _MessageAudioPlayerState extends State super.didChangeDependencies(); final audioCache = Provider.of(context); _audioFileFuture = audioCache - .cachedNetworkAudioFile( - AudioClipContent.fromMap(jsonDecode(widget.message.content))) + .cachedNetworkAudioFile(AudioClipContent.fromMap(jsonDecode(widget.message.content))) .then((value) => _audioPlayer.setFilePath(value.path)) .whenComplete(() => _audioPlayer.setLoopMode(LoopMode.off)); } @@ -55,8 +52,7 @@ class _MessageAudioPlayerState extends State if (oldWidget.message.id == widget.message.id) return; final audioCache = Provider.of(context); _audioFileFuture = audioCache - .cachedNetworkAudioFile( - AudioClipContent.fromMap(jsonDecode(widget.message.content))) + .cachedNetworkAudioFile(AudioClipContent.fromMap(jsonDecode(widget.message.content))) .then((value) async { final path = _audioPlayer.setFilePath(value.path); await _audioPlayer.setLoopMode(LoopMode.off); @@ -91,10 +87,7 @@ class _MessageAudioPlayerState extends State textAlign: TextAlign.center, softWrap: true, maxLines: 3, - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith(color: Theme.of(context).colorScheme.error), + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).colorScheme.error), ), ], ), @@ -108,8 +101,7 @@ class _MessageAudioPlayerState extends State stream: _audioPlayer.playerStateStream, builder: (context, snapshot) { if (snapshot.hasError) { - FlutterError.reportError(FlutterErrorDetails( - exception: snapshot.error!, stack: snapshot.stackTrace)); + FlutterError.reportError(FlutterErrorDetails(exception: snapshot.error!, stack: snapshot.stackTrace)); return _createErrorWidget("Failed to load audio-message."); } final playerState = snapshot.data; @@ -125,9 +117,8 @@ class _MessageAudioPlayerState extends State future: _audioFileFuture, builder: (context, fileSnapshot) { if (fileSnapshot.hasError) { - FlutterError.reportError(FlutterErrorDetails( - exception: fileSnapshot.error!, - stack: fileSnapshot.stackTrace)); + FlutterError.reportError( + FlutterErrorDetails(exception: fileSnapshot.error!, stack: fileSnapshot.stackTrace)); return const IconButton( icon: Icon(Icons.warning), tooltip: "Failed to load audio-message.", @@ -138,8 +129,7 @@ class _MessageAudioPlayerState extends State onPressed: fileSnapshot.hasData && snapshot.hasData && playerState != null && - playerState.processingState != - ProcessingState.loading + playerState.processingState != ProcessingState.loading ? () { switch (playerState.processingState) { case ProcessingState.idle: @@ -162,15 +152,11 @@ class _MessageAudioPlayerState extends State : null, color: widget.foregroundColor, icon: Icon( - ((_audioPlayer.duration ?? - const Duration(days: 9999)) - - _audioPlayer.position) + ((_audioPlayer.duration ?? const Duration(days: 9999)) - _audioPlayer.position) .inMilliseconds < 10 ? Icons.replay - : ((playerState?.playing ?? false) - ? Icons.pause - : Icons.play_arrow), + : ((playerState?.playing ?? false) ? Icons.pause : Icons.play_arrow), ), ); }, @@ -180,16 +166,14 @@ class _MessageAudioPlayerState extends State builder: (context, snapshot) { _sliderValue = _audioPlayer.duration == null ? 0 - : (_audioPlayer.position.inMilliseconds / - (_audioPlayer.duration!.inMilliseconds)) + : (_audioPlayer.position.inMilliseconds / (_audioPlayer.duration!.inMilliseconds)) .clamp(0, 1); return StatefulBuilder( // Not sure if this makes sense here... builder: (context, setState) { return SliderTheme( data: SliderThemeData( - inactiveTrackColor: - widget.foregroundColor?.withAlpha(100), + inactiveTrackColor: widget.foregroundColor?.withAlpha(100), ), child: Slider( thumbColor: widget.foregroundColor, @@ -203,11 +187,7 @@ class _MessageAudioPlayerState extends State }); _audioPlayer.seek( Duration( - milliseconds: (value * - (_audioPlayer - .duration?.inMilliseconds ?? - 0)) - .round(), + milliseconds: (value * (_audioPlayer.duration?.inMilliseconds ?? 0)).round(), ), ); }, @@ -231,8 +211,10 @@ class _MessageAudioPlayerState extends State builder: (context, snapshot) { return Text( "${snapshot.data?.format() ?? "??"}/${_audioPlayer.duration?.format() ?? "??"}", - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: widget.foregroundColor?.withAlpha(150)), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: widget.foregroundColor?.withAlpha(150)), ); }, ), diff --git a/lib/widgets/messages/message_input_bar.dart b/lib/widgets/messages/message_input_bar.dart index 0f65d8d..ebe1a35 100644 --- a/lib/widgets/messages/message_input_bar.dart +++ b/lib/widgets/messages/message_input_bar.dart @@ -18,11 +18,7 @@ import 'package:recon/widgets/messages/message_attachment_list.dart'; import 'package:record/record.dart'; class MessageInputBar extends StatefulWidget { - const MessageInputBar( - {this.disabled = false, - required this.recipient, - this.onMessageSent, - super.key}); + const MessageInputBar({this.disabled = false, required this.recipient, this.onMessageSent, super.key}); final bool disabled; final Friend recipient; @@ -45,8 +41,7 @@ class _MessageInputBarState extends State { String _currentText = ""; double? _sendProgress; bool get _isRecording => _recordingStartTime != null; - set _isRecording(value) => - _recordingStartTime = value ? DateTime.now() : null; + set _isRecording(value) => _recordingStartTime = value ? DateTime.now() : null; bool _recordingCancelled = false; @override @@ -56,8 +51,7 @@ class _MessageInputBarState extends State { super.dispose(); } - Future sendTextMessage( - ApiClient client, MessagingClient mClient, String content) async { + Future sendTextMessage(ApiClient client, MessagingClient mClient, String content) async { if (content.isEmpty) return; final message = Message( id: Message.generateId(), @@ -71,11 +65,7 @@ class _MessageInputBarState extends State { mClient.sendMessage(message); } - Future sendImageMessage( - ApiClient client, - MessagingClient mClient, - File file, - String machineId, + Future sendImageMessage(ApiClient client, MessagingClient mClient, File file, String machineId, void Function(double progress) progressCallback) async { final record = await RecordApi.uploadImage( client, @@ -94,11 +84,7 @@ class _MessageInputBarState extends State { mClient.sendMessage(message); } - Future sendVoiceMessage( - ApiClient client, - MessagingClient mClient, - File file, - String machineId, + Future sendVoiceMessage(ApiClient client, MessagingClient mClient, File file, String machineId, void Function(double progress) progressCallback) async { final record = await RecordApi.uploadVoiceClip( client, @@ -118,11 +104,7 @@ class _MessageInputBarState extends State { mClient.sendMessage(message); } - Future sendRawFileMessage( - ApiClient client, - MessagingClient mClient, - File file, - String machineId, + Future sendRawFileMessage(ApiClient client, MessagingClient mClient, File file, String machineId, void Function(double progress) progressCallback) async { final record = await RecordApi.uploadRawFile( client, @@ -205,9 +187,8 @@ class _MessageInputBarState extends State { _sendProgress = 0; }); final apiClient = cHolder.apiClient; - await sendVoiceMessage(apiClient, mClient, file, - cHolder.settingsClient.currentSettings.machineId.valueOrDefault, - (progress) { + await sendVoiceMessage( + apiClient, mClient, file, cHolder.settingsClient.currentSettings.machineId.valueOrDefault, (progress) { setState(() { _sendProgress = progress; }); @@ -229,8 +210,7 @@ class _MessageInputBarState extends State { top: false, child: Column( children: [ - if (_isSending && _sendProgress != null) - LinearProgressIndicator(value: _sendProgress), + if (_isSending && _sendProgress != null) LinearProgressIndicator(value: _sendProgress), Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceVariant, @@ -239,8 +219,7 @@ class _MessageInputBarState extends State { duration: const Duration(milliseconds: 200), switchInCurve: Curves.easeOut, switchOutCurve: Curves.easeOut, - transitionBuilder: (Widget child, animation) => - SizeTransition( + transitionBuilder: (Widget child, animation) => SizeTransition( sizeFactor: animation, child: child, ), @@ -252,19 +231,12 @@ class _MessageInputBarState extends State { onPressed: _isSending ? null : () async { - final result = await FilePicker.platform - .pickFiles( - type: FileType.image, - allowMultiple: true); + final result = + await FilePicker.platform.pickFiles(type: FileType.image, allowMultiple: true); if (result != null) { setState(() { _loadedFiles.addAll(result.files - .map((e) => e.path != null - ? ( - FileType.image, - File(e.path!) - ) - : null) + .map((e) => e.path != null ? (FileType.image, File(e.path!)) : null) .whereNotNull()); }); } @@ -276,29 +248,23 @@ class _MessageInputBarState extends State { onPressed: _isSending ? null : () async { - final picture = await _imagePicker - .pickImage(source: ImageSource.camera); + final picture = await _imagePicker.pickImage(source: ImageSource.camera); if (picture == null) { if (context.mounted) { ScaffoldMessenger.of(context) - .showSnackBar(const SnackBar( - content: Text( - "Failed to get image path"))); + .showSnackBar(const SnackBar(content: Text("Failed to get image path"))); } return; } final file = File(picture.path); if (await file.exists()) { setState(() { - _loadedFiles - .add((FileType.image, file)); + _loadedFiles.add((FileType.image, file)); }); } else { if (context.mounted) { ScaffoldMessenger.of(context) - .showSnackBar(const SnackBar( - content: Text( - "Failed to load image file"))); + .showSnackBar(const SnackBar(content: Text("Failed to load image file"))); } } }, @@ -309,16 +275,12 @@ class _MessageInputBarState extends State { onPressed: _isSending ? null : () async { - final result = await FilePicker.platform - .pickFiles( - type: FileType.any, - allowMultiple: true); + final result = + await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: true); if (result != null) { setState(() { _loadedFiles.addAll(result.files - .map((e) => e.path != null - ? (FileType.any, File(e.path!)) - : null) + .map((e) => e.path != null ? (FileType.any, File(e.path!)) : null) .whereNotNull()); }); } @@ -332,8 +294,7 @@ class _MessageInputBarState extends State { (_, _) => MessageAttachmentList( disabled: _isSending, initialFiles: _loadedFiles, - onChange: (List<(FileType, File)> loadedFiles) => - setState(() { + onChange: (List<(FileType, File)> loadedFiles) => setState(() { _loadedFiles.clear(); _loadedFiles.addAll(loadedFiles); }), @@ -345,13 +306,10 @@ class _MessageInputBarState extends State { children: [ AnimatedSwitcher( duration: const Duration(milliseconds: 200), - transitionBuilder: - (Widget child, Animation animation) => - FadeTransition( + transitionBuilder: (Widget child, Animation animation) => FadeTransition( opacity: animation, child: RotationTransition( - turns: Tween(begin: 0.6, end: 1) - .animate(animation), + turns: Tween(begin: 0.6, end: 1).animate(animation), child: child, ), ), @@ -360,9 +318,7 @@ class _MessageInputBarState extends State { onPressed: () {}, icon: Icon( Icons.delete, - color: _recordingCancelled - ? Theme.of(context).colorScheme.error - : null, + color: _recordingCancelled ? Theme.of(context).colorScheme.error : null, ), ), (false, _) => IconButton( @@ -371,9 +327,7 @@ class _MessageInputBarState extends State { ? null : () { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - "Sorry, this feature is not yet available"))); + const SnackBar(content: Text("Sorry, this feature is not yet available"))); return; // setState(() { // _attachmentPickerOpen = true; @@ -392,10 +346,8 @@ class _MessageInputBarState extends State { await showDialog( context: context, builder: (context) => AlertDialog( - title: const Text( - "Remove all attachments"), - content: const Text( - "This will remove all attachments, are you sure?"), + title: const Text("Remove all attachments"), + content: const Text("This will remove all attachments, are you sure?"), actions: [ TextButton( onPressed: () { @@ -407,8 +359,7 @@ class _MessageInputBarState extends State { onPressed: () { setState(() { _loadedFiles.clear(); - _attachmentPickerOpen = - false; + _attachmentPickerOpen = false; }); Navigator.of(context).pop(); }, @@ -430,8 +381,7 @@ class _MessageInputBarState extends State { ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 4), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4), child: Stack( children: [ TextField( @@ -453,12 +403,9 @@ class _MessageInputBarState extends State { style: Theme.of(context).textTheme.bodyLarge, decoration: InputDecoration( isDense: true, - hintText: _isRecording - ? "" - : "Message ${widget.recipient.username}...", + hintText: _isRecording ? "" : "Message ${widget.recipient.username}...", hintMaxLines: 1, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, vertical: 12), + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), fillColor: Colors.black26, filled: true, border: OutlineInputBorder( @@ -468,9 +415,7 @@ class _MessageInputBarState extends State { ), AnimatedSwitcher( duration: const Duration(milliseconds: 200), - transitionBuilder: - (Widget child, Animation animation) => - FadeTransition( + transitionBuilder: (Widget child, Animation animation) => FadeTransition( opacity: animation, child: SlideTransition( position: Tween( @@ -482,41 +427,33 @@ class _MessageInputBarState extends State { ), child: _isRecording ? Padding( - padding: const EdgeInsets.symmetric( - vertical: 12.0), + padding: const EdgeInsets.symmetric(vertical: 12.0), child: _recordingCancelled ? Row( - mainAxisAlignment: - MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ const SizedBox( width: 8, ), const Padding( - padding: EdgeInsets.symmetric( - horizontal: 8.0), + padding: EdgeInsets.symmetric(horizontal: 8.0), child: Icon( Icons.cancel, color: Colors.red, size: 16, ), ), - Text("Cancel Recording", - style: Theme.of(context) - .textTheme - .titleMedium), + Text("Cancel Recording", style: Theme.of(context).textTheme.titleMedium), ], ) : Row( - mainAxisAlignment: - MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ const SizedBox( width: 8, ), const Padding( - padding: EdgeInsets.symmetric( - horizontal: 8.0), + padding: EdgeInsets.symmetric(horizontal: 8.0), child: Icon( Icons.circle, color: Colors.red, @@ -524,14 +461,10 @@ class _MessageInputBarState extends State { ), ), StreamBuilder( - stream: - _recordingDurationStream(), + stream: _recordingDurationStream(), builder: (context, snapshot) { - return Text( - "Recording: ${snapshot.data?.format()}", - style: Theme.of(context) - .textTheme - .titleMedium); + return Text("Recording: ${snapshot.data?.format()}", + style: Theme.of(context).textTheme.titleMedium); }), ], ), @@ -544,13 +477,10 @@ class _MessageInputBarState extends State { ), AnimatedSwitcher( duration: const Duration(milliseconds: 200), - transitionBuilder: - (Widget child, Animation animation) => - FadeTransition( + transitionBuilder: (Widget child, Animation animation) => FadeTransition( opacity: animation, child: RotationTransition( - turns: Tween(begin: 0.5, end: 1) - .animate(animation), + turns: Tween(begin: 0.5, end: 1).animate(animation), child: child, ), ), @@ -563,12 +493,9 @@ class _MessageInputBarState extends State { ? null : () async { final cHolder = ClientHolder.of(context); - final sMsgnr = - ScaffoldMessenger.of(context); - final settings = - cHolder.settingsClient.currentSettings; - final toSend = List<(FileType, File)>.from( - _loadedFiles); + final sMsgnr = ScaffoldMessenger.of(context); + final settings = cHolder.settingsClient.currentSettings; + final toSend = List<(FileType, File)>.from(_loadedFiles); setState(() { _isSending = true; _sendProgress = 0; @@ -586,8 +513,7 @@ class _MessageInputBarState extends State { file.$2, settings.machineId.valueOrDefault, (progress) => setState(() { - _sendProgress = totalProgress + - progress * 1 / toSend.length; + _sendProgress = totalProgress + progress * 1 / toSend.length; }), ); } else { @@ -596,12 +522,8 @@ class _MessageInputBarState extends State { mClient, file.$2, settings.machineId.valueOrDefault, - (progress) => setState(() => - _sendProgress = - totalProgress + - progress * - 1 / - toSend.length)); + (progress) => setState( + () => _sendProgress = totalProgress + progress * 1 / toSend.length)); } } setState(() { @@ -609,22 +531,15 @@ class _MessageInputBarState extends State { }); if (_currentText.isNotEmpty) { - await sendTextMessage( - cHolder.apiClient, - mClient, - _messageTextController.text); + await sendTextMessage(cHolder.apiClient, mClient, _messageTextController.text); } _messageTextController.clear(); _currentText = ""; _loadedFiles.clear(); _attachmentPickerOpen = false; } catch (e, s) { - FlutterError.reportError( - FlutterErrorDetails( - exception: e, stack: s)); - sMsgnr.showSnackBar(SnackBar( - content: Text( - "Failed to send a message: $e"))); + FlutterError.reportError(FlutterErrorDetails(exception: e, stack: s)); + sMsgnr.showSnackBar(SnackBar(content: Text("Failed to send a message: $e"))); } setState(() { _isSending = false; @@ -642,9 +557,7 @@ class _MessageInputBarState extends State { ? null : (_) async { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - "Sorry, this feature is not yet available"))); + const SnackBar(content: Text("Sorry, this feature is not yet available"))); return; // HapticFeedback.vibrate(); // final hadToAsk = diff --git a/lib/widgets/messages/messages_list.dart b/lib/widgets/messages/messages_list.dart index d9c8392..a3311c8 100644 --- a/lib/widgets/messages/messages_list.dart +++ b/lib/widgets/messages/messages_list.dart @@ -17,8 +17,7 @@ class MessagesList extends StatefulWidget { State createState() => _MessagesListState(); } -class _MessagesListState extends State - with SingleTickerProviderStateMixin { +class _MessagesListState extends State with SingleTickerProviderStateMixin { final ScrollController _sessionListScrollController = ScrollController(); bool _showSessionListScrollChevron = false; @@ -36,8 +35,7 @@ class _MessagesListState extends State void initState() { super.initState(); _sessionListScrollController.addListener(() { - if (_sessionListScrollController.position.maxScrollExtent > 0 && - !_showSessionListScrollChevron) { + if (_sessionListScrollController.position.maxScrollExtent > 0 && !_showSessionListScrollChevron) { setState(() { _showSessionListScrollChevron = true; }); @@ -58,9 +56,7 @@ class _MessagesListState extends State return Consumer(builder: (context, mClient, _) { final friend = mClient.selectedFriend ?? Friend.empty(); final cache = mClient.getUserMessageCache(friend.id); - final sessions = friend.userStatus.decodedSessions - .where((element) => element.isVisible) - .toList(); + final sessions = friend.userStatus.decodedSessions.where((element) => element.isVisible).toList(); return Scaffold( appBar: AppBar( title: Row( @@ -77,10 +73,7 @@ class _MessagesListState extends State child: Icon( Icons.dns, size: 18, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer - .withAlpha(150), + color: Theme.of(context).colorScheme.onSecondaryContainer.withAlpha(150), ), ), ], @@ -110,8 +103,8 @@ class _MessagesListState extends State if (sessions.isNotEmpty) AnimatedSwitcher( duration: const Duration(milliseconds: 200), - transitionBuilder: (child, animation) => SizeTransition( - sizeFactor: animation, axis: Axis.vertical, child: child), + transitionBuilder: (child, animation) => + SizeTransition(sizeFactor: animation, axis: Axis.vertical, child: child), child: sessions.isEmpty || !_sessionListOpen ? null : Container( @@ -139,8 +132,7 @@ class _MessagesListState extends State child: Align( alignment: Alignment.centerRight, child: Container( - padding: const EdgeInsets.only( - left: 16, right: 4, top: 1, bottom: 1), + padding: const EdgeInsets.only(left: 16, right: 4, top: 1, bottom: 1), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.centerLeft, @@ -190,13 +182,11 @@ class _MessagesListState extends State children: [ const Icon(Icons.message_outlined), Padding( - padding: - const EdgeInsets.symmetric(vertical: 24), + padding: const EdgeInsets.symmetric(vertical: 24), child: Text( "There are no messages here\nWhy not say hello?", textAlign: TextAlign.center, - style: - Theme.of(context).textTheme.titleMedium, + style: Theme.of(context).textTheme.titleMedium, ), ) ], @@ -207,8 +197,7 @@ class _MessagesListState extends State create: (BuildContext context) => AudioCacheClient(), child: ListView.builder( reverse: true, - physics: const BouncingScrollPhysics( - decelerationRate: ScrollDecelerationRate.fast), + physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast), itemCount: cache.messages.length, itemBuilder: (context, index) { final entry = cache.messages[index]; diff --git a/lib/widgets/messages/messages_session_header.dart b/lib/widgets/messages/messages_session_header.dart index ca9e70f..9c4d96f 100644 --- a/lib/widgets/messages/messages_session_header.dart +++ b/lib/widgets/messages/messages_session_header.dart @@ -17,15 +17,12 @@ class SessionTile extends StatelessWidget { foregroundColor: Theme.of(context).colorScheme.onSurface, ), onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => SessionView(session: session))); + Navigator.of(context).push(MaterialPageRoute(builder: (context) => SessionView(session: session))); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - GenericAvatar( - imageUri: Aux.resdbToHttp(session.thumbnailUrl), - placeholderIcon: Icons.no_photography), + GenericAvatar(imageUri: Aux.resdbToHttp(session.thumbnailUrl), placeholderIcon: Icons.no_photography), Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), child: Column( @@ -35,11 +32,10 @@ class SessionTile extends StatelessWidget { FormattedText(session.formattedName), Text( "${session.sessionUsers.length.toString().padLeft(2, "0")}/${session.maxUsers.toString().padLeft(2, "0")} active users", - style: Theme.of(context).textTheme.labelMedium?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(.6)), + style: Theme.of(context) + .textTheme + .labelMedium + ?.copyWith(color: Theme.of(context).colorScheme.onSurface.withOpacity(.6)), ) ], ), diff --git a/lib/widgets/sessions/session_list_app_bar.dart b/lib/widgets/sessions/session_list_app_bar.dart index c09b415..205eee7 100644 --- a/lib/widgets/sessions/session_list_app_bar.dart +++ b/lib/widgets/sessions/session_list_app_bar.dart @@ -1,8 +1,7 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:recon/clients/session_client.dart'; import 'package:recon/widgets/sessions/session_filter_dialog.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; class SessionListAppBar extends StatefulWidget { const SessionListAppBar({super.key}); diff --git a/lib/widgets/settings_app_bar.dart b/lib/widgets/settings_app_bar.dart index 0a7846c..4a2ed02 100644 --- a/lib/widgets/settings_app_bar.dart +++ b/lib/widgets/settings_app_bar.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; class SettingsAppBar extends StatelessWidget { const SettingsAppBar({super.key}); diff --git a/test/widget_test.dart b/test/widget_test.dart index 60fcb26..7977cae 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -7,7 +7,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; - import 'package:recon/main.dart'; void main() {