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.
		
		
		
		
		
			
		
			
				
	
	
		
			107 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			107 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Dart
		
	
import 'package:flutter/material.dart';
 | 
						|
 | 
						|
import 'package:collection/collection.dart';
 | 
						|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
 | 
						|
import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod;
 | 
						|
import 'package:matrix/matrix.dart';
 | 
						|
import 'package:shared_preferences/shared_preferences.dart';
 | 
						|
 | 
						|
import 'package:fluffychat/config/app_config.dart';
 | 
						|
import 'package:fluffychat/utils/client_manager.dart';
 | 
						|
import 'package:fluffychat/utils/platform_infos.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');
 | 
						|
 | 
						|
  // 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();
 | 
						|
 | 
						|
  await vod.init(wasmPath: './assets/assets/vodozemac/');
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
  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;
 | 
						|
  }
 | 
						|
}
 |