Implemented per stream subscription recovery with polling fallback

This commit is contained in:
2026-03-01 17:24:04 +08:00
parent e91e7b43d2
commit c9479f01f0
19 changed files with 894 additions and 494 deletions
+26 -14
View File
@@ -528,29 +528,41 @@ class _TicketDetailScreenState extends ConsumerState<TicketDetailScreen> {
_maybeTypingController(widget.ticketId)?.stopTyping();
final message = await ref
.read(ticketsControllerProvider)
.sendTicketMessage(ticketId: widget.ticketId, content: content);
// Capture mentions and clear the composer immediately so the UI
// remains snappy. Perform the network send and notification creation
// in a fire-and-forget background Future.
final mentionUserIds = _extractMentionedUserIds(
content,
profiles,
currentUserId,
);
if (mentionUserIds.isNotEmpty && currentUserId != null) {
await ref
.read(notificationsControllerProvider)
.createMentionNotifications(
userIds: mentionUserIds,
actorId: currentUserId,
ticketId: widget.ticketId,
messageId: message.id,
);
}
ref.invalidate(ticketMessagesProvider(widget.ticketId));
if (mounted) {
_messageController.clear();
_clearMentions();
}
Future(() async {
try {
final message = await ref
.read(ticketsControllerProvider)
.sendTicketMessage(ticketId: widget.ticketId, content: content);
if (mentionUserIds.isNotEmpty && currentUserId != null) {
try {
await ref
.read(notificationsControllerProvider)
.createMentionNotifications(
userIds: mentionUserIds,
actorId: currentUserId,
ticketId: widget.ticketId,
messageId: message.id,
);
} catch (_) {}
}
} catch (e, st) {
debugPrint('sendTicketMessage error: $e\n$st');
}
});
}
List<String> _extractMentionedUserIds(