173 lines
5.4 KiB
Dart
173 lines
5.4 KiB
Dart
import 'dart:math' as math;
|
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:gap/gap.dart';
|
|
import 'package:island/models/chat.dart';
|
|
import 'package:island/pods/call.dart';
|
|
import 'package:island/widgets/content/markdown.dart';
|
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
|
import 'package:pretty_diff_text/pretty_diff_text.dart';
|
|
import 'package:styled_widget/styled_widget.dart';
|
|
|
|
class MessageContent extends StatelessWidget {
|
|
final SnChatMessage item;
|
|
final String? translatedText;
|
|
|
|
const MessageContent({super.key, required this.item, this.translatedText});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (item.type == 'messages.delete' || item.deletedAt != null) {
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Symbols.delete,
|
|
size: 16,
|
|
color: Theme.of(
|
|
context,
|
|
).colorScheme.onSurfaceVariant.withOpacity(0.6),
|
|
),
|
|
const Gap(4),
|
|
Text(
|
|
item.content ?? 'Deleted a message',
|
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
|
fontSize: 13,
|
|
color: Theme.of(
|
|
context,
|
|
).colorScheme.onSurfaceVariant.withOpacity(0.6),
|
|
fontStyle: FontStyle.italic,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
switch (item.type) {
|
|
case 'call.start':
|
|
case 'call.ended':
|
|
return _MessageContentCall(
|
|
isEnded: item.type == 'call.ended',
|
|
duration: item.meta['duration']?.toDouble(),
|
|
);
|
|
case 'messages.update':
|
|
case 'messages.update.links':
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Symbols.edit,
|
|
size: 16,
|
|
color: Theme.of(
|
|
context,
|
|
).colorScheme.onSurfaceVariant.withOpacity(0.6),
|
|
),
|
|
const Gap(4),
|
|
if (item.meta['previous_content'] is String)
|
|
PrettyDiffText(
|
|
oldText: item.meta['previous_content'],
|
|
newText: item.content ?? 'Edited a message',
|
|
defaultTextStyle: Theme.of(
|
|
context,
|
|
).textTheme.bodyMedium!.copyWith(
|
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
|
),
|
|
addedTextStyle: TextStyle(
|
|
backgroundColor: Theme.of(
|
|
context,
|
|
).colorScheme.primaryFixedDim.withOpacity(0.4),
|
|
),
|
|
deletedTextStyle: TextStyle(
|
|
decoration: TextDecoration.lineThrough,
|
|
color: Theme.of(
|
|
context,
|
|
).colorScheme.onSurfaceVariant.withOpacity(0.7),
|
|
),
|
|
)
|
|
else
|
|
Text(
|
|
item.content ?? 'Edited a message',
|
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
|
color: Theme.of(
|
|
context,
|
|
).colorScheme.onSurfaceVariant.withOpacity(0.6),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
case 'text':
|
|
default:
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
MarkdownTextContent(
|
|
content: item.content ?? '*${item.type} has no content*',
|
|
isSelectable: true,
|
|
linesMargin: EdgeInsets.zero,
|
|
),
|
|
if (translatedText?.isNotEmpty ?? false)
|
|
...([
|
|
ConstrainedBox(
|
|
constraints: BoxConstraints(
|
|
maxWidth: math.min(
|
|
280,
|
|
MediaQuery.of(context).size.width * 0.4,
|
|
),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text('translated').tr().fontSize(11).opacity(0.75),
|
|
const Gap(8),
|
|
Flexible(child: Divider()),
|
|
],
|
|
).padding(vertical: 4),
|
|
),
|
|
MarkdownTextContent(
|
|
content: translatedText!,
|
|
isSelectable: true,
|
|
linesMargin: EdgeInsets.zero,
|
|
),
|
|
]),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
static bool hasContent(SnChatMessage item) {
|
|
return item.type != 'text' || (item.content?.isNotEmpty ?? false);
|
|
}
|
|
}
|
|
|
|
class _MessageContentCall extends StatelessWidget {
|
|
final bool isEnded;
|
|
final double? duration;
|
|
|
|
const _MessageContentCall({required this.isEnded, this.duration});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
isEnded ? Symbols.call_end : Symbols.phone_in_talk,
|
|
size: 16,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
),
|
|
Gap(4),
|
|
Text(
|
|
isEnded
|
|
? 'Call ended after ${formatDuration(Duration(seconds: duration!.toInt()))}'
|
|
: 'Call started',
|
|
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|