debug view && priority in listview
This commit is contained in:
parent
34925b6678
commit
f5813a5489
11
flutter/README.md
Normal file
11
flutter/README.md
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
@ -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,
|
||||||
|
126
flutter/lib/pages/debug/debug_colors.dart
Normal file
126
flutter/lib/pages/debug/debug_colors.dart
Normal 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))
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
64
flutter/lib/pages/debug/debug_main.dart
Normal file
64
flutter/lib/pages/debug/debug_main.dart
Normal 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;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
13
flutter/lib/pages/debug/debug_persistence.dart
Normal file
13
flutter/lib/pages/debug/debug_persistence.dart
Normal 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 */);
|
||||||
|
}
|
||||||
|
}
|
13
flutter/lib/pages/debug/debug_requests.dart
Normal file
13
flutter/lib/pages/debug/debug_requests.dart
Normal 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 */);
|
||||||
|
}
|
||||||
|
}
|
@ -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)),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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) {
|
||||||
|
@ -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 ?? ''),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user