diff --git a/lib/pods/websocket.dart b/lib/pods/websocket.dart index f6ed332..afd8155 100644 --- a/lib/pods/websocket.dart +++ b/lib/pods/websocket.dart @@ -51,8 +51,8 @@ class WebSocketService { Future connect(Ref ref) async { _ref = ref; - _statusStreamController.sink.add(WebSocketState.connecting()); + final baseUrl = ref.watch(serverUrlProvider); final atk = await getFreshAtk( ref.watch(tokenPairProvider), @@ -141,19 +141,6 @@ class WebSocketStateNotifier extends StateNotifier { state = const WebSocketState.connecting(); try { final service = ref.read(websocketProvider); - final baseUrl = ref.watch(serverUrlProvider); - final atk = await getFreshAtk( - ref.watch(tokenPairProvider), - baseUrl, - onRefreshed: (atk, rtk) { - setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk); - ref.invalidate(tokenPairProvider); - }, - ); - if (atk == null) { - state = const WebSocketState.error('Unauthorized'); - return; - } await service.connect(ref); state = const WebSocketState.connected(); service.statusStream.listen((event) { diff --git a/lib/screens/notification.dart b/lib/screens/notification.dart index d10299b..3bab117 100644 --- a/lib/screens/notification.dart +++ b/lib/screens/notification.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:math' as math; import 'package:auto_route/auto_route.dart'; @@ -7,6 +8,7 @@ import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/user.dart'; import 'package:island/pods/network.dart'; +import 'package:island/pods/websocket.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/content/markdown.dart'; @@ -21,8 +23,18 @@ part 'notification.g.dart'; @riverpod class NotificationUnreadCountNotifier extends _$NotificationUnreadCountNotifier { + StreamSubscription? _subscription; + @override Future build() async { + // Subscribe to websocket events when this provider is built + _subscribeToWebSocket(); + + // Dispose the subscription when this provider is disposed + ref.onDispose(() { + _subscription?.cancel(); + }); + try { final client = ref.read(apiClientProvider); final response = await client.get('/notifications/count'); @@ -32,9 +44,23 @@ class NotificationUnreadCountNotifier } } + void _subscribeToWebSocket() { + final webSocketService = ref.read(websocketProvider); + _subscription = webSocketService.dataStream.listen((packet) { + if (packet.type == 'notifications.new') { + _incrementCounter(); + } + }); + } + + Future _incrementCounter() async { + final current = await future; + state = AsyncData(current + 1); + } + Future decrement(int count) async { final current = await future; - state = AsyncData(math.min(current - count, 0)); + state = AsyncData(math.max(current - count, 0)); } } @@ -94,6 +120,7 @@ class NotificationScreen extends HookConsumerWidget { notifierRefreshable: notificationListNotifierProvider.notifier, contentBuilder: (data, widgetCount, endItemView) => ListView.builder( + padding: EdgeInsets.zero, itemCount: widgetCount, itemBuilder: (context, index) { if (index == widgetCount - 1) { @@ -142,7 +169,7 @@ class NotificationScreen extends HookConsumerWidget { ], ), trailing: - notification.viewedAt == null + notification.viewedAt != null ? null : Container( width: 12,