refactor: 重构聊天模块支持 SSE 断线重连及用户上下文隔离
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
// ignore_for_file: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
|
||||
|
||||
part of 'chat_bloc.dart';
|
||||
|
||||
extension _ChatBlocAttachments on ChatBloc {
|
||||
void _syncUploadedAttachments({
|
||||
required String messageId,
|
||||
required List<UploadedAttachment> uploadedAttachments,
|
||||
}) {
|
||||
if (uploadedAttachments.isEmpty) {
|
||||
_markAttachmentUploadDone(messageId);
|
||||
return;
|
||||
}
|
||||
final items = state.items.map((item) {
|
||||
if (item is! TextMessageItem || item.id != messageId) {
|
||||
return item;
|
||||
}
|
||||
final synced = item.attachments.map((attachment) {
|
||||
final localPath = attachment['path'];
|
||||
if (localPath is! String || localPath.isEmpty) {
|
||||
return <String, dynamic>{...attachment, 'uploading': false};
|
||||
}
|
||||
UploadedAttachment? matched;
|
||||
for (final candidate in uploadedAttachments) {
|
||||
if (candidate.localPath == localPath) {
|
||||
matched = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matched == null) {
|
||||
return <String, dynamic>{...attachment, 'uploading': false};
|
||||
}
|
||||
return <String, dynamic>{
|
||||
...attachment,
|
||||
'url': matched.url,
|
||||
'mimeType': matched.mimeType,
|
||||
'uploading': false,
|
||||
};
|
||||
}).toList();
|
||||
return item.copyWith(attachments: synced);
|
||||
}).toList();
|
||||
emit(state.copyWith(items: items));
|
||||
}
|
||||
|
||||
void _markAttachmentUploadDone(String messageId) {
|
||||
final items = state.items.map((item) {
|
||||
if (item is! TextMessageItem || item.id != messageId) {
|
||||
return item;
|
||||
}
|
||||
final done = item.attachments
|
||||
.map(
|
||||
(attachment) => <String, dynamic>{
|
||||
...attachment,
|
||||
'uploading': false,
|
||||
},
|
||||
)
|
||||
.toList();
|
||||
return item.copyWith(attachments: done);
|
||||
}).toList();
|
||||
emit(state.copyWith(items: items));
|
||||
}
|
||||
|
||||
Future<Uint8List?> _loadAttachmentPreview(String previewPath) async {
|
||||
final cached = _attachmentPreviewCache[previewPath];
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
final pending = _attachmentPreviewInflight[previewPath];
|
||||
if (pending != null) {
|
||||
return pending;
|
||||
}
|
||||
|
||||
final future = (() async {
|
||||
try {
|
||||
final bytes = await _service.fetchAttachmentPreview(previewPath);
|
||||
_attachmentPreviewCache[previewPath] = bytes;
|
||||
return bytes;
|
||||
} catch (_) {
|
||||
return null;
|
||||
} finally {
|
||||
_attachmentPreviewInflight.remove(previewPath);
|
||||
}
|
||||
})();
|
||||
|
||||
_attachmentPreviewInflight[previewPath] = future;
|
||||
return future;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user