diff --git a/lib/helpers/events_helper.dart b/lib/helpers/events_helper.dart new file mode 100644 index 0000000..287b397 --- /dev/null +++ b/lib/helpers/events_helper.dart @@ -0,0 +1,32 @@ +import 'dart:async'; + +import 'package:event_bus/event_bus.dart'; + +/// Events helper +/// +/// @author Pierre Hubert + +/// Main WebSocket closed +class WSClosedEvent {} + +class EventsHelper { + static EventBus _mgr = EventBus(); + + /// Listen to event + /// + /// Do not use this method directly. You should instead prefer to use + /// [SafeState.listen] to handle safely widgets lifecycle... + /// + /// You can not register to global events + static StreamSubscription on(void onData(T event)) { + if (T == dynamic) throw Exception("Do not register to all events!"); + + final stream = _mgr.on(); + return stream.listen(onData); + } + + /// Propagate an event + static void emit(T event) { + _mgr.fire(event); + } +} diff --git a/lib/helpers/websocket_helper.dart b/lib/helpers/websocket_helper.dart index a137eb1..fde8abb 100644 --- a/lib/helpers/websocket_helper.dart +++ b/lib/helpers/websocket_helper.dart @@ -1,3 +1,4 @@ +import 'package:comunic/helpers/events_helper.dart'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/config.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; @@ -28,7 +29,7 @@ class WebSocketHelper { // First, get an access token final token = await _getWsToken(); - // Determine websocket URI + // Determine WebSocket URI final wsURL = "${(config().apiServerSecure ? "wss" : "ws")}://${config() .apiServerName}${config().apiServerUri}ws?token=$token"; @@ -48,7 +49,10 @@ class WebSocketHelper { }, // Notify when the channel is closed - onDone: () => print("WS Channel closed"), + onDone: () { + print("WS Channel closed"); + EventsHelper.emit(WSClosedEvent()); + }, ); } } diff --git a/lib/ui/widgets/init_widget.dart b/lib/ui/widgets/init_widget.dart index 44727c1..2f18bd6 100644 --- a/lib/ui/widgets/init_widget.dart +++ b/lib/ui/widgets/init_widget.dart @@ -1,5 +1,7 @@ +import 'package:comunic/helpers/events_helper.dart'; import 'package:comunic/helpers/websocket_helper.dart'; import 'package:comunic/ui/routes/main_route.dart'; +import 'package:comunic/ui/widgets/safe_state.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:flutter/material.dart'; @@ -17,7 +19,7 @@ class InitializeWidget extends StatefulWidget { _InitializeWidgetState createState() => _InitializeWidgetState(); } -class _InitializeWidgetState extends State { +class _InitializeWidgetState extends SafeState { bool _error = false; @override @@ -25,6 +27,9 @@ class _InitializeWidgetState extends State { _tryConnect(); super.initState(); + + // Listen to WebSocket close event + super.listen((e) => _tryConnect()); } /// Try to connect to server diff --git a/lib/ui/widgets/safe_state.dart b/lib/ui/widgets/safe_state.dart index 5fedbe5..0ee8316 100644 --- a/lib/ui/widgets/safe_state.dart +++ b/lib/ui/widgets/safe_state.dart @@ -1,3 +1,6 @@ +import 'dart:async'; + +import 'package:comunic/helpers/events_helper.dart'; import 'package:flutter/material.dart'; /// Little State hack to avoid issues @@ -5,9 +8,26 @@ import 'package:flutter/material.dart'; /// @author Pierre HUBERT abstract class SafeState extends State { + + final _subscriptions = List(); + + @override + void dispose() { + // Close subscriptions + _subscriptions.forEach((f) => f.cancel()); + + super.dispose(); + } + @override void setState(fn) { if(mounted) super.setState(fn); } + + /// Register to a new subscription + @protected + void listen(void onEvent(T event)) { + _subscriptions.add(EventsHelper.on(onEvent)); + } } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 652e023..d41b1da 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -106,6 +106,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.9" + event_bus: + dependency: "direct main" + description: + name: event_bus + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 64915d3..5e84d79 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -72,6 +72,9 @@ dependencies: # Establish WebSocket connections web_socket_channel: ^1.1.0 + # Events manager + event_bus: ^1.1.1 + dev_dependencies: flutter_test: sdk: flutter