From f5813a5489efd872b8de582ea5cff14b902360ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Thu, 23 May 2024 17:41:51 +0200 Subject: [PATCH] debug view && priority in listview --- flutter/README.md | 11 + flutter/lib/components/layout/app_bar.dart | 50 +++-- flutter/lib/components/layout/scaffold.dart | 15 +- flutter/lib/nav_layout.dart | 7 +- flutter/lib/pages/debug/debug_colors.dart | 126 +++++++++++ flutter/lib/pages/debug/debug_main.dart | 64 ++++++ .../lib/pages/debug/debug_persistence.dart | 13 ++ flutter/lib/pages/debug/debug_requests.dart | 13 ++ .../lib/pages/message_list/message_list.dart | 5 +- .../pages/message_list/message_list_item.dart | 209 ++++++++++-------- .../lib/pages/message_view/message_view.dart | 26 ++- flutter/lib/pages/send/root.dart | 16 ++ 12 files changed, 432 insertions(+), 123 deletions(-) create mode 100644 flutter/README.md create mode 100644 flutter/lib/pages/debug/debug_colors.dart create mode 100644 flutter/lib/pages/debug/debug_main.dart create mode 100644 flutter/lib/pages/debug/debug_persistence.dart create mode 100644 flutter/lib/pages/debug/debug_requests.dart diff --git a/flutter/README.md b/flutter/README.md new file mode 100644 index 0000000..1046744 --- /dev/null +++ b/flutter/README.md @@ -0,0 +1,11 @@ +### Links + + + - https://pub.dev/packages/font_awesome_flutter + - https://fontawesome.com/search + + - https://docs.flutter.dev/ui/widgets + - https://docs.flutter.dev/ui/widgets/material + + + \ No newline at end of file diff --git a/flutter/lib/components/layout/app_bar.dart b/flutter/lib/components/layout/app_bar.dart index aad20af..b690ae6 100644 --- a/flutter/lib/components/layout/app_bar.dart +++ b/flutter/lib/components/layout/app_bar.dart @@ -1,37 +1,55 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; +import 'package:simplecloudnotifier/pages/debug/debug_main.dart'; import 'package:simplecloudnotifier/state/app_theme.dart'; class SCNAppBar extends StatelessWidget implements PreferredSizeWidget { - const SCNAppBar({Key? key, this.title}) : super(key: key); + const SCNAppBar({ + Key? key, + required this.title, + required this.showThemeSwitch, + required this.showDebug, + required this.showSearch, + }) : super(key: key); final String? title; + final bool showThemeSwitch; + final bool showDebug; + final bool showSearch; @override Widget build(BuildContext context) { return AppBar( title: Text(title ?? 'Simple Cloud Notifier 2.0'), actions: [ - Consumer( - builder: (context, appTheme, child) => IconButton( - icon: Icon(appTheme.darkMode ? FontAwesomeIcons.solidSun : FontAwesomeIcons.solidMoon), + if (showThemeSwitch) + Consumer( + builder: (context, appTheme, child) => IconButton( + icon: Icon(appTheme.darkMode ? FontAwesomeIcons.solidSun : FontAwesomeIcons.solidMoon), + tooltip: 'Debug', + onPressed: () { + appTheme.switchDarkMode(); + }, + ), + ), + if (!showThemeSwitch) SizedBox.square(dimension: 40), + if (showDebug) + IconButton( + icon: const Icon(FontAwesomeIcons.solidSpiderBlackWidow), tooltip: 'Debug', onPressed: () { - appTheme.switchDarkMode(); + Navigator.push(context, MaterialPageRoute(builder: (context) => DebugMainPage())); }, ), - ), - IconButton( - icon: const Icon(FontAwesomeIcons.solidSpiderBlackWidow), - tooltip: 'Debug', - onPressed: () {}, - ), - IconButton( - icon: const Icon(FontAwesomeIcons.solidMagnifyingGlass), - tooltip: 'Search', - onPressed: () {}, - ), + if (!showDebug) SizedBox.square(dimension: 40), + if (showSearch) + IconButton( + icon: const Icon(FontAwesomeIcons.solidMagnifyingGlass), + tooltip: 'Search', + onPressed: () {}, + ), + if (!showSearch) SizedBox.square(dimension: 40), ], backgroundColor: Theme.of(context).secondaryHeaderColor, ); diff --git a/flutter/lib/components/layout/scaffold.dart b/flutter/lib/components/layout/scaffold.dart index 9aff4e7..aca4f23 100644 --- a/flutter/lib/components/layout/scaffold.dart +++ b/flutter/lib/components/layout/scaffold.dart @@ -2,16 +2,29 @@ import 'package:flutter/material.dart'; import 'package:simplecloudnotifier/components/layout/app_bar.dart'; class SCNScaffold extends StatelessWidget { - const SCNScaffold({Key? key, required this.child, this.title}) : super(key: key); + const SCNScaffold({ + Key? key, + required this.child, + this.title, + this.showThemeSwitch = true, + this.showDebug = true, + this.showSearch = true, + }) : super(key: key); final Widget child; final String? title; + final bool showThemeSwitch; + final bool showDebug; + final bool showSearch; @override Widget build(BuildContext context) { return Scaffold( appBar: SCNAppBar( title: title, + showThemeSwitch: showThemeSwitch, + showDebug: showDebug, + showSearch: showSearch, ), body: child, ); diff --git a/flutter/lib/nav_layout.dart b/flutter/lib/nav_layout.dart index 30e6081..ac5aa51 100644 --- a/flutter/lib/nav_layout.dart +++ b/flutter/lib/nav_layout.dart @@ -42,7 +42,12 @@ class _SCNNavLayoutState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: SCNAppBar(), + appBar: SCNAppBar( + title: null, + showDebug: true, + showSearch: _selectedIndex == 0 || _selectedIndex == 1, + showThemeSwitch: true, + ), body: _subPages.elementAt(_selectedIndex), bottomNavigationBar: _buildNavBar(context), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, diff --git a/flutter/lib/pages/debug/debug_colors.dart b/flutter/lib/pages/debug/debug_colors.dart new file mode 100644 index 0000000..f09f038 --- /dev/null +++ b/flutter/lib/pages/debug/debug_colors.dart @@ -0,0 +1,126 @@ +import 'package:flutter/material.dart'; + +class DebugColorsPage extends StatefulWidget { + @override + _DebugColorsPageState createState() => _DebugColorsPageState(); +} + +class _DebugColorsPageState extends State { + @override + Widget build(BuildContext context) { + return Container( + child: SingleChildScrollView( + child: Column( + children: listColors(context), + ), + ), + ); + } + + List listColors(BuildContext context) { + return [ + buildCol("primaryColor", Theme.of(context).primaryColor), + buildCol("primaryColorDark", Theme.of(context).primaryColorDark), + buildCol("primaryColorLight", Theme.of(context).primaryColorLight), + buildCol("secondaryHeaderColor", Theme.of(context).secondaryHeaderColor), + buildCol("disabledColor", Theme.of(context).disabledColor), + buildCol("splashColor", Theme.of(context).splashColor), + Divider(), + buildCol("canvasColor", Theme.of(context).canvasColor), + buildCol("cardColor", Theme.of(context).cardColor), + buildCol("dialogBackgroundColor", Theme.of(context).dialogBackgroundColor), + buildCol("dividerColor", Theme.of(context).dividerColor), + buildCol("focusColor", Theme.of(context).focusColor), + buildCol("highlightColor", Theme.of(context).highlightColor), + buildCol("hintColor", Theme.of(context).hintColor), + buildCol("hoverColor", Theme.of(context).hoverColor), + buildCol("indicatorColor", Theme.of(context).indicatorColor), + buildCol("scaffoldBackgroundColor", Theme.of(context).scaffoldBackgroundColor), + buildCol("shadowColor", Theme.of(context).shadowColor), + buildCol("unselectedWidgetColor", Theme.of(context).unselectedWidgetColor), + Divider(), + buildCol("colorScheme.primary", Theme.of(context).colorScheme.primary), + buildCol("colorScheme.onPrimary", Theme.of(context).colorScheme.onPrimary), + buildCol("colorScheme.primaryContainer", Theme.of(context).colorScheme.primaryContainer), + buildCol("colorScheme.onPrimaryContainer", Theme.of(context).colorScheme.onPrimaryContainer), + buildCol("colorScheme.inversePrimary", Theme.of(context).colorScheme.inversePrimary), + buildCol("colorScheme.secondary", Theme.of(context).colorScheme.secondary), + buildCol("colorScheme.onSecondary", Theme.of(context).colorScheme.onSecondary), + buildCol("colorScheme.secondaryContainer", Theme.of(context).colorScheme.secondaryContainer), + buildCol("colorScheme.onSecondaryContainer", Theme.of(context).colorScheme.onSecondaryContainer), + buildCol("colorScheme.tertiary", Theme.of(context).colorScheme.tertiary), + buildCol("colorScheme.onTertiary", Theme.of(context).colorScheme.onTertiary), + buildCol("colorScheme.tertiaryContainer", Theme.of(context).colorScheme.tertiaryContainer), + buildCol("colorScheme.onTertiaryContainer", Theme.of(context).colorScheme.onTertiaryContainer), + buildCol("colorScheme.surface", Theme.of(context).colorScheme.surface), + buildCol("colorScheme.onSurface", Theme.of(context).colorScheme.onSurface), + buildCol("colorScheme.surfaceTint", Theme.of(context).colorScheme.surfaceTint), + buildCol("colorScheme.surfaceVariant", Theme.of(context).colorScheme.surfaceVariant), + buildCol("colorScheme.inverseSurface", Theme.of(context).colorScheme.inverseSurface), + buildCol("colorScheme.onInverseSurface", Theme.of(context).colorScheme.onInverseSurface), + buildCol("colorScheme.background", Theme.of(context).colorScheme.background), + buildCol("colorScheme.onBackground", Theme.of(context).colorScheme.onBackground), + buildCol("colorScheme.error", Theme.of(context).colorScheme.error), + buildCol("colorScheme.onError", Theme.of(context).colorScheme.onError), + buildCol("colorScheme.errorContainer", Theme.of(context).colorScheme.errorContainer), + buildCol("colorScheme.onErrorContainer", Theme.of(context).colorScheme.onErrorContainer), + buildCol("colorScheme.outline", Theme.of(context).colorScheme.outline), + buildCol("colorScheme.outlineVariant", Theme.of(context).colorScheme.outlineVariant), + buildCol("colorScheme.shadow", Theme.of(context).colorScheme.shadow), + buildCol("colorScheme.scrim", Theme.of(context).colorScheme.scrim), + Divider(), + buildCol("primaryTextTheme.bodyLarge.backgroundColor", Theme.of(context).primaryTextTheme.bodyLarge?.backgroundColor), + buildCol("primaryTextTheme.bodyLarge.color", Theme.of(context).primaryTextTheme.bodyLarge?.color), + buildCol("primaryTextTheme.displayLarge.backgroundColor", Theme.of(context).primaryTextTheme.displayLarge?.backgroundColor), + buildCol("primaryTextTheme.displayLarge.color", Theme.of(context).primaryTextTheme.displayLarge?.color), + buildCol("primaryTextTheme.headlineLarge.backgroundColor", Theme.of(context).primaryTextTheme.headlineLarge?.backgroundColor), + buildCol("primaryTextTheme.headlineLarge.color", Theme.of(context).primaryTextTheme.headlineLarge?.color), + buildCol("primaryTextTheme.labelLarge.backgroundColor", Theme.of(context).primaryTextTheme.labelLarge?.backgroundColor), + buildCol("primaryTextTheme.labelLarge.color", Theme.of(context).primaryTextTheme.labelLarge?.color), + buildCol("primaryTextTheme.titleLarge.backgroundColor", Theme.of(context).primaryTextTheme.titleLarge?.backgroundColor), + buildCol("primaryTextTheme.titleLarge.color", Theme.of(context).primaryTextTheme.titleLarge?.color), + buildCol("textTheme.bodyLarge.backgroundColor", Theme.of(context).textTheme.bodyLarge?.backgroundColor), + buildCol("textTheme.bodyLarge.color", Theme.of(context).textTheme.bodyLarge?.color), + buildCol("textTheme.displayLarge.backgroundColor", Theme.of(context).textTheme.displayLarge?.backgroundColor), + buildCol("textTheme.displayLarge.color", Theme.of(context).textTheme.displayLarge?.color), + buildCol("textTheme.headlineLarge.backgroundColor", Theme.of(context).textTheme.headlineLarge?.backgroundColor), + buildCol("textTheme.headlineLarge.color", Theme.of(context).textTheme.headlineLarge?.color), + buildCol("textTheme.labelLarge.backgroundColor", Theme.of(context).textTheme.labelLarge?.backgroundColor), + buildCol("textTheme.labelLarge.color", Theme.of(context).textTheme.labelLarge?.color), + buildCol("textTheme.titleLarge.backgroundColor", Theme.of(context).textTheme.titleLarge?.backgroundColor), + buildCol("textTheme.titleLarge.color", Theme.of(context).textTheme.titleLarge?.color), + Divider(), + buildCol("iconTheme.color", Theme.of(context).iconTheme.color), + buildCol("primaryIconTheme.color", Theme.of(context).primaryIconTheme.color), + buildCol("appBarTheme.foregroundColor", Theme.of(context).appBarTheme.foregroundColor), + buildCol("appBarTheme.backgroundColor", Theme.of(context).appBarTheme.backgroundColor), + buildCol("badgeTheme.textColor", Theme.of(context).badgeTheme.textColor), + buildCol("badgeTheme.backgroundColor", Theme.of(context).badgeTheme.backgroundColor), + buildCol("bannerTheme.backgroundColor", Theme.of(context).bannerTheme.backgroundColor), + buildCol("bottomAppBarTheme.color", Theme.of(context).bottomAppBarTheme.color), + buildCol("buttonTheme.colorScheme.background", Theme.of(context).buttonTheme.colorScheme?.background), + buildCol("buttonTheme.colorScheme.primary", Theme.of(context).buttonTheme.colorScheme?.primary), + buildCol("buttonTheme.colorScheme.secondary", Theme.of(context).buttonTheme.colorScheme?.secondary), + buildCol("cardTheme.color", Theme.of(context).cardTheme.color), + ]; + } + + Widget buildCol(String key, Color? value) { + return Row( + children: [ + Padding( + padding: EdgeInsets.all(4), + child: Container( + width: 20, + decoration: BoxDecoration( + border: Border.all(color: Colors.black), + color: value ?? Color.fromARGB(0, 0, 0, 0), + ), + height: 20, + ), + ), + Expanded(child: Text(key)) + ], + ); + } +} diff --git a/flutter/lib/pages/debug/debug_main.dart b/flutter/lib/pages/debug/debug_main.dart new file mode 100644 index 0000000..838fa35 --- /dev/null +++ b/flutter/lib/pages/debug/debug_main.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:simplecloudnotifier/components/layout/scaffold.dart'; +import 'package:simplecloudnotifier/pages/debug/debug_colors.dart'; +import 'package:simplecloudnotifier/pages/debug/debug_persistence.dart'; +import 'package:simplecloudnotifier/pages/debug/debug_requests.dart'; + +class DebugMainPage extends StatefulWidget { + @override + _DebugMainPageState createState() => _DebugMainPageState(); +} + +enum DebugMainPageSubPage { colors, requests, persistence } + +class _DebugMainPageState extends State { + final Map _subpages = { + DebugMainPageSubPage.colors: DebugColorsPage(), + DebugMainPageSubPage.requests: DebugRequestsPage(), + DebugMainPageSubPage.persistence: DebugPersistencePage(), + }; + + DebugMainPageSubPage _subPage = DebugMainPageSubPage.colors; + + @override + Widget build(BuildContext context) { + return SCNScaffold( + title: 'Debug', + showSearch: false, + showDebug: false, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + buildSegButton(context), + ], + ), + ), + Expanded( + child: _subpages[_subPage]!, + ), + ], + ), + ); + } + + Widget buildSegButton(BuildContext context) { + return SegmentedButton( + showSelectedIcon: false, + segments: const >[ + ButtonSegment(value: DebugMainPageSubPage.colors, label: Text('Theme')), + ButtonSegment(value: DebugMainPageSubPage.requests, label: Text('Requests')), + ButtonSegment(value: DebugMainPageSubPage.persistence, label: Text('Persistence')), + ], + selected: {_subPage}, + onSelectionChanged: (Set v) { + setState(() { + _subPage = v.first; + }); + }, + ); + } +} diff --git a/flutter/lib/pages/debug/debug_persistence.dart b/flutter/lib/pages/debug/debug_persistence.dart new file mode 100644 index 0000000..fb0d9be --- /dev/null +++ b/flutter/lib/pages/debug/debug_persistence.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +class DebugPersistencePage extends StatefulWidget { + @override + _DebugPersistencePageState createState() => _DebugPersistencePageState(); +} + +class _DebugPersistencePageState extends State { + @override + Widget build(BuildContext context) { + return Container(/* Add your UI components here */); + } +} diff --git a/flutter/lib/pages/debug/debug_requests.dart b/flutter/lib/pages/debug/debug_requests.dart new file mode 100644 index 0000000..96e7850 --- /dev/null +++ b/flutter/lib/pages/debug/debug_requests.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +class DebugRequestsPage extends StatefulWidget { + @override + _DebugRequestsPageState createState() => _DebugRequestsPageState(); +} + +class _DebugRequestsPageState extends State { + @override + Widget build(BuildContext context) { + return Container(/* Add your UI components here */); + } +} diff --git a/flutter/lib/pages/message_list/message_list.dart b/flutter/lib/pages/message_list/message_list.dart index c5d4d58..38b0702 100644 --- a/flutter/lib/pages/message_list/message_list.dart +++ b/flutter/lib/pages/message_list/message_list.dart @@ -76,10 +76,7 @@ class _MessageListPageState extends State { message: item, allChannels: _channels ?? {}, onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => MessageViewPage(messageID: item.messageID)), - ); + Navigator.push(context, MaterialPageRoute(builder: (context) => MessageViewPage(message: item))); }, ), ), diff --git a/flutter/lib/pages/message_list/message_list_item.dart b/flutter/lib/pages/message_list/message_list_item.dart index 879ff87..b2742be 100644 --- a/flutter/lib/pages/message_list/message_list_item.dart +++ b/flutter/lib/pages/message_list/message_list_item.dart @@ -1,13 +1,14 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:simplecloudnotifier/models/channel.dart'; import 'package:simplecloudnotifier/models/message.dart'; import 'package:intl/intl.dart'; class MessageListItem extends StatelessWidget { static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm'); - static final _lineCount = 3; + static final _lineCount = 3; //TODO setting const MessageListItem({ required this.message, @@ -23,107 +24,125 @@ class MessageListItem extends StatelessWidget { @override Widget build(BuildContext context) { if (showChannel(message)) { - return Card.filled( - margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - //clipBehavior: Clip.hardEdge, // nto needed, because our borderRadius is 0 anyway - child: InkWell( - splashColor: Theme.of(context).primaryColor.withAlpha(30), - onTap: onPressed, - child: Padding( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), - margin: const EdgeInsets.fromLTRB(0, 0, 4, 0), - decoration: BoxDecoration( - color: Theme.of(context).hintColor, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - child: Text( - resolveChannelName(message), - style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).cardColor, fontSize: 12), - overflow: TextOverflow.clip, - maxLines: 1, - ), - ), - Expanded(child: SizedBox()), - Text( - _dateFormat.format(DateTime.parse(message.timestamp).toLocal()), - style: const TextStyle(fontWeight: FontWeight.normal, fontSize: 11), - overflow: TextOverflow.clip, - maxLines: 1, - ), - ], - ), - SizedBox(height: 4), - Text( - processTitle(message.title), - style: const TextStyle(fontWeight: FontWeight.bold), - overflow: TextOverflow.ellipsis, - maxLines: 3, - ), - Text( - processContent(message.content), - style: TextStyle(color: Theme.of(context).textTheme.bodyLarge?.color?.withAlpha(160)), - overflow: TextOverflow.ellipsis, - maxLines: _lineCount, - ), - ], - ), - ), - ), - ); + return buildWithChannel(context); } else { - return Card.filled( - margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - //clipBehavior: Clip.hardEdge, // nto needed, because our borderRadius is 0 anyway - child: InkWell( - splashColor: Theme.of(context).primaryColor.withAlpha(30), - onTap: onPressed, - child: Padding( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Text( - processTitle(message.title), - style: const TextStyle(fontWeight: FontWeight.bold), - overflow: TextOverflow.ellipsis, - maxLines: 3, - ), + return buildWithoutChannel(context); + } + } + + Card buildWithoutChannel(BuildContext context) { + return Card.filled( + margin: EdgeInsets.fromLTRB(0, 4, 0, 4), + shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), + color: (message.priority == 2) ? Theme.of(context).colorScheme.errorContainer : Theme.of(context).cardTheme.color, + //clipBehavior: Clip.hardEdge, // nto needed, because our borderRadius is 0 anyway + child: InkWell( + splashColor: Theme.of(context).splashColor, + onTap: onPressed, + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (message.priority == 2) FaIcon(FontAwesomeIcons.solidTriangleExclamation, size: 16, color: Theme.of(context).colorScheme.error), + if (message.priority == 2) SizedBox(width: 4), + if (message.priority == 0) FaIcon(FontAwesomeIcons.solidDown, size: 16, color: Theme.of(context).colorScheme.primary), + if (message.priority == 0) SizedBox(width: 4), + Expanded( + child: Text( + processTitle(message.title), + style: const TextStyle(fontWeight: FontWeight.bold), + overflow: TextOverflow.ellipsis, + maxLines: 3, ), - Text( - _dateFormat.format(DateTime.parse(message.timestamp).toLocal()), - style: const TextStyle(fontWeight: FontWeight.normal, fontSize: 11), + ), + Text( + _dateFormat.format(DateTime.parse(message.timestamp).toLocal()), + style: const TextStyle(fontWeight: FontWeight.normal, fontSize: 11), + overflow: TextOverflow.clip, + maxLines: 1, + ), + ], + ), + SizedBox(height: 4), + Text( + processContent(message.content), + style: TextStyle(color: Theme.of(context).textTheme.bodyLarge?.color?.withAlpha(160)), + overflow: TextOverflow.ellipsis, + maxLines: _lineCount, + ), + ], + ), + ), + ), + ); + } + + Card buildWithChannel(BuildContext context) { + return Card.filled( + margin: EdgeInsets.fromLTRB(0, 4, 0, 4), + shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), + //clipBehavior: Clip.hardEdge, // nto needed, because our borderRadius is 0 anyway + color: (message.priority == 2) ? Theme.of(context).colorScheme.errorContainer : Theme.of(context).cardTheme.color, + child: InkWell( + splashColor: Theme.of(context).splashColor, + onTap: onPressed, + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (message.priority == 2) FaIcon(FontAwesomeIcons.solidTriangleExclamation, size: 16, color: Theme.of(context).colorScheme.error), + if (message.priority == 2) SizedBox(width: 4), + if (message.priority == 0) FaIcon(FontAwesomeIcons.solidDown, size: 16, color: Theme.of(context).colorScheme.primary), + if (message.priority == 0) SizedBox(width: 4), + Container( + padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), + margin: const EdgeInsets.fromLTRB(0, 0, 4, 0), + decoration: BoxDecoration( + color: Theme.of(context).hintColor, + borderRadius: BorderRadius.all(Radius.circular(4)), + ), + child: Text( + resolveChannelName(message), + style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).cardColor, fontSize: 12), overflow: TextOverflow.clip, maxLines: 1, ), - ], - ), - SizedBox(height: 4), - Text( - processContent(message.content), - style: TextStyle(color: Theme.of(context).textTheme.bodyLarge?.color?.withAlpha(160)), - overflow: TextOverflow.ellipsis, - maxLines: _lineCount, - ), - ], - ), + ), + Expanded(child: SizedBox()), + Text( + _dateFormat.format(DateTime.parse(message.timestamp).toLocal()), + style: const TextStyle(fontWeight: FontWeight.normal, fontSize: 11), + overflow: TextOverflow.clip, + maxLines: 1, + ), + ], + ), + SizedBox(height: 4), + Text( + processTitle(message.title), + style: const TextStyle(fontWeight: FontWeight.bold), + overflow: TextOverflow.ellipsis, + maxLines: 3, + ), + Text( + processContent(message.content), + style: TextStyle(color: Theme.of(context).textTheme.bodyLarge?.color?.withAlpha(160)), + overflow: TextOverflow.ellipsis, + maxLines: _lineCount, + ), + ], ), ), - ); - } + ), + ); } processContent(String? v) { diff --git a/flutter/lib/pages/message_view/message_view.dart b/flutter/lib/pages/message_view/message_view.dart index edc59c0..808b0eb 100644 --- a/flutter/lib/pages/message_view/message_view.dart +++ b/flutter/lib/pages/message_view/message_view.dart @@ -6,9 +6,9 @@ import 'package:simplecloudnotifier/models/message.dart'; import 'package:simplecloudnotifier/state/user_account.dart'; class MessageViewPage extends StatefulWidget { - const MessageViewPage({super.key, required this.messageID}); + const MessageViewPage({super.key, required this.message}); - final String messageID; + final Message message; // Potentially trimmed @override State createState() => _MessageViewPageState(); @@ -26,7 +26,7 @@ class _MessageViewPageState extends State { Future fetchMessage() async { final acc = Provider.of(context, listen: false); - return await APIClient.getMessage(acc.auth!, widget.messageID); + return await APIClient.getMessage(acc.auth!, widget.message.messageID); } @override @@ -38,18 +38,32 @@ class _MessageViewPageState extends State { Widget build(BuildContext context) { return SCNScaffold( title: 'Message', + showSearch: false, child: FutureBuilder( future: futureMessage, builder: (context, snapshot) { if (snapshot.hasData) { - return Center(child: Text(snapshot.data!.title)); + return buildMessageView(snapshot.data!, false); } else if (snapshot.hasError) { return Center(child: Text('${snapshot.error}')); //TODO nice error page + } else if (!widget.message.trimmed) { + return buildMessageView(widget.message, true); + } else { + return const Center(child: CircularProgressIndicator()); } - - return const Center(child: CircularProgressIndicator()); }, ), ); } + + Widget buildMessageView(Message message, bool loading) { + return Center( + child: Column( + children: [ + Text(message.title), + Text(message.content ?? ''), + ], + ), + ); + } } diff --git a/flutter/lib/pages/send/root.dart b/flutter/lib/pages/send/root.dart index 7dc9587..c4ba722 100644 --- a/flutter/lib/pages/send/root.dart +++ b/flutter/lib/pages/send/root.dart @@ -101,6 +101,14 @@ class _SendRootPageState extends State { data: url, version: QrVersions.auto, size: 400.0, + eyeStyle: QrEyeStyle( + eyeShape: QrEyeShape.square, + color: Theme.of(context).textTheme.bodyLarge?.color, + ), + dataModuleStyle: QrDataModuleStyle( + dataModuleShape: QrDataModuleShape.square, + color: Theme.of(context).textTheme.bodyLarge?.color, + ), ), ); } @@ -123,6 +131,14 @@ class _SendRootPageState extends State { data: url, version: QrVersions.auto, size: 400.0, + eyeStyle: QrEyeStyle( + eyeShape: QrEyeShape.square, + color: Theme.of(context).textTheme.bodyLarge?.color, + ), + dataModuleStyle: QrDataModuleStyle( + dataModuleShape: QrDataModuleShape.square, + color: Theme.of(context).textTheme.bodyLarge?.color, + ), ), ); }