Edited message diff

This commit is contained in:
2025-09-23 15:20:45 +08:00
parent 9529bbf08b
commit 84c38500d0
7 changed files with 96 additions and 14 deletions

View File

@@ -206,6 +206,18 @@ class AppDatabase extends _$AppDatabase {
createdAt: dbMessage.createdAt, createdAt: dbMessage.createdAt,
status: dbMessage.status, status: dbMessage.status,
nonce: dbMessage.nonce, nonce: dbMessage.nonce,
content: dbMessage.content,
isDeleted: dbMessage.isDeleted,
updatedAt: dbMessage.updatedAt,
deletedAt: dbMessage.deletedAt,
type: dbMessage.type,
meta: dbMessage.meta,
membersMentioned: dbMessage.membersMentioned,
editedAt: dbMessage.editedAt,
attachments: dbMessage.attachments,
reactions: dbMessage.reactions,
repliedMessageId: dbMessage.repliedMessageId,
forwardedMessageId: dbMessage.forwardedMessageId,
); );
} }

View File

@@ -76,8 +76,19 @@ class LocalChatMessage {
final DateTime createdAt; final DateTime createdAt;
MessageStatus status; MessageStatus status;
final String? nonce; final String? nonce;
final String? content;
final bool? isDeleted;
final DateTime? updatedAt;
final DateTime? deletedAt;
final String type;
final Map<String, dynamic> meta;
final List<String> membersMentioned;
final DateTime? editedAt;
final List<Map<String, dynamic>> attachments;
final List<Map<String, dynamic>> reactions;
final String? repliedMessageId;
final String? forwardedMessageId;
List<UniversalFile>? localAttachments; List<UniversalFile>? localAttachments;
bool isRead;
LocalChatMessage({ LocalChatMessage({
required this.id, required this.id,
@@ -87,8 +98,19 @@ class LocalChatMessage {
required this.createdAt, required this.createdAt,
required this.nonce, required this.nonce,
required this.status, required this.status,
this.content,
this.isDeleted,
this.updatedAt,
this.deletedAt,
required this.type,
required this.meta,
required this.membersMentioned,
this.editedAt,
required this.attachments,
required this.reactions,
this.repliedMessageId,
this.forwardedMessageId,
this.localAttachments, this.localAttachments,
this.isRead = false,
}); });
SnChatMessage toRemoteMessage() { SnChatMessage toRemoteMessage() {
@@ -99,7 +121,6 @@ class LocalChatMessage {
SnChatMessage message, SnChatMessage message,
MessageStatus status, { MessageStatus status, {
String? nonce, String? nonce,
bool isRead = false,
}) { }) {
return LocalChatMessage( return LocalChatMessage(
id: message.id, id: message.id,
@@ -109,7 +130,18 @@ class LocalChatMessage {
createdAt: message.createdAt, createdAt: message.createdAt,
status: status, status: status,
nonce: nonce ?? message.nonce, nonce: nonce ?? message.nonce,
isRead: isRead, content: message.content,
isDeleted: false,
updatedAt: message.updatedAt,
deletedAt: null,
type: message.type,
meta: message.meta,
membersMentioned: message.membersMentioned,
editedAt: message.editedAt,
attachments: message.attachments.map((e) => e.toJson()).toList(),
reactions: message.reactions.map((e) => e.toJson()).toList(),
repliedMessageId: message.repliedMessageId,
forwardedMessageId: message.forwardedMessageId,
); );
} }
} }

View File

@@ -904,7 +904,7 @@ class MessagesNotifier extends _$MessagesNotifier {
final remote = messageToUpdate.toRemoteMessage(); final remote = messageToUpdate.toRemoteMessage();
final updatedRemote = remote.copyWith( final updatedRemote = remote.copyWith(
content: 'This message was deleted', content: 'This message was deleted',
type: 'deleted', deletedAt: DateTime.now(),
attachments: [], attachments: [],
); );

View File

@@ -6,7 +6,7 @@ part of 'room.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$messagesNotifierHash() => r'ebbbc77a74b7130ca5885aaaa06478888cb50262'; String _$messagesNotifierHash() => r'196fe42438c716b2f975f5f14733974174b3dde7';
/// Copied from Dart SDK /// Copied from Dart SDK
class _SystemHash { class _SystemHash {

View File

@@ -24,6 +24,7 @@ import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/content/embed/link.dart'; import 'package:island/widgets/content/embed/link.dart';
import 'package:island/widgets/content/markdown.dart'; import 'package:island/widgets/content/markdown.dart';
import 'package:material_symbols_icons/material_symbols_icons.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'; import 'package:styled_widget/styled_widget.dart';
import 'package:super_context_menu/super_context_menu.dart'; import 'package:super_context_menu/super_context_menu.dart';
@@ -566,18 +567,38 @@ class _MessageItemContent extends StatelessWidget {
).colorScheme.onSurfaceVariant.withOpacity(0.6), ).colorScheme.onSurfaceVariant.withOpacity(0.6),
), ),
const Gap(4), const Gap(4),
Text( if (item.meta['previous_content'] is String)
item.content ?? 'Edited a message', PrettyDiffText(
style: Theme.of(context).textTheme.bodySmall?.copyWith( oldText: item.meta['previous_content'],
color: Theme.of( newText: item.content ?? 'Edited a message',
defaultTextStyle: Theme.of(
context, context,
).colorScheme.onSurfaceVariant.withOpacity(0.6), ).textTheme.bodySmall!.copyWith(
fontStyle: FontStyle.italic, 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 'deleted': // Client side history // TODO add seprate is_deleted column to indicate it
case 'messages.delete': case 'messages.delete':
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,

View File

@@ -449,6 +449,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.3" version: "7.0.3"
diff_match_patch:
dependency: transitive
description:
name: diff_match_patch
sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4"
url: "https://pub.dev"
source: hosted
version: "0.4.1"
dio: dio:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1885,6 +1893,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.3" version: "6.0.3"
pretty_diff_text:
dependency: "direct main"
description:
name: pretty_diff_text
sha256: "2d4decf2bb6dac14c4e7a2cbd2da9ae7e004ccadc1155c723a0ca20a5daa7c57"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
process_run: process_run:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -152,6 +152,7 @@ dependencies:
win32: ^5.14.0 win32: ^5.14.0
ffi: ^2.1.4 ffi: ^2.1.4
dart_ipc: ^1.0.1 dart_ipc: ^1.0.1
pretty_diff_text: ^2.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: