fix relay toggling

This commit is contained in:
gitea
2025-11-08 14:09:10 +01:00
parent b1a7b44efa
commit d85219ccbb
9 changed files with 440 additions and 153 deletions
+48 -2
View File
@@ -87,7 +87,17 @@ class NostrService {
}
/// Gets the list of configured relays.
///
/// Automatically disables any relays that are enabled but not connected,
/// since enabled should always mean connected.
List<NostrRelay> getRelays() {
// Ensure enabled relays are actually connected
// If a relay is enabled but not connected, disable it
for (final relay in _relays) {
if (relay.isEnabled && !relay.isConnected) {
relay.isEnabled = false;
}
}
return List.unmodifiable(_relays);
}
@@ -120,8 +130,11 @@ class NostrService {
// Wrap in try-catch to ensure synchronous errors are caught
WebSocketChannel channel;
try {
Logger.info('Creating WebSocket connection to: $relayUrl');
channel = WebSocketChannel.connect(Uri.parse(relayUrl));
Logger.debug('WebSocketChannel created for: $relayUrl');
} catch (e) {
Logger.error('Failed to create WebSocketChannel for: $relayUrl', e);
throw NostrException('Failed to connect to relay: $e');
}
_connections[relayUrl] = channel;
@@ -129,12 +142,33 @@ class NostrService {
final controller = StreamController<Map<String, dynamic>>.broadcast();
_messageControllers[relayUrl] = controller;
// Don't set isConnected = true immediately - wait for actual connection
// The connection might fail asynchronously
// Mark connection as established after a short delay if no errors occur
// WebSocket connection is established when channel is created successfully
// We'll wait a bit to catch any immediate connection errors
bool connectionConfirmed = false;
bool hasError = false;
// Set up error tracking before listening
Timer? connectionTimer;
connectionTimer = Timer(const Duration(milliseconds: 500), () {
if (!hasError && !connectionConfirmed) {
// No errors occurred, connection is established
connectionConfirmed = true;
relay.isConnected = true;
Logger.info('Connection confirmed for relay: $relayUrl (no errors after 500ms)');
}
});
// Listen for messages
channel.stream.listen(
(message) {
// First message received - connection is confirmed
if (!connectionConfirmed) {
connectionConfirmed = true;
relay.isConnected = true;
Logger.info('Connection confirmed for relay: $relayUrl (first message received)');
connectionTimer?.cancel();
}
try {
final data = jsonDecode(message as String);
if (data is List && data.isNotEmpty) {
@@ -168,11 +202,23 @@ class NostrService {
}
},
onError: (error) {
hasError = true;
connectionTimer?.cancel();
Logger.error('WebSocket error for relay: $relayUrl', error);
relay.isConnected = false;
// Automatically disable relay when connection error occurs
relay.isEnabled = false;
Logger.warning('Relay $relayUrl disabled due to connection error');
controller.addError(NostrException('Relay error: $error'));
},
onDone: () {
hasError = true;
connectionTimer?.cancel();
Logger.warning('WebSocket stream closed for relay: $relayUrl');
relay.isConnected = false;
// Automatically disable relay when connection closes
relay.isEnabled = false;
Logger.warning('Relay $relayUrl disabled due to stream closure');
controller.close();
},
);