@ -5,6 +5,7 @@ import 'package:flutter_app_lock/flutter_app_lock.dart';
import ' package:flutter_secure_storage/flutter_secure_storage.dart ' ;
import ' package:matrix/matrix.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 ' ;
@ -13,7 +14,7 @@ import 'widgets/fluffy_chat_app.dart';
import ' widgets/lock_screen.dart ' ;
void main ( ) async {
Logs ( ) . i ( ' Welcome to FluffyChat ' ) ;
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
@ -28,9 +29,34 @@ void main() async {
await firstClient ? . roomsLoading ;
await firstClient ? . accountDataLoading ;
/ / 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 ) {
/ / 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 ) ) ;
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 ) ;
}
/ / / Fetch the pincode for the applock and start the flutter engine .
Future < void > startGui ( List < Client > clients ) async {
/ / Fetch the pin for the applock if existing for mobile applications .
String ? pin ;
if ( PlatformInfos . isMobile ) {
BackgroundPush . clientOnly ( clients . first ) ;
try {
pin =
await const FlutterSecureStorage ( ) . read ( key: SettingKeys . appLockKey ) ;
@ -39,6 +65,9 @@ void main() async {
}
}
/ / Start rendering the Flutter app and wrap it in an Applock .
/ / We do this only for mobile applications as we saw routing
/ / problems on other platforms if we wrap it always .
runApp (
PlatformInfos . isMobile
? AppLock (
@ -49,3 +78,25 @@ void main() async {
: FluffyChatApp ( clients: clients ) ,
) ;
}
/ / / Watches the lifecycle changes to start the application when it
/ / / is no longer detached .
class AppStarter with WidgetsBindingObserver {
final List < Client > clients ;
bool guiStarted = false ;
AppStarter ( this . clients ) ;
@ 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... ' ,
) ;
startGui ( clients ) ;
/ / We must make sure that the GUI is only started once .
guiStarted = true ;
}
}