✨ Reactive notification unread count
This commit is contained in:
parent
bfa97dcd11
commit
9c1a983466
@ -51,8 +51,8 @@ class WebSocketService {
|
|||||||
|
|
||||||
Future<void> connect(Ref ref) async {
|
Future<void> connect(Ref ref) async {
|
||||||
_ref = ref;
|
_ref = ref;
|
||||||
|
|
||||||
_statusStreamController.sink.add(WebSocketState.connecting());
|
_statusStreamController.sink.add(WebSocketState.connecting());
|
||||||
|
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final atk = await getFreshAtk(
|
||||||
ref.watch(tokenPairProvider),
|
ref.watch(tokenPairProvider),
|
||||||
@ -141,19 +141,6 @@ class WebSocketStateNotifier extends StateNotifier<WebSocketState> {
|
|||||||
state = const WebSocketState.connecting();
|
state = const WebSocketState.connecting();
|
||||||
try {
|
try {
|
||||||
final service = ref.read(websocketProvider);
|
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);
|
await service.connect(ref);
|
||||||
state = const WebSocketState.connected();
|
state = const WebSocketState.connected();
|
||||||
service.statusStream.listen((event) {
|
service.statusStream.listen((event) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
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:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
@ -21,8 +23,18 @@ part 'notification.g.dart';
|
|||||||
@riverpod
|
@riverpod
|
||||||
class NotificationUnreadCountNotifier
|
class NotificationUnreadCountNotifier
|
||||||
extends _$NotificationUnreadCountNotifier {
|
extends _$NotificationUnreadCountNotifier {
|
||||||
|
StreamSubscription<WebSocketPacket>? _subscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<int> build() async {
|
Future<int> 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 {
|
try {
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
final response = await client.get('/notifications/count');
|
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<void> _incrementCounter() async {
|
||||||
|
final current = await future;
|
||||||
|
state = AsyncData(current + 1);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> decrement(int count) async {
|
Future<void> decrement(int count) async {
|
||||||
final current = await future;
|
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,
|
notifierRefreshable: notificationListNotifierProvider.notifier,
|
||||||
contentBuilder:
|
contentBuilder:
|
||||||
(data, widgetCount, endItemView) => ListView.builder(
|
(data, widgetCount, endItemView) => ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
itemCount: widgetCount,
|
itemCount: widgetCount,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index == widgetCount - 1) {
|
if (index == widgetCount - 1) {
|
||||||
@ -142,7 +169,7 @@ class NotificationScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing:
|
trailing:
|
||||||
notification.viewedAt == null
|
notification.viewedAt != null
|
||||||
? null
|
? null
|
||||||
: Container(
|
: Container(
|
||||||
width: 12,
|
width: 12,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user