Compare commits

...

2 Commits

Author SHA1 Message Date
5032cccf38 Chat quote and reply 2024-11-18 22:33:03 +08:00
9f7a3082cb Message with attachment 2024-11-18 21:38:15 +08:00
10 changed files with 294 additions and 123 deletions

View File

@ -119,12 +119,20 @@ class ChatMessageController extends ChangeNotifier {
} }
Future<void> _addUnconfirmedMessage(SnChatMessage message) async { Future<void> _addUnconfirmedMessage(SnChatMessage message) async {
SnChatMessage? quoteEvent;
if (message.body['quote_event'] != null) {
quoteEvent = await getMessage(message.body['quote_event'] as int);
}
final attachmentRid = List<String>.from( final attachmentRid = List<String>.from(
message.body['attachments']?.cast<String>() ?? [], message.body['attachments']?.cast<String>() ?? [],
); );
final attachments = await _attach.getMultiple(attachmentRid); final attachments = await _attach.getMultiple(attachmentRid);
message = message.copyWith( message = message.copyWith(
preload: SnChatMessagePreload(attachments: attachments), preload: SnChatMessagePreload(
quoteEvent: quoteEvent,
attachments: attachments,
),
); );
messages.insert(0, message); messages.insert(0, message);
@ -133,12 +141,20 @@ class ChatMessageController extends ChangeNotifier {
} }
Future<void> _addMessage(SnChatMessage message) async { Future<void> _addMessage(SnChatMessage message) async {
SnChatMessage? quoteEvent;
if (message.body['quote_event'] != null) {
quoteEvent = await getMessage(message.body['quote_event'] as int);
}
final attachmentRid = List<String>.from( final attachmentRid = List<String>.from(
message.body['attachments']?.cast<String>() ?? [], message.body['attachments']?.cast<String>() ?? [],
); );
final attachments = await _attach.getMultiple(attachmentRid); final attachments = await _attach.getMultiple(attachmentRid);
message = message.copyWith( message = message.copyWith(
preload: SnChatMessagePreload(attachments: attachments), preload: SnChatMessagePreload(
quoteEvent: quoteEvent,
attachments: attachments,
),
); );
final idx = messages.indexWhere((e) => e.uuid == message.uuid); final idx = messages.indexWhere((e) => e.uuid == message.uuid);
@ -199,8 +215,8 @@ class ChatMessageController extends ChangeNotifier {
final body = { final body = {
'text': content, 'text': content,
'algorithm': 'plain', 'algorithm': 'plain',
if (quoteId != null) 'quote_id': quoteId, if (quoteId != null) 'quote_event': quoteId,
if (relatedId != null) 'related_id': relatedId, if (relatedId != null) 'quote_event': relatedId,
if (attachments != null && attachments.isNotEmpty) if (attachments != null && attachments.isNotEmpty)
'attachments': attachments, 'attachments': attachments,
}; };
@ -269,6 +285,42 @@ class ChatMessageController extends ChangeNotifier {
} }
} }
/// Get a single event from the current channel
/// If it was not found in local storage we will look it up in remote
Future<SnChatMessage?> getMessage(int id) async {
SnChatMessage? out;
if (_box != null && _box!.containsKey(id)) {
out = _box!.get(id);
}
if (out == null) {
try {
final resp = await _sn.client
.get('/cgi/im/channels/${channel!.keyPath}/events/$id');
out = SnChatMessage.fromJson(resp.data);
_saveMessageToLocal([out]);
} catch (_) {
// ignore, maybe not found
}
}
// Preload some related things if found
if (out != null) {
await _ud.listAccount([out.sender.accountId]);
final attachments = await _attach.getMultiple(
out.body['attachments']?.cast<String>() ?? [],
);
out = out.copyWith(
preload: SnChatMessagePreload(
attachments: attachments,
),
);
}
return out;
}
/// Get message from local storage first, then from the server. /// Get message from local storage first, then from the server.
/// Will not check local storage is up to date with the server. /// Will not check local storage is up to date with the server.
/// If you need to do the sync, do the `checkUpdate` instead. /// If you need to do the sync, do the `checkUpdate` instead.
@ -279,7 +331,7 @@ class ChatMessageController extends ChangeNotifier {
}) async { }) async {
late List<SnChatMessage> out; late List<SnChatMessage> out;
if (_box != null && (_box!.length >= take + offset || forceLocal)) { if (_box != null && (_box!.length >= take + offset || forceLocal)) {
out = _box!.values.skip(offset).take(take).toList(); out = _box!.values.skip(offset).take(take).toList().reversed.toList();
} else { } else {
final resp = await _sn.client.get( final resp = await _sn.client.get(
'/cgi/im/channels/${channel!.keyPath}/events', '/cgi/im/channels/${channel!.keyPath}/events',
@ -300,18 +352,27 @@ class ChatMessageController extends ChangeNotifier {
out.expand((e) => (e.body['attachments'] as List<dynamic>?) ?? []), out.expand((e) => (e.body['attachments'] as List<dynamic>?) ?? []),
); );
final attachments = await _attach.getMultiple(attachmentRid); final attachments = await _attach.getMultiple(attachmentRid);
out = out.reversed
.map((ele) => ele.copyWith( // Putting preload back to data
preload: SnChatMessagePreload( for (var i = 0; i < out.length; i++) {
attachments: attachments // Preload related events (quoted)
.where((e) => SnChatMessage? quoteEvent;
(ele.body['attachments'] as List<dynamic>?) if (out[i].body['quote_event'] != null) {
?.contains(e) ?? quoteEvent = await getMessage(out[i].body['quote_event'] as int);
false) }