Working on message search+filter

This commit is contained in:
2024-06-16 00:46:46 +02:00
parent e9ea573e33
commit 0bbe5fc7fa
10 changed files with 354 additions and 64 deletions

View File

@@ -0,0 +1,36 @@
import 'package:flutter/src/widgets/icon_data.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
enum MessageFilterChipletType {
search,
channel,
sender,
timeRange,
priority,
sendkey,
}
class MessageFilterChiplet {
final String label;
final String value;
final MessageFilterChipletType type;
MessageFilterChiplet({required this.label, required this.value, required this.type});
IconData? icon() {
switch (type) {
case MessageFilterChipletType.search:
return FontAwesomeIcons.magnifyingGlass;
case MessageFilterChipletType.channel:
return FontAwesomeIcons.snake;
case MessageFilterChipletType.sender:
return FontAwesomeIcons.signature;
case MessageFilterChipletType.timeRange:
return FontAwesomeIcons.timer;
case MessageFilterChipletType.priority:
return FontAwesomeIcons.bolt;
case MessageFilterChipletType.sendkey:
return FontAwesomeIcons.gearCode;
}
}
}

View File

@@ -5,6 +5,7 @@ import 'package:provider/provider.dart';
import 'package:simplecloudnotifier/api/api_client.dart';
import 'package:simplecloudnotifier/models/channel.dart';
import 'package:simplecloudnotifier/models/scn_message.dart';
import 'package:simplecloudnotifier/pages/message_list/message_filter_chiplet.dart';
import 'package:simplecloudnotifier/pages/message_view/message_view.dart';
import 'package:simplecloudnotifier/settings/app_settings.dart';
import 'package:simplecloudnotifier/state/app_bar_state.dart';
@@ -34,10 +35,14 @@ class _MessageListPageState extends State<MessageListPage> with RouteAware {
bool _isInitialized = false;
List<MessageFilterChiplet> _filterChiplets = [];
@override
void initState() {
super.initState();
AppBarState().subscribeSearchListener(_onAppBarSearch);
_pagingController.addPageRequestListener(_fetchPage);
if (widget.isVisiblePage && !_isInitialized) _realInitState();
@@ -94,6 +99,7 @@ class _MessageListPageState extends State<MessageListPage> with RouteAware {
@override
void dispose() {
ApplicationLog.debug('MessageListPage::dispose');
AppBarState().unsubscribeSearchListener(_onAppBarSearch);
Navi.modalRouteObserver.unsubscribe(this);
_pagingController.dispose();
_lifecyleListener.dispose();
@@ -222,22 +228,50 @@ class _MessageListPageState extends State<MessageListPage> with RouteAware {
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
child: RefreshIndicator(
onRefresh: () => Future.sync(
() => _pagingController.refresh(),
),
child: PagedListView<String, SCNMessage>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<SCNMessage>(
itemBuilder: (context, item, index) => MessageListItem(
message: item,
allChannels: _channels ?? {},
onPressed: () {
Navi.push(context, () => MessageViewPage(message: item));
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (_filterChiplets.isNotEmpty)
Wrap(
alignment: WrapAlignment.start,
spacing: 5.0,
children: [
for (var chiplet in _filterChiplets) _buildFilterChip(context, chiplet),
],
),
Expanded(
child: RefreshIndicator(
onRefresh: () => Future.sync(
() => _pagingController.refresh(),
),
child: PagedListView<String, SCNMessage>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<SCNMessage>(
itemBuilder: (context, item, index) => MessageListItem(
message: item,
allChannels: _channels ?? {},
onPressed: () {
Navi.push(context, () => MessageViewPage(message: item));
},
),
),
),
),
),
),
],
),
);
}
Widget _buildFilterChip(BuildContext context, MessageFilterChiplet chiplet) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 2, 0, 2),
child: InputChip(
avatar: Icon(chiplet.icon()),
label: Text(chiplet.label),
onDeleted: () => setState(() => _filterChiplets.remove(chiplet)),
onPressed: () {/* TODO idk what to do here ? */},
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
),
);
}
@@ -269,4 +303,10 @@ class _MessageListPageState extends State<MessageListPage> with RouteAware {
await cache.delete(val.messageID);
}
}
void _onAppBarSearch(String str) {
setState(() {
_filterChiplets = _filterChiplets.where((element) => false).toList() + [MessageFilterChiplet(label: str, value: str, type: MessageFilterChipletType.search)];
});
}
}

View File

@@ -137,6 +137,7 @@ class _MessageViewPageState extends State<MessageViewPage> {
_buildMetaCard(context, FontAwesomeIcons.solidSnake, 'Channel', [message.channelID, channel?.displayName ?? message.channelInternalName], () => {/*TODO*/}),
_buildMetaCard(context, FontAwesomeIcons.solidTimer, 'Timestamp', [message.timestamp], null),
_buildMetaCard(context, FontAwesomeIcons.solidUser, 'User', [if (user != null) user.userID, if (user?.username != null) user!.username!], () => {/*TODO*/}), //TODO
_buildMetaCard(context, FontAwesomeIcons.solidBolt, 'Priority', [_prettyPrintPriority(message.priority)], () => {/*TODO*/}), //TODO
if (message.senderUserID == userAccUserID) UI.button(text: "Delete Message", onPressed: () {/*TODO*/}, color: Colors.red[900]),
],
),
@@ -252,4 +253,17 @@ class _MessageViewPageState extends State<MessageViewPage> {
String _preformatTitle(SCNMessage message) {
return message.title.replaceAll('\n', '').replaceAll('\r', '').replaceAll('\t', ' ');
}
String _prettyPrintPriority(int priority) {
switch (priority) {
case 0:
return 'Low (0)';
case 1:
return 'Normal (1)';
case 2:
return 'High (2)';
default:
return 'Unknown ($priority)';
}
}
}