moxxy/lib/main.dart
Alexander "PapaTutuWawa 8800be6423 service: Fix the app getting stuck in release mode
It turns out that a release build is much faster than a
development build. The issue was that the UI sent the
[PerformPreStartCommand] too early as the background service
still had work to do before being considered ready.

As a solution we now either wait for the event to arrive by
itself, as the service sends it at the end of its initilization, or
after an explicit request if the service is already running.
2022-04-19 13:30:56 +02:00

250 lines
8.6 KiB
Dart

import "dart:async";
import "package:moxxyv2/ui/events.dart";
import "package:moxxyv2/ui/constants.dart";
/*
import "package:moxxyv2/ui/pages/register/register.dart";
import "package:moxxyv2/ui/pages/postregister/postregister.dart";
import "package:moxxyv2/ui/pages/sendfiles.dart";
*/
import "package:moxxyv2/ui/pages/addcontact.dart";
import "package:moxxyv2/ui/pages/blocklist.dart";
import "package:moxxyv2/ui/pages/conversation.dart";
import "package:moxxyv2/ui/pages/newconversation.dart";
import "package:moxxyv2/ui/pages/conversations.dart";
import "package:moxxyv2/ui/pages/login.dart";
import "package:moxxyv2/ui/pages/intro.dart";
import "package:moxxyv2/ui/pages/sharedmedia.dart";
import "package:moxxyv2/ui/pages/crop.dart";
import "package:moxxyv2/ui/pages/splashscreen/splashscreen.dart";
import "package:moxxyv2/ui/pages/settings/debugging.dart";
import "package:moxxyv2/ui/pages/settings/privacy.dart";
import "package:moxxyv2/ui/pages/settings/network.dart";
import "package:moxxyv2/ui/pages/settings/appearance.dart";
import "package:moxxyv2/ui/pages/profile/profile.dart";
import "package:moxxyv2/ui/pages/settings/settings.dart";
import "package:moxxyv2/ui/pages/settings/licenses.dart";
import "package:moxxyv2/ui/pages/settings/about.dart";
import "package:moxxyv2/ui/bloc/navigation_bloc.dart";
import "package:moxxyv2/ui/bloc/login_bloc.dart";
import "package:moxxyv2/ui/bloc/conversations_bloc.dart";
import "package:moxxyv2/ui/bloc/newconversation_bloc.dart";
import "package:moxxyv2/ui/bloc/conversation_bloc.dart";
import "package:moxxyv2/ui/bloc/blocklist_bloc.dart";
import "package:moxxyv2/ui/bloc/profile_bloc.dart";
import "package:moxxyv2/ui/bloc/preferences_bloc.dart";
import "package:moxxyv2/ui/bloc/addcontact_bloc.dart";
import "package:moxxyv2/ui/bloc/sharedmedia_bloc.dart";
import "package:moxxyv2/ui/bloc/crop_bloc.dart";
import "package:moxxyv2/ui/service/download.dart";
import "package:moxxyv2/ui/service/data.dart";
import "package:moxxyv2/ui/service/thumbnail.dart";
import "package:moxxyv2/service/service.dart";
import "package:moxxyv2/shared/commands.dart";
import "package:moxxyv2/shared/backgroundsender.dart";
import "package:flutter/material.dart";
import "package:flutter_bloc/flutter_bloc.dart";
import "package:page_transition/page_transition.dart";
import "package:get_it/get_it.dart";
import "package:logging/logging.dart";
void setupLogging() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
// ignore: avoid_print
print("[${record.level.name}] (${record.loggerName}) ${record.time}: ${record.message}");
});
GetIt.I.registerSingleton<Logger>(Logger("MoxxyMain"));
}
Future<void> setupUIServices() async {
GetIt.I.registerSingleton<UIDownloadService>(UIDownloadService());
GetIt.I.registerSingleton<UIDataService>(UIDataService());
GetIt.I.registerSingleton<ThumbnailCacheService>(ThumbnailCacheService());
await GetIt.I.get<UIDataService>().init();
}
void setupBlocs(GlobalKey<NavigatorState> navKey) {
GetIt.I.registerSingleton<NavigationBloc>(NavigationBloc(navigationKey: navKey));
GetIt.I.registerSingleton<ConversationsBloc>(ConversationsBloc());
GetIt.I.registerSingleton<NewConversationBloc>(NewConversationBloc());
GetIt.I.registerSingleton<ConversationBloc>(ConversationBloc());
GetIt.I.registerSingleton<BlocklistBloc>(BlocklistBloc());
GetIt.I.registerSingleton<ProfileBloc>(ProfileBloc());
GetIt.I.registerSingleton<PreferencesBloc>(PreferencesBloc());
GetIt.I.registerSingleton<AddContactBloc>(AddContactBloc());
GetIt.I.registerSingleton<SharedMediaBloc>(SharedMediaBloc());
GetIt.I.registerSingleton<CropBloc>(CropBloc());
}
// TODO: Replace all Column(children: [ Padding(), Padding, ...]) with a
// Padding(padding: ..., child: Column(children: [ ... ]))
// TODO: Theme the switches
void main() async {
GetIt.I.registerSingleton<Completer>(Completer());
setupLogging();
await setupUIServices();
await initializeServiceIfNeeded();
setupEventHandler();
GetIt.I.registerSingleton<BackgroundServiceDataSender>(BackgroundServiceDataSender());
final navKey = GlobalKey<NavigatorState>();
setupBlocs(navKey);
runApp(
MultiBlocProvider(
providers: [
BlocProvider<NavigationBloc>(
create: (_) => GetIt.I.get<NavigationBloc>()
),
BlocProvider<LoginBloc>(
create: (_) => LoginBloc()
),
BlocProvider<ConversationsBloc>(
create: (_) => GetIt.I.get<ConversationsBloc>()
),
BlocProvider<NewConversationBloc>(
create: (_) => GetIt.I.get<NewConversationBloc>()
),
BlocProvider<ConversationBloc>(
create: (_) => GetIt.I.get<ConversationBloc>()
),
BlocProvider<BlocklistBloc>(
create: (_) => GetIt.I.get<BlocklistBloc>()
),
BlocProvider<ProfileBloc>(
create: (_) => GetIt.I.get<ProfileBloc>()
),
BlocProvider<PreferencesBloc>(
create: (_) => GetIt.I.get<PreferencesBloc>()
),
BlocProvider<AddContactBloc>(
create: (_) => GetIt.I.get<AddContactBloc>()
),
BlocProvider<SharedMediaBloc>(
create: (_) => GetIt.I.get<SharedMediaBloc>()
),
BlocProvider<CropBloc>(
create: (_) => GetIt.I.get<CropBloc>()
)
],
child: MyApp(navKey)
)
);
}
class MyApp extends StatefulWidget {
final GlobalKey<NavigatorState> navigationKey;
const MyApp(this.navigationKey, { Key? key }) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
_MyAppState();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
// Lift the UI block
GetIt.I.get<Completer>().complete();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
final sender = GetIt.I.get<BackgroundServiceDataSender>();
switch (state) {
case AppLifecycleState.paused: {
sender.sendData(
SetCSIStateCommand(active: false)
);
GetIt.I.get<ConversationBloc>().add(AppStateChanged(false));
}
break;
case AppLifecycleState.resumed: {
sender.sendData(
SetCSIStateCommand(active: true)
);
GetIt.I.get<ConversationBloc>().add(AppStateChanged(true));
}
break;
default: break;
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Moxxy",
theme: ThemeData(
primarySwatch: Colors.blue,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
primary: primaryColor,
onPrimary: Colors.white
)
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
primary: primaryColor
)
),
// NOTE: Mainly for the SettingsSection
colorScheme: const ColorScheme.dark(
secondary: primaryColor
),
backgroundColor: const Color(0xff303030)
),
navigatorKey: widget.navigationKey,
themeMode: ThemeMode.system,
onGenerateRoute: (settings) {
switch (settings.name) {
case introRoute: return Intro.route;
case loginRoute: return Login.route;
case conversationsRoute: return ConversationsPage.route;
case newConversationRoute: return NewConversationPage.route;
case conversationRoute: return PageTransition(
child: const ConversationPage(),
type: PageTransitionType.rightToLeft,
settings: settings
);
case sharedMediaRoute: return SharedMediaPage.route;
case blocklistRoute: return BlocklistPage.route;
case profileRoute: return ProfilePage.route;
case settingsRoute: return SettingsPage.route;
case aboutRoute: return SettingsAboutPage.route;
case licensesRoute: return SettingsLicensesPage.route;
case appearanceRoute: return AppearancePage.route;
case networkRoute: return NetworkPage.route;
case privacyRoute: return PrivacyPage.route;
case debuggingRoute: return DebuggingPage.route;
case addContactRoute: return AddContactPage.route;
case cropRoute: return CropPage.route;
}
return null;
},
home: const Splashscreen()
);
}
}