debug view && priority in listview

This commit is contained in:
Mike Schwörer 2024-05-23 17:41:51 +02:00
parent 34925b6678
commit f5813a5489
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
12 changed files with 432 additions and 123 deletions

11
flutter/README.md Normal file
View File

@ -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

View File

@ -1,37 +1,55 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:simplecloudnotifier/pages/debug/debug_main.dart';
import 'package:simplecloudnotifier/state/app_theme.dart'; import 'package:simplecloudnotifier/state/app_theme.dart';
class SCNAppBar extends StatelessWidget implements PreferredSizeWidget { 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 String? title;
final bool showThemeSwitch;
final bool showDebug;
final bool showSearch;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppBar( return AppBar(
title: Text(title ?? 'Simple Cloud Notifier 2.0'), title: Text(title ?? 'Simple Cloud Notifier 2.0'),
actions: <Widget>[ actions: <Widget>[
Consumer<AppTheme>( if (showThemeSwitch)
builder: (context, appTheme, child) => IconButton( Consumer<AppTheme>(
icon: Icon(appTheme.darkMode ? FontAwesomeIcons.solidSun : FontAwesomeIcons.solidMoon), 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', tooltip: 'Debug',
onPressed: () { onPressed: () {
appTheme.switchDarkMode(); Navigator.push(context, MaterialPageRoute(builder: (context) => DebugMainPage()));
}, },
), ),
), if (!showDebug) SizedBox.square(dimension: 40),
IconButton( if (showSearch)
icon: const Icon(FontAwesomeIcons.solidSpiderBlackWidow), IconButton(
tooltip: 'Debug', icon: const Icon(FontAwesomeIcons.solidMagnifyingGlass),
onPressed: () {}, tooltip: 'Search',
), onPressed: () {},
IconButton( ),
icon: const Icon(FontAwesomeIcons.solidMagnifyingGlass), if (!showSearch) SizedBox.square(dimension: 40),
tooltip: 'Search',
onPressed: () {},
),
], ],
backgroundColor: Theme.of(context).secondaryHeaderColor, backgroundColor: Theme.of(context).secondaryHeaderColor,
); );

View File

@ -2,16 +2,29 @@ import 'package:flutter/material.dart';
import 'package:simplecloudnotifier/components/layout/app_bar.dart'; import 'package:simplecloudnotifier/components/layout/app_bar.dart';
class SCNScaffold extends StatelessWidget { 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 Widget child;
final String? title; final String? title;
final bool showThemeSwitch;
final bool showDebug;
final bool showSearch;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: SCNAppBar( appBar: SCNAppBar(
title: title, title: title,
showThemeSwitch: showThemeSwitch,
showDebug: showDebug,
showSearch: showSearch,
), ),
body: child, body: child,
); );

View File

@ -42,7 +42,12 @@ class _SCNNavLayoutState extends State<SCNNavLayout> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: SCNAppBar(), appBar: SCNAppBar(
title: null,
showDebug: true,
showSearch: _selectedIndex == 0 || _selectedIndex == 1,
showThemeSwitch: true,
),
body: _subPages.elementAt(_selectedIndex), body: _subPages.elementAt(_selectedIndex),
bottomNavigationBar: _buildNavBar(context), bottomNavigationBar: _buildNavBar(context),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,

View File

@ -0,0 +1,126 @@
import 'package:flutter/material.dart';
class DebugColorsPage extends StatefulWidget {
@override
_DebugColorsPageState createState() => _DebugColorsPageState();
}
class _DebugColorsPageState extends State<DebugColorsPage> {
@override
Widget build(BuildContext context) {
return Container(
child: SingleChildScrollView(
child: Column(
children: listColors(context),
),
),
);
}
List<Widget> 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))
],
);
}
}

View File

@ -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<DebugMainPage> {
final Map<DebugMainPageSubPage, Widget> _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<DebugMainPageSubPage>(
showSelectedIcon: false,
segments: const <ButtonSegment<DebugMainPageSubPage>>[
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.colors, label: Text('Theme')),
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.requests, label: Text('Requests')),
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.persistence, label: Text('Persistence')),
],
selected: <DebugMainPageSubPage>{_subPage},
onSelectionChanged: (Set<DebugMainPageSubPage> v) {
setState(() {
_subPage = v.first;
});
},
);
}
}

View File

@ -0,0 +1,13 @@
import 'package:flutter/material.dart';
class DebugPersistencePage extends StatefulWidget {
@override
_DebugPersistencePageState createState() => _DebugPersistencePageState();
}
class _DebugPersistencePageState extends State<DebugPersistencePage> {
@override
Widget build(BuildContext context) {
return Container(/* Add your UI components here */);
}
}

View File

@ -0,0 +1,13 @@
import 'package:flutter/material.dart';
class DebugRequestsPage extends StatefulWidget {
@override
_DebugRequestsPageState createState() => _DebugRequestsPageState();
}
class _DebugRequestsPageState extends State<DebugRequestsPage> {
@override
Widget build(BuildContext context) {
return Container(/* Add your UI components here */);
}
}

View File

@ -76,10 +76,7 @@ class _MessageListPageState extends State<MessageListPage> {
message: item, message: item,
allChannels: _channels ?? {}, allChannels: _channels ?? {},
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(context, MaterialPageRoute(builder: (context) => MessageViewPage(message: item)));
context,
MaterialPageRoute(builder: (context) => MessageViewPage(messageID: item.messageID)),
);
}, },
), ),
), ),

View File

@ -1,13 +1,14 @@
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:simplecloudnotifier/models/channel.dart'; import 'package:simplecloudnotifier/models/channel.dart';
import 'package:simplecloudnotifier/models/message.dart'; import 'package:simplecloudnotifier/models/message.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class MessageListItem extends StatelessWidget { class MessageListItem extends StatelessWidget {
static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm'); static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm');
static final _lineCount = 3; static final _lineCount = 3; //TODO setting
const MessageListItem({ const MessageListItem({
required this.message, required this.message,
@ -23,107 +24,125 @@ class MessageListItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (showChannel(message)) { if (showChannel(message)) {
return Card.filled( return buildWithChannel(context);
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,
),
],
),
),
),
);
} else { } else {
return Card.filled( return buildWithoutChannel(context);
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( Card buildWithoutChannel(BuildContext context) {
splashColor: Theme.of(context).primaryColor.withAlpha(30), return Card.filled(
onTap: onPressed, margin: EdgeInsets.fromLTRB(0, 4, 0, 4),
child: Padding( shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)),
padding: const EdgeInsets.all(8), color: (message.priority == 2) ? Theme.of(context).colorScheme.errorContainer : Theme.of(context).cardTheme.color,
child: Column( //clipBehavior: Clip.hardEdge, // nto needed, because our borderRadius is 0 anyway
crossAxisAlignment: CrossAxisAlignment.stretch, child: InkWell(
children: [ splashColor: Theme.of(context).splashColor,
Row( onTap: onPressed,
crossAxisAlignment: CrossAxisAlignment.start, child: Padding(
children: [ padding: const EdgeInsets.all(8),
Expanded( child: Column(
child: Text( crossAxisAlignment: CrossAxisAlignment.stretch,
processTitle(message.title), children: [
style: const TextStyle(fontWeight: FontWeight.bold), Row(
overflow: TextOverflow.ellipsis, crossAxisAlignment: CrossAxisAlignment.start,
maxLines: 3, 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()), Text(
style: const TextStyle(fontWeight: FontWeight.normal, fontSize: 11), _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, overflow: TextOverflow.clip,
maxLines: 1, maxLines: 1,
), ),
], ),
), Expanded(child: SizedBox()),
SizedBox(height: 4), Text(
Text( _dateFormat.format(DateTime.parse(message.timestamp).toLocal()),
processContent(message.content), style: const TextStyle(fontWeight: FontWeight.normal, fontSize: 11),
style: TextStyle(color: Theme.of(context).textTheme.bodyLarge?.color?.withAlpha(160)), overflow: TextOverflow.clip,
overflow: TextOverflow.ellipsis, maxLines: 1,
maxLines: _lineCount, ),
), ],
], ),
), 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) { processContent(String? v) {

View File

@ -6,9 +6,9 @@ import 'package:simplecloudnotifier/models/message.dart';
import 'package:simplecloudnotifier/state/user_account.dart'; import 'package:simplecloudnotifier/state/user_account.dart';
class MessageViewPage extends StatefulWidget { 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 @override
State<MessageViewPage> createState() => _MessageViewPageState(); State<MessageViewPage> createState() => _MessageViewPageState();
@ -26,7 +26,7 @@ class _MessageViewPageState extends State<MessageViewPage> {
Future<Message> fetchMessage() async { Future<Message> fetchMessage() async {
final acc = Provider.of<UserAccount>(context, listen: false); final acc = Provider.of<UserAccount>(context, listen: false);
return await APIClient.getMessage(acc.auth!, widget.messageID); return await APIClient.getMessage(acc.auth!, widget.message.messageID);
} }
@override @override
@ -38,18 +38,32 @@ class _MessageViewPageState extends State<MessageViewPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SCNScaffold( return SCNScaffold(
title: 'Message', title: 'Message',
showSearch: false,
child: FutureBuilder<Message>( child: FutureBuilder<Message>(
future: futureMessage, future: futureMessage,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
return Center(child: Text(snapshot.data!.title)); return buildMessageView(snapshot.data!, false);
} else if (snapshot.hasError) { } else if (snapshot.hasError) {
return Center(child: Text('${snapshot.error}')); //TODO nice error page 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 ?? ''),
],
),
);
}
} }

View File

@ -101,6 +101,14 @@ class _SendRootPageState extends State<SendRootPage> {
data: url, data: url,
version: QrVersions.auto, version: QrVersions.auto,
size: 400.0, 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<SendRootPage> {
data: url, data: url,
version: QrVersions.auto, version: QrVersions.auto,
size: 400.0, 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,
),
), ),
); );
} }