diff --git a/example/lib/main.dart b/example/lib/main.dart index b7ed2d3..5dc9be8 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -20,7 +20,7 @@ class MyApp extends StatelessWidget { home: LenraApplication( clientId: 'XXX-XXX-XXX', child: const MyHomePage(title: 'Flutter Demo Home Page'), - loginWidgetBuilder: (BuildContext context, VoidCallback login) => + loginWidgetBuilder: (BuildContext context, VoidCallback login, Object? error) => Scaffold( body: Center( child: TextButton( diff --git a/example/pubspec.lock b/example/pubspec.lock index ccb93b2..51b5f54 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" crypto: dependency: transitive description: @@ -211,26 +211,26 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" nested: dependency: transitive description: @@ -296,26 +296,26 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -336,10 +336,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" typed_data: dependency: transitive description: @@ -420,6 +420,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + url: "https://pub.dev" + source: hosted + version: "0.3.0" window_to_front: dependency: transitive description: @@ -429,5 +437,5 @@ packages: source: hosted version: "0.0.3" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/lib/application.dart b/lib/application.dart index 4c6611a..dee3ac2 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -10,7 +10,8 @@ import 'package:oauth2_client/access_token_response.dart'; const defaultLoader = Center(child: CircularProgressIndicator()); -typedef LoginWidgetBuilder = Widget Function(BuildContext, VoidCallback); +typedef LoginWidgetBuilder = Widget Function( + BuildContext, VoidCallback, Object?); /// A widget that handles the Lenra OAuth2 authentication flow. class LenraApplication extends StatefulWidget { @@ -20,7 +21,7 @@ class LenraApplication extends StatefulWidget { /// The UI to show during the authentication flow. final Widget? loader; - /// The UI to show after the authentication flow. + /// The UI to show before the authentication flow. final LoginWidgetBuilder? loginWidgetBuilder; /// The lenra instance's OAuth base URI. @@ -61,6 +62,9 @@ class LenraApplication extends StatefulWidget { /// The OAuth2 helper for customizing OAuth configuration. final LenraOauth2Helper? oauth2helper; + /// Once logged in auto connect the socket. + final bool autoConnect; + /// Creates a new instance of [LenraOauth2Widget]. LenraApplication({ super.key, @@ -81,6 +85,7 @@ class LenraApplication extends StatefulWidget { this.loader, this.loginWidgetBuilder, this.oauth2helper, + this.autoConnect = false, }) { this.oauthRedirectPort = oauthRedirectPort ?? (kIsWeb ? Uri.base.port : 10000); @@ -96,6 +101,7 @@ class _LenraApplicationState extends State { late LenraOauth2Helper oauth2; bool gettingLocalToken = true; bool isLogging = false; + Object? error; @override void initState() { @@ -138,18 +144,25 @@ class _LenraApplicationState extends State { future: oauth2.getToken(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.hasError) { - return Text('Error ${snapshot.error}'); + if (!snapshot.hasError) { + return SocketManager( + appName: widget.appName, + endpoint: widget.socketEndpoint, + token: snapshot.data as AccessTokenResponse, + autoConnect: widget.autoConnect, + child: widget.child, + ); + } else { + Future.delayed(const Duration()).then( + (val) => setState(() { + error = snapshot.error; + if (widget.loginWidgetBuilder != null) isLogging = false; + }), + ); + return Container(); } - return SocketManager( - appName: widget.appName, - endpoint: widget.socketEndpoint, - token: snapshot.data as AccessTokenResponse, - child: widget.child, - ); - } else { - return widget.loader ?? defaultLoader; } + return widget.loader ?? defaultLoader; }, ), ); @@ -160,7 +173,7 @@ class _LenraApplicationState extends State { setState(() { isLogging = true; }); - }); + }, error); } } } diff --git a/lib/socket.dart b/lib/socket.dart index 67e02b6..afbd7b9 100644 --- a/lib/socket.dart +++ b/lib/socket.dart @@ -10,6 +10,7 @@ class SocketManager extends StatefulWidget { final String endpoint; final Widget child; final AccessTokenResponse token; + final bool autoConnect; const SocketManager({ Key? key, @@ -17,6 +18,7 @@ class SocketManager extends StatefulWidget { required this.child, required this.token, this.appName, + this.autoConnect = false, }) : super(key: key); @override @@ -27,6 +29,7 @@ class SocketManager extends StatefulWidget { class _SocketManagerState extends State { late PhoenixSocket socket; + bool connected = false; @override void initState() { @@ -46,7 +49,25 @@ class _SocketManagerState extends State { params, ); - socket.onError((error) => throw error); + socket.onOpen(() { + print("Socket opened"); + setState(() { + connected = true; + }); + }); + socket.onClose((_) { + print("Socket closed"); + setState(() { + connected = false; + }); + }); + socket.onError((error) { + print("Socket error: $error"); + throw error; + }); + if (widget.autoConnect) { + socket.connect(); + } } @override @@ -54,19 +75,31 @@ class _SocketManagerState extends State { return LenraSocket( socket: socket, child: widget.child, + connected: connected, ); } + + @override + void dispose() { + socket.disconnect(); + super.dispose(); + } } class LenraSocket extends InheritedWidget { final PhoenixSocket socket; + final bool connected; - const LenraSocket({super.key, required super.child, required this.socket}); + const LenraSocket( + {super.key, + required super.child, + required this.socket, + required this.connected}); @override bool updateShouldNotify(covariant InheritedWidget oldWidget) { if (oldWidget is! LenraSocket) return true; - return oldWidget.socket != socket; + return oldWidget.connected != connected || oldWidget.socket != socket; } static LenraSocket? maybeOf(BuildContext context) { diff --git a/pubspec.lock b/pubspec.lock index 0d73593..4da820f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" crypto: dependency: transitive description: @@ -196,26 +196,26 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" oauth2_client: dependency: "direct main" description: @@ -265,26 +265,26 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -305,10 +305,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" typed_data: dependency: transitive description: @@ -389,6 +389,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + url: "https://pub.dev" + source: hosted + version: "0.3.0" window_to_front: dependency: transitive description: @@ -398,5 +406,5 @@ packages: source: hosted version: "0.0.3" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0"