implemented chat long-polling and optimistic updates, centralized notification management, optimized avatar caching
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eraser/eraser.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_app_badge/flutter_app_badge.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../routing/app_routes.dart';
|
||||
import '../state/app/modules/chat/bloc/chat_bloc.dart';
|
||||
import '../state/app/modules/chat_list/bloc/chat_list_bloc.dart';
|
||||
import 'notification_service.dart';
|
||||
|
||||
class NotificationTasks {
|
||||
static void updateBadgeCount(RemoteMessage notification) {
|
||||
@@ -14,9 +18,43 @@ class NotificationTasks {
|
||||
);
|
||||
}
|
||||
|
||||
/// Per-chat tag scheme. MUST match the Notify backend, which sets this
|
||||
/// value on `AndroidNotification.setTag` AND `apns-collapse-id`.
|
||||
static String chatTag(String chatToken) => 'talk_$chatToken';
|
||||
|
||||
/// Removes tray notifications belonging to [chatToken]. Eraser handles
|
||||
/// iOS (where the plugin's `getActiveNotifications` returns null ids
|
||||
/// for FCM posts and can't cancel them); the local-notifications sweep
|
||||
/// handles Android and acts as a fallback while Eraser's native side
|
||||
/// isn't built in yet.
|
||||
static Future<void> clearNotificationsForChat(String chatToken) async {
|
||||
final tag = chatTag(chatToken);
|
||||
try {
|
||||
await Eraser.clearAppNotificationsByTag(tag);
|
||||
} on MissingPluginException {
|
||||
// Eraser native code not yet linked — needs flutter clean + run.
|
||||
} on Object catch (e) {
|
||||
log('Eraser($tag) failed: $e');
|
||||
}
|
||||
try {
|
||||
final plugin = NotificationService().flutterLocalNotificationsPlugin;
|
||||
final actives = await plugin.getActiveNotifications();
|
||||
for (final n in actives) {
|
||||
final id = n.id;
|
||||
if (id == null) continue;
|
||||
if (n.tag == tag) await plugin.cancel(id: id, tag: n.tag);
|
||||
}
|
||||
} on Object catch (e) {
|
||||
log('Active-notification sweep failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Refreshes the chat list. Deliberately does NOT touch [ChatBloc] —
|
||||
/// the open chat view manages its own state via long-poll, and refreshing
|
||||
/// it here would re-fetch the last-opened chat with setReadMarker=on
|
||||
/// even if the user has already left.
|
||||
static void updateProviders(BuildContext context) {
|
||||
context.read<ChatListBloc>().refresh();
|
||||
context.read<ChatBloc>().refresh();
|
||||
}
|
||||
|
||||
/// Switches to the Talk tab. If [chatToken] is provided, also schedules
|
||||
|
||||
Reference in New Issue
Block a user