Files
lunasea/lib/main.dart
Jagandeep Brar 57404f2dc2 [Release] v5.0.0 (50000013) (#376)
NEW
- [-Arr/Releases] Match torrent seeder colours to the web GUI
- [Firebase/Analytics] Added analytics for breadcrumb tracking in crashes
- [Logger] Utilize a new, custom built on-device logging system
- [Logger] Compact/delete old log entries once the log count passes 100
- [Logger] Exported logs are now in JSON format
- [Routing] Protect all module routes by showing a "Not Enabled" screen when the module is not enabled
- [Settings/System] Added toggle to disable Firebase Analytics
- [Tautulli/Activity] Show custom season titles from Plex's new TV agent

TWEAKS
- [Radarr/Files] Add languages to file block
- [Radarr/Files] Small changes to table titles
- [System/Logs] Reimplemented logger view
- [System/Logs] Removed viewing the stack trace within the application (still viewable within the exported logs)
- [System/Logs] Added the exception to the expanded table instead of a separate dialog popup
- [Tautulli/Activity] Minor UI tweaks including showing the full season title and italicizing the episode title
- [UI/Navbar] Jump instead of animate to page when tapping a navbar item

FIXES
- [Firebase/Crashes] Do not log DioError/networking exceptions
- [Flutter] Updated packages
- [Flutter] Upgrade all Comet.Tools packages to null-safety/NNBD
- [Radarr/Releases] Negative format scores were not being shown
- [Share] The sharesheet could break after the first time it was opened
- [Strings] Safe-guard many substring operations
- [Tautulli/Activity] Play/paused/buffering icon was not properly left aligned to the text
- [Tautulli/Users] User images would not be fetched on newer versions of Tautulli
- [UI/UX] Modal scroll controller was not being attached to the ListView in a bottom modal sheet
- [UI/UX] Do not log errors when network images fail to load
- [UI/UX] Prevent attempting to load background images that are passed an empty URL
- [URLs] Safe-guard launching specific invalid URLs
2021-03-17 19:51:28 -05:00

126 lines
4.5 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:lunasea/core.dart';
/// LunaSea Entry Point: Initialize & Run Application
///
/// Runs app in guarded zone to attempt to capture fatal (crashing) errors
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await _init();
runZonedGuarded(
() => runApp(
EasyLocalization(
supportedLocales: LunaLocalization().supportedLocales,
path: LunaLocalization().fileDirectory,
fallbackLocale: LunaLocalization().fallbackLocale,
useFallbackTranslations: true,
child: LunaBIOS(),
),
),
(error, stack) => LunaLogger().critical(error, stack),
);
}
/// Initializes LunaSea before running the BIOS Widget.
///
/// Sets up (in order):
/// - System UI Overlay Styling
/// - Logger
/// - Network
/// - Image Cache
/// - Router
/// - Firebase
/// - IAPs
/// - Database
///
/// Does not call [WidgetsFlutterBinding.ensureInitialized()] as that is called during Sentry's initialization.
/// If Sentry is removed, you should call that method to prevent black-screen flashing on launch.
Future<void> _init() async {
//Set system UI overlay style (navbar, statusbar)
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Colors.black,
systemNavigationBarDividerColor: Colors.black,
statusBarColor: Colors.transparent,
));
//LunaSea initialization
await Database().initialize();
await LunaFirebase().initialize();
LunaLogger().initialize();
LunaNetworking().initialize();
LunaImageCache().initialize();
LunaRouter().intialize();
await LunaInAppPurchases().initialize();
await LunaLocalization().initialize();
}
class LunaBIOS extends StatefulWidget {
@override
State<StatefulWidget> createState() => _State();
}
class _State extends State<LunaBIOS> {
StreamSubscription _firebaseOnMessageListener;
StreamSubscription _firebaseOnMessageOpenedAppListener;
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) => _boot());
}
@override
void dispose() {
Future.wait([
if(_firebaseOnMessageListener != null) _firebaseOnMessageListener.cancel(),
if(_firebaseOnMessageOpenedAppListener != null) _firebaseOnMessageOpenedAppListener.cancel(),
Database().deinitialize(),
LunaInAppPurchases().deinitialize(),
]).then((_) => super.dispose());
}
/// Runs the first-step boot sequence that is required for widgets
Future<void> _boot() async {
// Initialize notifications
// - Request notification permission
// - Add device token to Firebase (if logged in)
// - Check and handle initial message (if found)
// - Add notification listeners for onMessage and onMessageOpenedApp
await LunaFirebaseMessaging().requestNotificationPermissions();
LunaFirebaseFirestore().addDeviceToken();
LunaFirebaseMessaging().checkAndHandleInitialMessage();
_firebaseOnMessageListener = LunaFirebaseMessaging().onMessageListener();
_firebaseOnMessageOpenedAppListener = LunaFirebaseMessaging().onMessageOpenedAppListener();
// Remaining boot sequence
LunaQuickActions().initialize();
LunaChangelog().checkAndShowChangelog();
LunaFirebaseAnalytics().appOpened();
}
@override
Widget build(BuildContext context) => LunaState.providers(
child: ValueListenableBuilder(
valueListenable: Database.lunaSeaBox.listenable(keys: [
LunaDatabaseValue.THEME_AMOLED.key,
LunaDatabaseValue.THEME_AMOLED_BORDER.key,
]),
builder: (context, box, _) {
return MaterialApp(
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
routes: LunaRouter().routes,
onGenerateRoute: LunaRouter.router.generator,
navigatorKey: LunaState.navigatorKey,
navigatorObservers: [LunaFirebaseAnalytics.observer],
darkTheme: LunaTheme().activeTheme(),
theme: LunaTheme().activeTheme(),
title: 'LunaSea',
);
},
),
);
}