Skip to content

Commit ceb698d

Browse files
committed
fix: disconnect open realtime client after flutter web hot-restart
1 parent 6a86752 commit ceb698d

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'package:supabase_flutter/supabase_flutter.dart';
2+
3+
void markRealtimeClientToBeDisconnected(RealtimeClient client) {}
4+
5+
void disconnectPreviousRealtimeClient() {}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import 'dart:js_interop';
2+
3+
import 'package:supabase_flutter/supabase_flutter.dart';
4+
5+
@JS()
6+
external JSFunction? supabaseFlutterWSToClose;
7+
8+
/// Store a function to properly disconnect the previous [RealtimeClient] in
9+
/// the js context.
10+
///
11+
/// WebSocket connections are not closed when Flutter is hot-restarted on web.
12+
///
13+
/// This causes old dart code that is still associated with the WebSocket
14+
/// connection to be still running and causes unexpected behavior like type
15+
/// errors and the fact that the events to the old connection may still be
16+
/// logged.
17+
void markRealtimeClientToBeDisconnected(RealtimeClient client) {
18+
void disconnect() {
19+
client.disconnect(
20+
code: 1000, reason: 'Closed due to Flutter Web hot-restart');
21+
}
22+
23+
supabaseFlutterWSToClose = disconnect.toJS;
24+
}
25+
26+
/// Disconnect the previous [RealtimeClient] if it exists.
27+
///
28+
/// This is done by calling the function stored by
29+
/// [markRealtimeClientToBeDisconnected] from the js context
30+
void disconnectPreviousRealtimeClient() {
31+
if (supabaseFlutterWSToClose != null) {
32+
supabaseFlutterWSToClose!.callAsFunction();
33+
supabaseFlutterWSToClose = null;
34+
}
35+
}

packages/supabase_flutter/lib/src/supabase.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import 'package:supabase_flutter/src/flutter_go_true_client_options.dart';
1111
import 'package:supabase_flutter/src/local_storage.dart';
1212
import 'package:supabase_flutter/src/supabase_auth.dart';
1313

14+
import 'realtime_cleanup_stub.dart'
15+
if (dart.library.js_interop) 'realtime_cleanup_web.dart';
16+
1417
import 'version.dart';
1518

1619
final _log = Logger('supabase.supabase_flutter');
@@ -203,6 +206,8 @@ class Supabase with WidgetsBindingObserver {
203206
authOptions: authOptions,
204207
accessToken: accessToken,
205208
);
209+
disconnectPreviousRealtimeClient();
210+
markRealtimeClientToBeDisconnected(client.realtime);
206211
_widgetsBindingInstance?.addObserver(this);
207212
_initialized = true;
208213
}

0 commit comments

Comments
 (0)