mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 03:42:13 +00:00
rename global variables into app state
This commit is contained in:
parent
715774bd7f
commit
e945e30991
13 changed files with 82 additions and 75 deletions
|
|
@ -32,7 +32,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
globalIsAppInBackground = false;
|
||||
AppState.isAppInBackground = false;
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
|
||||
unawaited(initAsync());
|
||||
|
|
@ -54,13 +54,13 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
|||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
if (wasPaused) {
|
||||
globalIsAppInBackground = false;
|
||||
AppState.isAppInBackground = false;
|
||||
twonlyDB.markUpdated();
|
||||
unawaited(apiService.connect());
|
||||
}
|
||||
} else if (state == AppLifecycleState.paused) {
|
||||
wasPaused = true;
|
||||
globalIsAppInBackground = true;
|
||||
AppState.isAppInBackground = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
|||
builder: (context, child) {
|
||||
return MaterialApp.router(
|
||||
routerConfig: routerProvider,
|
||||
scaffoldMessengerKey: globalRootScaffoldMessengerKey,
|
||||
scaffoldMessengerKey: AppGlobalKeys.scaffoldMessengerKey,
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
|
@ -17,6 +19,18 @@ class AppEnvironment {
|
|||
}
|
||||
}
|
||||
|
||||
class AppState {
|
||||
static bool isAppInBackground = true;
|
||||
static bool isInBackgroundTask = false;
|
||||
static bool allowErrorTrackingViaSentry = false;
|
||||
static bool gotMessageFromServer = false;
|
||||
}
|
||||
|
||||
class AppGlobalKeys {
|
||||
static final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
|
||||
GlobalKey<ScaffoldMessengerState>();
|
||||
}
|
||||
|
||||
late ApiService apiService;
|
||||
|
||||
// uses for background notification
|
||||
|
|
@ -26,20 +40,4 @@ late TwonlyDB twonlyDB;
|
|||
// which will update this global variable. The variable is set in the main.dart and after the user has registered in the register.view.dart
|
||||
late UserData gUser;
|
||||
|
||||
// The following global function can be called from anywhere to update
|
||||
// the UI when something changed. The callbacks will be set by
|
||||
// App widget.
|
||||
|
||||
// This callback called by the apiProvider
|
||||
void Function() globalCallbackAppIsOutdated = () {};
|
||||
void Function() globalCallbackNewDeviceRegistered = () {};
|
||||
|
||||
Map<String, VoidCallback> globalUserDataChangedCallBack = {};
|
||||
|
||||
bool globalIsAppInBackground = true;
|
||||
bool globalIsInBackgroundTask = false;
|
||||
bool globalAllowErrorTrackingViaSentry = false;
|
||||
bool globalGotMessageFromServer = false;
|
||||
|
||||
final GlobalKey<ScaffoldMessengerState> globalRootScaffoldMessengerKey =
|
||||
GlobalKey<ScaffoldMessengerState>();
|
||||
final userDataUpdateController = StreamController<void>.broadcast();
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ void main() async {
|
|||
gUser = user;
|
||||
|
||||
if (user.allowErrorTrackingViaSentry) {
|
||||
globalAllowErrorTrackingViaSentry = true;
|
||||
AppState.allowErrorTrackingViaSentry = true;
|
||||
await SentryFlutter.init(
|
||||
(options) => options
|
||||
..dsn =
|
||||
|
|
|
|||
|
|
@ -64,6 +64,12 @@ class ApiService {
|
|||
final _connectionStateController = StreamController<bool>.broadcast();
|
||||
Stream<bool> get onConnectionStateUpdated => _connectionStateController.stream;
|
||||
|
||||
final _appOutdatedController = StreamController<void>.broadcast();
|
||||
Stream<void> get onAppOutdated => _appOutdatedController.stream;
|
||||
|
||||
final _newDeviceRegisteredController = StreamController<void>.broadcast();
|
||||
Stream<void> get onNewDeviceRegistered => _newDeviceRegisteredController.stream;
|
||||
|
||||
bool appIsOutdated = false;
|
||||
bool isAuthenticated = false;
|
||||
|
||||
|
|
@ -97,12 +103,12 @@ class ApiService {
|
|||
await initFCMAfterAuthenticated();
|
||||
_connectionStateController.add(true);
|
||||
|
||||
if (globalIsInBackgroundTask) {
|
||||
if (AppState.isInBackgroundTask) {
|
||||
await retransmitRawBytes();
|
||||
await retransmitAllMessages();
|
||||
await reuploadMediaFiles();
|
||||
await tryDownloadAllMediaFiles();
|
||||
} else if (!globalIsAppInBackground) {
|
||||
} else if (!AppState.isAppInBackground) {
|
||||
unawaited(retransmitRawBytes());
|
||||
unawaited(retransmitAllMessages());
|
||||
unawaited(tryDownloadAllMediaFiles());
|
||||
|
|
@ -140,7 +146,7 @@ class ApiService {
|
|||
}
|
||||
|
||||
Future<void> startReconnectionTimer() async {
|
||||
if (globalIsInBackgroundTask) return;
|
||||
if (AppState.isInBackgroundTask) return;
|
||||
if (reconnectionTimer?.isActive ?? false) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -148,7 +154,7 @@ class ApiService {
|
|||
reconnectionTimer = Timer(Duration(seconds: _reconnectionDelay), () async {
|
||||
reconnectionTimer = null;
|
||||
// only try to reconnect in case the app is in the foreground
|
||||
if (!globalIsAppInBackground) {
|
||||
if (!AppState.isAppInBackground) {
|
||||
await connect();
|
||||
}
|
||||
});
|
||||
|
|
@ -353,14 +359,14 @@ class ApiService {
|
|||
Log.warn('Got error from server: ${res.error}');
|
||||
}
|
||||
if (res.error == ErrorCode.AppVersionOutdated) {
|
||||
globalCallbackAppIsOutdated();
|
||||
_appOutdatedController.add(null);
|
||||
Log.warn('App Version is OUTDATED.');
|
||||
appIsOutdated = true;
|
||||
await close(() {});
|
||||
return Result.error(ErrorCode.InternalError);
|
||||
}
|
||||
if (res.error == ErrorCode.NewDeviceRegistered) {
|
||||
globalCallbackNewDeviceRegistered();
|
||||
_newDeviceRegisteredController.add(null);
|
||||
Log.warn(
|
||||
'Device is disabled, as a newer device restore twonly Backup.',
|
||||
);
|
||||
|
|
@ -416,7 +422,7 @@ class ApiService {
|
|||
..userId = Int64(userId)
|
||||
..appVersion = (await PackageInfo.fromPlatform()).version
|
||||
..deviceId = Int64(user.deviceId)
|
||||
..inBackground = globalIsInBackgroundTask
|
||||
..inBackground = AppState.isInBackgroundTask
|
||||
..authToken = base64Decode(apiAuthToken);
|
||||
|
||||
final handshake = Handshake()..authenticate = authenticate;
|
||||
|
|
@ -427,7 +433,7 @@ class ApiService {
|
|||
if (result.isSuccess) {
|
||||
Log.info('websocket is authenticated');
|
||||
isAuthenticated = true;
|
||||
if (globalIsInBackgroundTask) {
|
||||
if (AppState.isInBackgroundTask) {
|
||||
await onAuthenticated();
|
||||
} else {
|
||||
unawaited(onAuthenticated());
|
||||
|
|
|
|||
|
|
@ -593,9 +593,9 @@ Future<void> _uploadUploadRequest(MediaFileService media) async {
|
|||
|
||||
final connectivityResult = await Connectivity().checkConnectivity();
|
||||
|
||||
if (globalIsInBackgroundTask ||
|
||||
if (AppState.isInBackgroundTask ||
|
||||
!connectivityResult.contains(ConnectivityResult.mobile) &&
|
||||
!connectivityResult.contains(ConnectivityResult.wifi)) {
|
||||
!connectivityResult.contains(ConnectivityResult.wifi)) {
|
||||
// no internet, directly put it into the background...
|
||||
await FileDownloader().enqueue(task);
|
||||
await media.setUploadState(UploadState.backgroundUploadTaskStarted);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
|
|||
..response = response;
|
||||
|
||||
await apiService.sendResponse(ClientToServer()..v0 = v0);
|
||||
globalGotMessageFromServer = true;
|
||||
AppState.gotMessageFromServer = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ Future<bool> initBackgroundExecution() async {
|
|||
|
||||
twonlyDB = TwonlyDB();
|
||||
apiService = ApiService();
|
||||
globalIsInBackgroundTask = true;
|
||||
AppState.isInBackgroundTask = true;
|
||||
|
||||
_isInitialized = true;
|
||||
return true;
|
||||
|
|
@ -124,7 +124,7 @@ Future<void> handlePeriodicTask({int lastExecutionInSecondsLimit = 120}) async {
|
|||
return;
|
||||
}
|
||||
|
||||
while (!globalGotMessageFromServer) {
|
||||
while (!AppState.gotMessageFromServer) {
|
||||
if (stopwatch.elapsed.inSeconds >= 15) {
|
||||
Log.info('No new message from the server after 15 seconds.');
|
||||
break;
|
||||
|
|
@ -132,7 +132,7 @@ Future<void> handlePeriodicTask({int lastExecutionInSecondsLimit = 120}) async {
|
|||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
if (globalGotMessageFromServer) {
|
||||
if (AppState.gotMessageFromServer) {
|
||||
Log.info('Received a server message from the server.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ Future<void> handleRemoteMessage(RemoteMessage message) async {
|
|||
if (!Platform.isAndroid) {
|
||||
Log.error('Got message in Dart while on iOS');
|
||||
}
|
||||
if (message.notification != null && globalIsAppInBackground) {
|
||||
if (message.notification != null && AppState.isAppInBackground) {
|
||||
Log.error(
|
||||
'Got notification but app is in background, so the SDK already have shown the message.',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class Log {
|
|||
StackTrace? stackTrace,
|
||||
]) {
|
||||
final message = filterLogMessage('$messageInput');
|
||||
if (globalAllowErrorTrackingViaSentry) {
|
||||
if (AppState.allowErrorTrackingViaSentry) {
|
||||
try {
|
||||
throw Exception(message);
|
||||
} catch (exception, stackTrace) {
|
||||
|
|
|
|||
|
|
@ -72,13 +72,8 @@ Future<UserData?> updateUserdata(
|
|||
gUser = updated;
|
||||
return updated;
|
||||
});
|
||||
try {
|
||||
for (final callBack in globalUserDataChangedCallBack.values) {
|
||||
callBack();
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
userDataUpdateController.add(null);
|
||||
|
||||
return userData;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -379,10 +379,10 @@ class MainCameraController {
|
|||
}
|
||||
await HapticFeedback.heavyImpact();
|
||||
if (verificationOk) {
|
||||
globalRootScaffoldMessengerKey.currentState?.showSnackBar(
|
||||
AppGlobalKeys.scaffoldMessengerKey.currentState?.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
globalRootScaffoldMessengerKey.currentContext?.lang
|
||||
AppGlobalKeys.scaffoldMessengerKey.currentContext?.lang
|
||||
.verifiedPublicKey(
|
||||
getContactDisplayName(contact),
|
||||
) ??
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
|
@ -16,29 +17,37 @@ class AppOutdated extends StatefulWidget {
|
|||
class _AppOutdatedState extends State<AppOutdated> {
|
||||
bool appIsOutdated = false;
|
||||
bool newDeviceRegistered = false;
|
||||
|
||||
late StreamSubscription<void> _subOutdated;
|
||||
late StreamSubscription<void> _subNewDevice;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
globalCallbackAppIsOutdated = () {};
|
||||
globalCallbackNewDeviceRegistered = () {};
|
||||
_subOutdated.cancel();
|
||||
_subNewDevice.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
globalCallbackAppIsOutdated = () async {
|
||||
await context.read<CustomChangeProvider>().updateConnectionState(false);
|
||||
setState(() {
|
||||
appIsOutdated = true;
|
||||
});
|
||||
};
|
||||
globalCallbackNewDeviceRegistered = () async {
|
||||
await context.read<CustomChangeProvider>().updateConnectionState(false);
|
||||
setState(() {
|
||||
newDeviceRegistered = true;
|
||||
});
|
||||
};
|
||||
super.initState();
|
||||
_subOutdated = apiService.onAppOutdated.listen((_) async {
|
||||
if (mounted) {
|
||||
await context.read<CustomChangeProvider>().updateConnectionState(false);
|
||||
setState(() {
|
||||
appIsOutdated = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_subNewDevice = apiService.onNewDeviceRegistered.listen((_) async {
|
||||
if (mounted) {
|
||||
await context.read<CustomChangeProvider>().updateConnectionState(false);
|
||||
setState(() {
|
||||
newDeviceRegistered = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ class AvatarIcon extends StatefulWidget {
|
|||
|
||||
class _AvatarIconState extends State<AvatarIcon> {
|
||||
List<Contact> _avatarContacts = [];
|
||||
String? _globalUserDataCallBackId;
|
||||
String? _avatarSvg;
|
||||
|
||||
StreamSubscription<List<Contact>>? groupStream;
|
||||
StreamSubscription<List<Contact>>? contactsStream;
|
||||
StreamSubscription<Contact?>? contactStream;
|
||||
StreamSubscription<void>? _userDataSub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -46,9 +46,7 @@ class _AvatarIconState extends State<AvatarIcon> {
|
|||
groupStream?.cancel();
|
||||
contactStream?.cancel();
|
||||
contactsStream?.cancel();
|
||||
if (_globalUserDataCallBackId != null) {
|
||||
globalUserDataChangedCallBack.remove(_globalUserDataCallBackId);
|
||||
}
|
||||
_userDataSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -95,16 +93,17 @@ class _AvatarIconState extends State<AvatarIcon> {
|
|||
setState(() {});
|
||||
});
|
||||
} else if (widget.myAvatar) {
|
||||
_globalUserDataCallBackId = 'avatar_${getRandomString(10)}';
|
||||
globalUserDataChangedCallBack[_globalUserDataCallBackId!] = () {
|
||||
setState(() {
|
||||
if (gUser.avatarSvg != null) {
|
||||
_avatarSvg = gUser.avatarSvg;
|
||||
} else {
|
||||
_avatarContacts = [];
|
||||
}
|
||||
});
|
||||
};
|
||||
_userDataSub = userDataUpdateController.stream.listen((_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (gUser.avatarSvg != null) {
|
||||
_avatarSvg = gUser.avatarSvg;
|
||||
} else {
|
||||
_avatarContacts = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (gUser.avatarSvg != null) {
|
||||
_avatarSvg = gUser.avatarSvg;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue