import 'package:comunic/helpers/account_helper.dart'; import 'package:comunic/helpers/events_helper.dart'; import 'package:comunic/helpers/preferences_helper.dart'; import 'package:comunic/helpers/server_config_helper.dart'; import 'package:comunic/helpers/version_helper.dart'; import 'package:comunic/helpers/websocket_helper.dart'; import 'package:comunic/models/config.dart'; import 'package:comunic/ui/dialogs/deprecation_dialog.dart'; import 'package:comunic/ui/routes/main_route/main_route.dart'; import 'package:comunic/ui/routes/main_route/smartphone_route.dart'; import 'package:comunic/ui/routes/main_route/tablet_route.dart'; import 'package:comunic/ui/routes/tour_route.dart'; import 'package:comunic/ui/routes/welcome_route.dart'; import 'package:comunic/ui/widgets/login_routes_theme.dart'; import 'package:comunic/ui/widgets/safe_state.dart'; import 'package:comunic/utils/flutter_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; /// Comunic account initialization widget /// /// Application screens should only appears as children of this widget /// /// This widget ensures that the application is correctly initialized before /// starting it /// /// @author Pierre Hubert class InitializeWidget extends StatefulWidget { @override _InitializeWidgetState createState() => _InitializeWidgetState(); } class _InitializeWidgetState extends SafeState { bool _error = false; @override void initState() { _tryConnect(); super.initState(); // Check if login token are considered as invalid super.listen((ev) => _openLoginPage()); // Listen to WebSocket close event super.listen((e) { _popToMainRoute(); _tryConnect(); }); } @override void dispose() { super.dispose(); WebSocketHelper.close(); } /// Open login page _openLoginPage() { Navigator.of(context) .pushReplacement(MaterialPageRoute(builder: (c) => WelcomeRoute())); } /// Try to connect to server void _tryConnect() async { try { await ServerConfigurationHelper.ensureLoaded(); if (!isWeb && ServerConfigurationHelper.config.minSupportedMobileVersion > VersionHelper.version) await showDeprecationDialog(context); if (!AccountHelper.isUserIDLoaded) { _popToMainRoute(); _openLoginPage(); return; } setState(() { _error = false; }); await WebSocketHelper.connect(); final prefs = await PreferencesHelper.getInstance(); if (!prefs.getBool(PreferencesKeyList.IS_TOUR_SEEN)) await showTour(context); print("Attempting WebSocket connection..."); setState(() {}); } catch (e, stack) { print("Could not connect to server! $e"); print(stack); _popToMainRoute(); setState(() { _error = true; }); } } @override Widget build(BuildContext context) { return (!_error && WebSocketHelper.isConnected()) ? (isTablet(context) ? TabletRoute(key: mainControllerKey) : SmartphoneMainRoute(key: mainControllerKey)) : _buildNonReadyWidget(); } /// Build loading widget Widget _buildNonReadyWidget() { return LoginRoutesTheme( child: Scaffold( backgroundColor: config().splashBackgroundColor, body: Center( child: Material( color: Colors.transparent, textStyle: TextStyle(color: Colors.white), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Spacer( flex: 4, ), Text( config().appName, style: TextStyle(fontSize: 50), ), Spacer( flex: 2, ), _error ? _buildErrorWidget() : _buildConnectingWidget(), Spacer( flex: 2, ), !isWeb ? Text(tr("Version %version% - Build %build%", args: { "version": VersionHelper.info.version.toString(), "build": VersionHelper.info.buildNumber.toString() })) : Container(), Spacer(flex: 1), ], ), ), ), ), ); } Widget _buildConnectingWidget() { return CircularProgressIndicator(); } Widget _buildErrorWidget() { return Column( children: [ Icon(Icons.error, color: Colors.white), SizedBox(height: 30), Text(tr("Could not connect to server!")), SizedBox( height: 30, ), ElevatedButton( onPressed: () => _tryConnect(), child: Text(tr("Try again")), ), ], ); } void _popToMainRoute() { // Pop until we reach main route Navigator.of(context).popUntil((settings) => ModalRoute.of(context).isCurrent || !ModalRoute.of(context).isActive); } }