import 'dart:async'; import 'package:flutter/material.dart'; import 'core/app_controller.dart'; import 'l10n/strings.dart'; import 'services/blob_store.dart'; import 'services/secure_store.dart'; import 'services/local_files.dart'; import 'ui/adaptive.dart'; import 'ui/gates.dart'; import 'ui/theme.dart'; import 'ui/workspace.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); unawaited(purgeTransferCache().catchError((Object _) {})); final controller = AppController(DeviceStore.normal, blobs: FileBlobStore()); runApp(SmMobileApp(controller)); controller.initialize(); } class SmMobileApp extends StatefulWidget { final AppController controller; const SmMobileApp(this.controller, {super.key}); @override State createState() => _SmMobileAppState(); } class _SmMobileAppState extends State { final navigator = GlobalKey(); @override void initState() { super.initState(); widget.controller.onLocked = () { unawaited(purgeTransferCache().catchError((Object _) {})); navigator.currentState?.popUntil((r) => r.isFirst); }; } @override Widget build(BuildContext context) => ListenableBuilder( listenable: widget.controller, builder: (_, _) { final c = widget.controller; return MaterialApp( navigatorKey: navigator, title: 'SM Mobile', debugShowCheckedModeBanner: false, locale: c.locale, supportedLocales: AppLocalizations.supportedLocales, localizationsDelegates: AppLocalizations.localizationsDelegates, theme: buildTheme(Brightness.light), darkTheme: buildTheme(Brightness.dark), themeMode: c.theme, builder: (context, child) => Listener( onPointerDown: (_) => c.activity(), onPointerMove: (_) => c.activity(), // iOS and Android keep the keyboard open after a tap outside a // text field; a tap on empty space closes it. Taps on buttons, // fields and the terminal are won by their own recognizers. child: GestureDetector( behavior: HitTestBehavior.translucent, // Not an action for screen readers, only a touch convenience. excludeFromSemantics: true, onTap: () => FocusManager.instance.primaryFocus?.unfocus(), child: MinimumCanvas(child: child!), ), ), home: !c.ready ? const Scaffold(body: Center(child: CircularProgressIndicator())) : c.startupError != null ? Builder( builder: (context) => Scaffold( body: SafeArea( child: Center( child: Padding( padding: const EdgeInsets.all(24), child: Text(context.tr(c.startupError!)), ), ), ), ), ) : !c.accepted ? Onboarding(c) : !c.vault.unlocked ? VaultGate(c) : Workspace(c), ); }, ); }