2024-05-21 23:20:34 +02:00
|
|
|
import 'dart:math';
|
|
|
|
|
2024-02-18 17:36:58 +01:00
|
|
|
import 'package:flutter/material.dart';
|
2024-05-23 17:41:51 +02:00
|
|
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
2024-05-21 23:20:34 +02:00
|
|
|
import 'package:simplecloudnotifier/models/channel.dart';
|
2024-02-18 17:36:58 +01:00
|
|
|
import 'package:simplecloudnotifier/models/message.dart';
|
2024-05-21 23:20:34 +02:00
|
|
|
import 'package:intl/intl.dart';
|
2024-02-18 17:36:58 +01:00
|
|
|
|
|
|
|
class MessageListItem extends StatelessWidget {
|
2024-05-21 23:20:34 +02:00
|
|
|
static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm');
|
2024-05-23 17:41:51 +02:00
|
|
|
static final _lineCount = 3; //TODO setting
|
2024-05-21 23:20:34 +02:00
|
|
|
|
2024-02-18 17:36:58 +01:00
|
|
|
const MessageListItem({
|
|
|
|
required this.message,
|
2024-05-21 23:20:34 +02:00
|
|
|
required this.allChannels,
|
|
|
|
required this.onPressed,
|
2024-02-18 17:36:58 +01:00
|
|
|
super.key,
|
|
|
|
});
|
|
|
|
|
|
|
|
final Message message;
|
2024-05-21 23:20:34 +02:00
|
|
|
final Map<String, Channel> allChannels;
|
|
|
|
final Null Function() onPressed;
|
2024-02-18 17:36:58 +01:00
|
|
|
|
|
|
|
@override
|
2024-05-21 23:20:34 +02:00
|
|
|
Widget build(BuildContext context) {
|
|
|
|
if (showChannel(message)) {
|
2024-05-23 17:41:51 +02:00
|
|
|
return buildWithChannel(context);
|
|
|
|
} else {
|
|
|
|
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,
|
2024-05-21 23:20:34 +02:00
|
|
|
),
|
2024-05-23 17:41:51 +02:00
|
|
|
),
|
|
|
|
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,
|
|
|
|
),
|
|
|
|
],
|
2024-05-21 23:20:34 +02:00
|
|
|
),
|
|
|
|
),
|
2024-05-23 17:41:51 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)),
|
2024-05-21 23:20:34 +02:00
|
|
|
),
|
2024-05-23 17:41:51 +02:00
|
|
|
child: Text(
|
|
|
|
resolveChannelName(message),
|
|
|
|
style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).cardColor, fontSize: 12),
|
2024-05-21 23:20:34 +02:00
|
|
|
overflow: TextOverflow.clip,
|
|
|
|
maxLines: 1,
|
|
|
|
),
|
2024-05-23 17:41:51 +02:00
|
|
|
),
|
|
|
|
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,
|
|
|
|
),
|
|
|
|
],
|
2024-05-21 23:20:34 +02:00
|
|
|
),
|
|
|
|
),
|
2024-05-23 17:41:51 +02:00
|
|
|
),
|
|
|
|
);
|
2024-05-21 23:20:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
processContent(String? v) {
|
|
|
|
if (v == null) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
var lines = v.split('\n');
|
|
|
|
if (lines.isEmpty) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return lines.sublist(0, min(_lineCount, lines.length)).join("\n").trim();
|
|
|
|
}
|
|
|
|
|
|
|
|
processTitle(String? v) {
|
|
|
|
if (v == null) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
v = v.replaceAll("\n", " ");
|
|
|
|
v = v.replaceAll("\t", " ");
|
|
|
|
v = v.replaceAll("\r", "");
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
String resolveChannelName(Message message) {
|
|
|
|
return allChannels[message.channelID]?.displayName ?? message.channelInternalName;
|
|
|
|
}
|
|
|
|
|
|
|
|
showChannel(Message message) {
|
|
|
|
return message.channelInternalName != 'main';
|
|
|
|
}
|
2024-02-18 17:36:58 +01:00
|
|
|
}
|