// app.dart import '../config.dart'; import 'error-alert.dart'; import 'screens/splashscreen.dart'; import 'package:flutter/material.dart'; import 'screens/home.dart'; import 'package:flutter/services.dart'; import 'dart:async'; import 'dart:developer'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_web_browser/flutter_web_browser.dart'; import 'dart:convert'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter_app_auth_wrapper/flutter_app_auth_wrapper.dart'; import 'dart:io'; import 'package:uni_links/uni_links.dart'; enum AppMode { Default, Authorization, } enum Screen { App, OAuth, Dashboard } class App extends StatelessWidget { Future<Widget> initApplication() async { Uri initialUri; try { initialUri = await getInitialUri(); } on PlatformException { initialUri = null; } on FormatException { initialUri = null; } final prefs = await SharedPreferences.getInstance(); final host = prefs.getString('host'); return new MainApp(initialUri: initialUri, initialHost: host); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Vereign', theme: ThemeData( primaryColor: Color(0xFFd51d32), fontFamily: "Arial", textTheme: TextTheme( button: TextStyle(color: Colors.white, fontSize: 18.0), title: TextStyle(color: Colors.red))), home: new SplashScreen( navigateAfterFuture: initApplication, ) ); } } class MainApp extends StatefulWidget { MainApp({ @required this.initialUri, this.initialHost }); final Uri initialUri; final String initialHost; @override _MainAppState createState() => _MainAppState(); } class _MainAppState extends State<MainApp> { StreamSubscription _sub; /// "Default" when you open app, "Authorization" when app initiated /// from third party app AppMode _appMode; // Url of the app which invoked OAuth String _invokerURL; String _host = Config.appFlavor == Flavor.DEVELOPMENT ? Config.HOSTS[0] : Config.DEFAULT_APP_HOST; Screen _currentScreen = Screen.App; bool _buttonsHidden = true; @override initState() { super.initState(); // Set up app host if (widget.initialHost != null) { setState(() { _host = widget.initialHost; }); } // Subscribe to authorization events FlutterAppAuthWrapper.eventStream().listen((data) async { var token = json.decode(data.toString())["access_token"]; setScreen(Screen.App); try { await launch("$_invokerURL?token=$token&host=$_host"); } catch (e) { showErrorAlert(context, 'Unable to open URL $_invokerURL', openVereign); } revealButtons(1); }, onError: (error) { log("Err $error"); String errorMessage = error.message; String errorDetails = ""; try { errorDetails = json.decode(error.details)["errorDescription"]; } catch (e) { errorDetails = error.details; } if ( // Handle cancellation for Android errorDetails == 'User cancelled flow' || // Handle cancellation for iOS errorMessage.toLowerCase().contains("the operation couldn") ) { if (Platform.isAndroid) { // Reveal after three seconds revealButtons(3); // Open only for android, because iOS will show the same alert as // was for Auth request openVereign(); } else { setScreen(Screen.App); revealButtons(0); } } else { showErrorAlert(context, Platform.isAndroid ? errorDetails : errorMessage, openVereign); setScreen(Screen.App); revealButtons(0); } }); // Show buttons after timeout revealButtons(3); initUniLinks(); } @override dispose() { if (_sub != null) _sub.cancel(); super.dispose(); } Future<Null> initUniLinks() async { handleLinkChange(widget.initialUri); _sub = getUriLinksStream().listen((Uri uri) { handleLinkChange(uri); }, onError: (err) { log('got err: $err'); }); } hideButtons() { if (_revealTimer != null && _revealTimer.isActive) { _revealTimer.cancel(); } setState(() { _buttonsHidden = true; }); } Timer _revealTimer; revealButtons(delay) { _revealTimer = Timer( Duration(seconds: delay), () { setState(() { _buttonsHidden = false; }); } ); } handleLinkChange(Uri uri) { if (uri?.path == "/authorize") { setState(() { _appMode = AppMode.Authorization; _invokerURL = uri.queryParameters["invokerUrl"]; }); startOAuth(); } else { setState(() { _appMode = AppMode.Default; }); openVereign(); } } setScreen(Screen screen) { setState(() { _currentScreen = screen; }); } openVereign() { setScreen(Screen.Dashboard); FlutterWebBrowser.openWebPage(url: _host, androidToolbarColor: Color(0xFFd51d32)); } startOAuth() { if (_currentScreen == Screen.OAuth) { return; } // Hide buttons so they wont blink after we close or finish oauth hideButtons(); setScreen(Screen.OAuth); var params = Config.getOAuthParams(host: _host); FlutterAppAuthWrapper.startAuth( AuthConfig( clientId: params["clientId"], clientSecret: params["clientSecret"], redirectUrl: params["redirectUrl"], state: "login", prompt: "consent", endpoint: AuthEndpoint( auth: params["authEndpoint"], token: params["tokenEndpoint"]), scopes: [ "user_account_status", "user_territory", "user_profile" ], ), ); } setHost(String host) { setState(() { _host = host; }); } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar(title: Text("Vereign")), body: Home( mode: _appMode, host: _host, setHost: setHost, openDashboardClick: openVereign, authorizeClick: startOAuth, buttonsHidden: _buttonsHidden ) ); } }