You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fluffychat/lib/main.dart

152 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:collection/collection.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get_storage/get_storage.dart';
import 'package:matrix/matrix.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/common/config/environment.dart';
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart';
import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart';
import 'package:fluffychat/utils/client_manager.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/error_widget.dart';
import 'config/setting_keys.dart';
import 'utils/background_push.dart';
import 'widgets/fluffy_chat_app.dart';
void main() async {
Logs().i('Welcome to ${AppConfig.applicationName} <3');
// #Pangea
try {
await dotenv.load(fileName: ".env");
} catch (e) {
Logs().e('Failed to load .env file', e);
}
// await dotenv.load(fileName: ".env");
// await dotenv.load(fileName: Environment.fileName);
await Future.wait([
ErrorHandler.initialize(),
PLanguageStore.initialize(),
GoogleAnalytics.initialize(),
]);
///
/// PangeaLanguage must be initialized before the runApp
/// Then where ever you need language functions simply call PangeaLanguage pangeaLanguage = PangeaLanguage()
/// pangeaLanguage.getList or whatever function you need
///
await GetStorage.init();
// Pangea#
// Our background push shared isolate accesses flutter-internal things very early in the startup proccess
// To make sure that the parts of flutter needed are started up already, we need to ensure that the
// widget bindings are initialized already.
WidgetsFlutterBinding.ensureInitialized();
Logs().nativeColors = !PlatformInfos.isIOS;
final store = await SharedPreferences.getInstance();
final clients = await ClientManager.getClients(store: store);
// If the app starts in detached mode, we assume that it is in
// background fetch mode for processing push notifications. This is
// currently only supported on Android.
if (PlatformInfos.isAndroid &&
AppLifecycleState.detached == WidgetsBinding.instance.lifecycleState) {
// Do not send online presences when app is in background fetch mode.
for (final client in clients) {
client.backgroundSync = false;
client.syncPresence = PresenceType.offline;
}
// In the background fetch mode we do not want to waste ressources with
// starting the Flutter engine but process incoming push notifications.
BackgroundPush.clientOnly(clients.first);
// To start the flutter engine afterwards we add an custom observer.
WidgetsBinding.instance.addObserver(AppStarter(clients, store));
Logs().i(
'${AppConfig.applicationName} started in background-fetch mode. No GUI will be created unless the app is no longer detached.',
);
return;
}
// Started in foreground mode.
Logs().i(
'${AppConfig.applicationName} started in foreground mode. Rendering GUI...',
);
await startGui(clients, store);
}
/// Fetch the pincode for the applock and start the flutter engine.
Future<void> startGui(List<Client> clients, SharedPreferences store) async {
// Fetch the pin for the applock if existing for mobile applications.
String? pin;
if (PlatformInfos.isMobile) {
try {
pin =
await const FlutterSecureStorage().read(key: SettingKeys.appLockKey);
} catch (e, s) {
Logs().d('Unable to read PIN from Secure storage', e, s);
}
}
// Preload first client
final firstClient = clients.firstOrNull;
await firstClient?.roomsLoading;
await firstClient?.accountDataLoading;
ErrorWidget.builder = (details) => FluffyChatErrorWidget(details);
// #Pangea
// errors seems to happen a lot when users switch better production / staging
// while testing by accident. If the account is a production account but server is
// staging or vice versa, logout.
if (firstClient?.userID?.domain != null) {
final isStagingUser = firstClient!.userID!.domain!.contains("staging");
final isStagingServer = Environment.synapseURL.contains("staging");
if (isStagingServer != isStagingUser) {
await firstClient.logout();
}
}
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp, // Lock to portrait mode
]);
// Pangea#
runApp(FluffyChatApp(clients: clients, pincode: pin, store: store));
}
/// Watches the lifecycle changes to start the application when it
/// is no longer detached.
class AppStarter with WidgetsBindingObserver {
final List<Client> clients;
final SharedPreferences store;
bool guiStarted = false;
AppStarter(this.clients, this.store);
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (guiStarted) return;
if (state == AppLifecycleState.detached) return;
Logs().i(
'${AppConfig.applicationName} switches from the detached background-fetch mode to ${state.name} mode. Rendering GUI...',
);
// Switching to foreground mode needs to reenable send online sync presence.
for (final client in clients) {
client.backgroundSync = true;
client.syncPresence = PresenceType.online;
}
startGui(clients, store);
// We must make sure that the GUI is only started once.
guiStarted = true;
}
}