refactor: sockets to use riverpod

This commit is contained in:
cogwheel0
2025-09-29 00:22:12 +05:30
parent 0ba48030c8
commit 3dfa5c6ec8
5 changed files with 410 additions and 49 deletions

View File

@@ -1,8 +1,13 @@
import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../providers/app_providers.dart';
part 'connectivity_service.g.dart';
enum ConnectivityStatus { online, offline, checking }
class ConnectivityService {
@@ -211,10 +216,29 @@ final connectivityServiceProvider = Provider<ConnectivityService>((ref) {
return service;
});
final connectivityStatusProvider = StreamProvider<ConnectivityStatus>((ref) {
final service = ref.watch(connectivityServiceProvider);
return service.connectivityStream;
});
@Riverpod(keepAlive: true)
class ConnectivityStatusNotifier extends _$ConnectivityStatusNotifier {
StreamSubscription<ConnectivityStatus>? _subscription;
@override
FutureOr<ConnectivityStatus> build() {
final service = ref.watch(connectivityServiceProvider);
_subscription?.cancel();
_subscription = service.connectivityStream.listen(
(status) => state = AsyncValue.data(status),
onError: (error, stackTrace) =>
state = AsyncValue.error(error, stackTrace),
);
ref.onDispose(() {
_subscription?.cancel();
_subscription = null;
});
return service.currentStatus;
}
}
final isOnlineProvider = Provider<bool>((ref) {
// In reviewer mode, treat app as online to enable flows

View File

@@ -4,6 +4,7 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import '../../core/models/chat_message.dart';
import '../../core/models/socket_event.dart';
import '../../core/services/persistent_streaming_service.dart';
import '../../core/services/socket_service.dart';
import '../../core/utils/inactivity_watchdog.dart';
@@ -25,7 +26,7 @@ class ActiveSocketStream {
});
final StreamSubscription<String> streamSubscription;
final List<SocketEventSubscription> socketSubscriptions;
final List<VoidCallback> socketSubscriptions;
final VoidCallback disposeWatchdog;
}
@@ -44,6 +45,8 @@ ActiveSocketStream attachUnifiedChunkedStreaming({
required String? activeConversationId,
required dynamic api,
required SocketService? socketService,
Stream<ConversationDelta>? chatEvents,
Stream<ConversationDelta>? channelEvents,
// Message update callbacks
required void Function(String) appendToLastMessage,
required void Function(String) replaceLastMessageContent,
@@ -91,8 +94,10 @@ ActiveSocketStream attachUnifiedChunkedStreaming({
);
InactivityWatchdog? socketWatchdog;
final socketSubscriptions = <SocketEventSubscription>[];
if (socketService != null) {
final socketSubscriptions = <VoidCallback>[];
final hasSocketSignals =
socketService != null || chatEvents != null || channelEvents != null;
if (hasSocketSignals) {
// Increase timeout to match OpenWebUI's more generous timeouts for long responses
socketWatchdog = InactivityWatchdog(
window: const Duration(minutes: 15), // Increased from 5 to 15 minutes
@@ -102,8 +107,10 @@ ActiveSocketStream attachUnifiedChunkedStreaming({
scope: 'streaming/helper',
);
try {
for (final sub in socketSubscriptions) {
sub.dispose();
for (final dispose in socketSubscriptions) {
try {
dispose();
} catch (_) {}
}
socketSubscriptions.clear();
} catch (_) {}
@@ -124,9 +131,9 @@ ActiveSocketStream attachUnifiedChunkedStreaming({
if (socketSubscriptions.isEmpty) {
return;
}
for (final sub in socketSubscriptions) {
for (final dispose in socketSubscriptions) {
try {
sub.dispose();
dispose();
} catch (_) {}
}
socketSubscriptions.clear();
@@ -983,22 +990,40 @@ ActiveSocketStream attachUnifiedChunkedStreaming({
} catch (_) {}
}
if (socketService != null) {
if (chatEvents != null) {
final subscription = chatEvents.listen((event) {
socketWatchdog?.ping();
chatHandler(event.raw, event.ack);
});
socketSubscriptions.add(() {
unawaited(subscription.cancel());
});
} else if (socketService != null) {
final chatSub = socketService.addChatEventHandler(
conversationId: activeConversationId,
sessionId: sessionId,
requireFocus: false,
handler: chatHandler,
);
socketSubscriptions.add(chatSub);
socketSubscriptions.add(chatSub.dispose);
}
if (channelEvents != null) {
final subscription = channelEvents.listen((event) {
socketWatchdog?.ping();
channelEventsHandler(event.raw, event.ack);
});
socketSubscriptions.add(() {
unawaited(subscription.cancel());
});
} else if (socketService != null) {
final channelSub = socketService.addChannelEventHandler(
conversationId: activeConversationId,
sessionId: sessionId,
requireFocus: false,
handler: channelEventsHandler,
);
socketSubscriptions.add(channelSub);
socketSubscriptions.add(channelSub.dispose);
}
final subscription = persistentController.stream.listen(