mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 02:12:13 +00:00
move user handling to a single user service
This commit is contained in:
parent
583368505d
commit
1e72883db0
31 changed files with 126 additions and 166 deletions
13
lib/app.dart
13
lib/app.dart
|
|
@ -11,7 +11,6 @@ import 'package:twonly/src/providers/purchases.provider.dart';
|
|||
import 'package:twonly/src/providers/routing.provider.dart';
|
||||
import 'package:twonly/src/providers/settings.provider.dart';
|
||||
import 'package:twonly/src/services/subscription.service.dart';
|
||||
import 'package:twonly/src/services/user.service.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/pow.dart';
|
||||
import 'package:twonly/src/visual/components/app_outdated.comp.dart';
|
||||
|
|
@ -45,10 +44,9 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
|||
|
||||
Future<void> initAsync() async {
|
||||
try {
|
||||
final user = await getUser();
|
||||
if (user != null && mounted) {
|
||||
if (userService.isUserCreated && mounted) {
|
||||
context.read<PurchasesProvider>().updatePlan(
|
||||
planFromString(user.subscriptionPlan),
|
||||
planFromString(userService.currentUser.subscriptionPlan),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -142,7 +140,6 @@ class AppMainWidget extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _AppMainWidgetState extends State<AppMainWidget> {
|
||||
bool _isUserCreated = false;
|
||||
bool _showOnboarding = true;
|
||||
bool _isLoaded = false;
|
||||
Object? _storageError;
|
||||
|
|
@ -159,9 +156,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
|||
|
||||
Future<void> initAsync() async {
|
||||
try {
|
||||
_isUserCreated = await isUserCreated();
|
||||
|
||||
if (_isUserCreated) {
|
||||
if (userService.isUserCreated) {
|
||||
if (_isTwonlyLocked) {
|
||||
// do not change in case twonly was already unlocked at some point
|
||||
_isTwonlyLocked = userService.currentUser.screenLockEnabled;
|
||||
|
|
@ -202,7 +197,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
|||
|
||||
late Widget child;
|
||||
|
||||
if (_isUserCreated) {
|
||||
if (userService.isUserCreated) {
|
||||
if (_isTwonlyLocked) {
|
||||
child = UnlockTwonlyView(
|
||||
callbackOnSuccess: () => setState(() {
|
||||
|
|
|
|||
|
|
@ -107,9 +107,8 @@ void main() async {
|
|||
);
|
||||
}
|
||||
|
||||
final settingsController = SettingsChangeProvider();
|
||||
final settingsController = SettingsChangeProvider()..loadSettings();
|
||||
|
||||
await settingsController.loadSettings();
|
||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
|
||||
await initFileDownloader();
|
||||
|
|
@ -144,13 +143,13 @@ Future<void> runMigrations() async {
|
|||
if (userService.currentUser.appVersion < 90) {
|
||||
// BUG: Requested media files for reupload where not reuploaded because the wrong state...
|
||||
await twonlyDB.mediaFilesDao.updateAllRetransmissionUploadingState();
|
||||
await updateUser((u) => u.appVersion = 90);
|
||||
await UserService.update((u) => u.appVersion = 90);
|
||||
}
|
||||
|
||||
if (userService.currentUser.appVersion < 91) {
|
||||
// BUG: Requested media files for reupload where not reuploaded because the wrong state...
|
||||
await makeMigrationToVersion91();
|
||||
await updateUser((u) => u.appVersion = 91);
|
||||
await UserService.update((u) => u.appVersion = 91);
|
||||
}
|
||||
|
||||
if (userService.currentUser.appVersion < 109) {
|
||||
|
|
@ -163,6 +162,6 @@ Future<void> runMigrations() async {
|
|||
);
|
||||
}
|
||||
}
|
||||
await updateUser((u) => u.appVersion = 109);
|
||||
await UserService.update((u) => u.appVersion = 109);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,9 +42,8 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|||
_planSub = apiService.onPlanUpdated.listen(updatePlan);
|
||||
_connSub = apiService.onConnectionStateUpdated.listen((_) async {
|
||||
try {
|
||||
final user = await getUser();
|
||||
if (user != null) {
|
||||
updatePlan(planFromString(user.subscriptionPlan));
|
||||
if (userService.isUserCreated) {
|
||||
updatePlan(planFromString(userService.currentUser.subscriptionPlan));
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
|
|
@ -95,8 +94,10 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|||
notifyListeners();
|
||||
|
||||
try {
|
||||
final user = await getUser();
|
||||
if (user != null && isPayingUser(planFromString(user.subscriptionPlan))) {
|
||||
if (userService.isUserCreated &&
|
||||
isPayingUser(
|
||||
planFromString(userService.currentUser.subscriptionPlan),
|
||||
)) {
|
||||
Log.info('Started IPA timer for verification.');
|
||||
globalForceIpaCheck = Timer(const Duration(seconds: 5), () async {
|
||||
Log.info(
|
||||
|
|
@ -185,7 +186,7 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|||
// an ok authenticated which is processed in the apiProvider...
|
||||
if (res.isSuccess) {
|
||||
if (Platform.isAndroid) {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.subscriptionPlanIdStore = purchaseDetails.productID;
|
||||
});
|
||||
}
|
||||
|
|
@ -216,11 +217,10 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|||
purchaseDetails.error == null) {
|
||||
globalForceIpaCheck?.cancel();
|
||||
|
||||
final user = await getUser();
|
||||
final currentPlan = userService.currentUser.subscriptionPlan;
|
||||
|
||||
if (user != null &&
|
||||
(user.subscriptionPlan != SubscriptionPlan.Family.name &&
|
||||
user.subscriptionPlan != SubscriptionPlan.Pro.name)) {
|
||||
if (currentPlan != SubscriptionPlan.Family.name &&
|
||||
currentPlan != SubscriptionPlan.Pro.name) {
|
||||
for (var i = 0; i < 100; i++) {
|
||||
if (apiService.isAuthenticated) {
|
||||
Log.info(
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/services/user.service.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
|
||||
class SettingsChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
||||
late ThemeMode _themeMode;
|
||||
|
||||
ThemeMode get themeMode => _themeMode;
|
||||
|
||||
Future<void> loadSettings() async {
|
||||
try {
|
||||
_themeMode = (await getUser())?.themeMode ?? ThemeMode.system;
|
||||
void loadSettings() {
|
||||
if (userService.isUserCreated) {
|
||||
_themeMode = userService.currentUser.themeMode;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
} else {
|
||||
_themeMode = ThemeMode.system;
|
||||
Log.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -27,6 +26,6 @@ class SettingsChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|||
|
||||
notifyListeners();
|
||||
|
||||
await updateUser((u) => u.themeMode = newThemeMode);
|
||||
await UserService.update((u) => u.themeMode = newThemeMode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ class ApiService {
|
|||
final ok = res.value as server.Response_Ok;
|
||||
if (ok.hasAuthenticated()) {
|
||||
final authenticated = ok.authenticated;
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.subscriptionPlan = authenticated.plan;
|
||||
});
|
||||
_planUpdateController.add(planFromString(authenticated.plan));
|
||||
|
|
@ -470,8 +470,7 @@ class ApiService {
|
|||
return;
|
||||
}
|
||||
|
||||
final userData = await getUser();
|
||||
if (userData == null) return;
|
||||
if (userService.isUserCreated) return;
|
||||
|
||||
if (await tryAuthenticateWithToken()) {
|
||||
return;
|
||||
|
|
@ -501,7 +500,7 @@ class ApiService {
|
|||
|
||||
final getAuthToken = Handshake_GetAuthToken()
|
||||
..response = signature
|
||||
..userId = Int64(userData.userId);
|
||||
..userId = Int64(userService.currentUser.userId);
|
||||
|
||||
final getauthtoken = Handshake()..getAuthToken = getAuthToken;
|
||||
|
||||
|
|
@ -791,7 +790,7 @@ class ApiService {
|
|||
Future<Response_PlanBallance?> loadPlanBalance({bool useCache = true}) async {
|
||||
final ballance = await getPlanBallance();
|
||||
if (ballance != null) {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.lastPlanBallance = ballance.writeToJson();
|
||||
});
|
||||
return ballance;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Future<void> enableTwonlySafe(String password) async {
|
|||
userService.currentUser.username,
|
||||
);
|
||||
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.twonlySafeBackup = TwonlySafeBackup(
|
||||
encryptionKey: encryptionKey,
|
||||
backupId: backupId,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
key: SecureStorageKeys.signalSignedPreKey,
|
||||
);
|
||||
|
||||
final userBackup = await getUser();
|
||||
final userBackup = await UserService.getUser();
|
||||
if (userBackup == null) return;
|
||||
// FILTER settings which should not be in the backup
|
||||
userBackup
|
||||
|
|
@ -183,7 +183,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
if (encryptedBackupBytes.length >
|
||||
userService.currentUser.backupServer!.maxBackupBytes) {
|
||||
Log.error('Backup is to big for the alternative backup server.');
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.twonlySafeBackup!.backupUploadState = LastBackupUploadState.failed;
|
||||
});
|
||||
return;
|
||||
|
|
@ -203,7 +203,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
);
|
||||
if (await FileDownloader().enqueue(task)) {
|
||||
Log.info('Starting upload from twonly Backup.');
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.twonlySafeBackup!.backupUploadState = LastBackupUploadState.pending;
|
||||
user.twonlySafeBackup!.lastBackupDone = clock.now();
|
||||
user.twonlySafeBackup!.lastBackupSize = encryptedBackupBytes.length;
|
||||
|
|
@ -216,7 +216,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
Future<void> handleBackupStatusUpdate(TaskStatusUpdate update) async {
|
||||
if (update.status == TaskStatus.failed ||
|
||||
update.status == TaskStatus.canceled) {
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
if (user.twonlySafeBackup != null) {
|
||||
user.twonlySafeBackup!.backupUploadState = LastBackupUploadState.failed;
|
||||
}
|
||||
|
|
@ -225,7 +225,7 @@ Future<void> handleBackupStatusUpdate(TaskStatusUpdate update) async {
|
|||
Log.info(
|
||||
'twonly Backup uploaded with status code ${update.responseStatusCode}',
|
||||
);
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
if (user.twonlySafeBackup != null) {
|
||||
user.twonlySafeBackup!.backupUploadState =
|
||||
LastBackupUploadState.success;
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ Future<void> handleBackupData(
|
|||
key: SecureStorageKeys.userData,
|
||||
value: secureStorage[SecureStorageKeys.userData] as String,
|
||||
);
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.deviceId += 1;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Future<void> syncFlameCounters({String? forceForGroup}) async {
|
|||
);
|
||||
|
||||
if (userService.currentUser.myBestFriendGroupId != bestFriend.groupId) {
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.myBestFriendGroupId = bestFriend.groupId;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Future<void> checkForTokenUpdates() async {
|
|||
if (storedToken == null || fcmToken != storedToken) {
|
||||
Log.info('Got new FCM TOKEN.');
|
||||
await storage.write(key: SecureStorageKeys.googleFcm, value: fcmToken);
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.updateFCMToken = true;
|
||||
});
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ Future<void> checkForTokenUpdates() async {
|
|||
key: SecureStorageKeys.googleFcm,
|
||||
value: fcmToken,
|
||||
);
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.updateFCMToken = true;
|
||||
});
|
||||
})
|
||||
|
|
@ -81,7 +81,7 @@ Future<void> initFCMAfterAuthenticated({bool force = false}) async {
|
|||
final res = await apiService.updateFCMToken(storedToken);
|
||||
if (res.isSuccess) {
|
||||
Log.info('Uploaded new FCM token!');
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.updateFCMToken = false;
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ Future<void> signalHandleNewServerConnection() async {
|
|||
Log.error('could not generate a new signed pre key!');
|
||||
return;
|
||||
}
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.signalLastSignedPreKeyUpdated = clock.now();
|
||||
});
|
||||
final res = await apiService.updateSignedPreKey(
|
||||
|
|
@ -49,7 +49,7 @@ Future<void> signalHandleNewServerConnection() async {
|
|||
);
|
||||
if (res.isError) {
|
||||
Log.error('could not update the signed pre key: ${res.error}');
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.signalLastSignedPreKeyUpdated = null;
|
||||
});
|
||||
} else {
|
||||
|
|
@ -59,13 +59,9 @@ Future<void> signalHandleNewServerConnection() async {
|
|||
|
||||
Future<List<PreKeyRecord>> signalGetPreKeys() async {
|
||||
return lockingSignalProtocol.protect(() async {
|
||||
final user = await getUser();
|
||||
if (user == null) return [];
|
||||
|
||||
final start = user.currentPreKeyIndexStart;
|
||||
await updateUser((user) {
|
||||
user.currentPreKeyIndexStart =
|
||||
(user.currentPreKeyIndexStart + 200) % maxValue;
|
||||
final start = userService.currentUser.currentPreKeyIndexStart;
|
||||
await UserService.update((u) {
|
||||
u.currentPreKeyIndexStart = (u.currentPreKeyIndexStart + 200) % maxValue;
|
||||
});
|
||||
final preKeys = generatePreKeys(start, 200);
|
||||
final signalStore = await getSignalStore();
|
||||
|
|
@ -138,14 +134,14 @@ Future<void> createIfNotExistsSignalIdentity() async {
|
|||
Future<SignedPreKeyRecord?> _getNewSignalSignedPreKey() async {
|
||||
return lockingSignalProtocol.protect(() async {
|
||||
var identityKeyPair = await getSignalIdentityKeyPair();
|
||||
final user = await getUser();
|
||||
final signalStore = await getSignalStore();
|
||||
if (identityKeyPair == null || signalStore == null || user == null) {
|
||||
if (identityKeyPair == null || signalStore == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final signedPreKeyId = user.currentSignedPreKeyIndexStart;
|
||||
await updateUser((user) {
|
||||
final signedPreKeyId =
|
||||
userService.currentUser.currentSignedPreKeyIndexStart;
|
||||
await UserService.update((user) {
|
||||
user.currentSignedPreKeyIndexStart += 1;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/secure_storage.keys.dart';
|
||||
import 'package:twonly/src/model/json/userdata.model.dart';
|
||||
import 'package:twonly/src/providers/purchases.provider.dart';
|
||||
import 'package:twonly/src/services/subscription.service.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/secure_storage.dart';
|
||||
|
||||
class UserService {
|
||||
late UserData currentUser;
|
||||
bool isUserCreated = false;
|
||||
static final Mutex _updateProtection = Mutex();
|
||||
|
||||
final _userDataUpdateController = StreamController<void>.broadcast();
|
||||
Stream<void> get onUserUpdated => _userDataUpdateController.stream;
|
||||
|
|
@ -23,79 +20,53 @@ class UserService {
|
|||
final user = await getUser();
|
||||
if (user == null) return false;
|
||||
userService.currentUser = user;
|
||||
isUserCreated = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Future<UserData?> getUser() async {
|
||||
try {
|
||||
final userDataJson = await SecureStorage.instance.read(
|
||||
key: SecureStorageKeys.userData,
|
||||
);
|
||||
if (userDataJson == null) {
|
||||
return null;
|
||||
}
|
||||
return UserData.fromJson(
|
||||
jsonDecode(userDataJson) as Map<String, dynamic>,
|
||||
);
|
||||
} catch (e) {
|
||||
Log.error('could not load user: $e');
|
||||
rethrow; // Rethrow instead of returning null to distinguish error from missing user
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> update(
|
||||
void Function(UserData userData) updateUser,
|
||||
) async {
|
||||
await _updateProtection.protect(() async {
|
||||
try {
|
||||
final user = await getUser();
|
||||
if (user == null) return;
|
||||
if (user.defaultShowTime == 999999) {
|
||||
// This was the old version for infinity -> change it to null
|
||||
user.defaultShowTime = null;
|
||||
}
|
||||
updateUser(user);
|
||||
await SecureStorage.instance.write(
|
||||
key: SecureStorageKeys.userData,
|
||||
value: jsonEncode(user),
|
||||
);
|
||||
userService.currentUser = user;
|
||||
} catch (e) {
|
||||
Log.error('Could not update the user: $e');
|
||||
}
|
||||
});
|
||||
|
||||
userService.triggerUserUpdate();
|
||||
}
|
||||
|
||||
void triggerUserUpdate() {
|
||||
_userDataUpdateController.add(null);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_userDataUpdateController.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> isUserCreated() async {
|
||||
final user = await getUser();
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
userService.currentUser = user;
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<UserData?> getUser() async {
|
||||
try {
|
||||
final userDataJson = await SecureStorage.instance.read(
|
||||
key: SecureStorageKeys.userData,
|
||||
);
|
||||
if (userDataJson == null) {
|
||||
return null;
|
||||
}
|
||||
return UserData.fromJson(jsonDecode(userDataJson) as Map<String, dynamic>);
|
||||
} catch (e) {
|
||||
Log.error('could not load user: $e');
|
||||
rethrow; // Rethrow instead of returning null to distinguish error from missing user
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateUsersPlan(
|
||||
BuildContext context,
|
||||
SubscriptionPlan plan,
|
||||
) async {
|
||||
context.read<PurchasesProvider>().plan = plan;
|
||||
|
||||
await updateUser((user) {
|
||||
user.subscriptionPlan = plan.name;
|
||||
});
|
||||
|
||||
if (!context.mounted) return;
|
||||
context.read<PurchasesProvider>().updatePlan(plan);
|
||||
}
|
||||
|
||||
Mutex updateProtection = Mutex();
|
||||
|
||||
Future<void> updateUser(
|
||||
void Function(UserData userData) updateUser,
|
||||
) async {
|
||||
await updateProtection.protect(() async {
|
||||
try {
|
||||
final user = await getUser();
|
||||
if (user == null) return;
|
||||
if (user.defaultShowTime == 999999) {
|
||||
// This was the old version for infinity -> change it to null
|
||||
user.defaultShowTime = null;
|
||||
}
|
||||
updateUser(user);
|
||||
await const FlutterSecureStorage().write(
|
||||
key: SecureStorageKeys.userData,
|
||||
value: jsonEncode(user),
|
||||
);
|
||||
userService.currentUser = user;
|
||||
} catch (e) {
|
||||
Log.error('Could not update the user: $e');
|
||||
}
|
||||
});
|
||||
|
||||
userService.triggerUserUpdate();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class UserDiscoveryService {
|
|||
userId: userService.currentUser.userId,
|
||||
publicKey: await getUserPublicKey(),
|
||||
);
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u
|
||||
..isUserDiscoveryEnabled = true
|
||||
..minimumRequiredImagesExchanged = minimumRequiredImagesExchanged,
|
||||
|
|
@ -168,7 +168,7 @@ class UserDiscoveryService {
|
|||
}
|
||||
|
||||
static Future<void> disable() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.isUserDiscoveryEnabled = false;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,13 +100,13 @@ Future<void> handleUserStudyUpload() async {
|
|||
headers: {'Content-Type': 'application/json'},
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.lastUserStudyDataUpload = DateTime.now();
|
||||
});
|
||||
}
|
||||
if (response.statusCode == 404) {
|
||||
// Token is unknown to the server...
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u
|
||||
..lastUserStudyDataUpload = null
|
||||
..userStudyParticipantsToken = null;
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
|||
|
||||
if (!_hasAudioPermission &&
|
||||
!userService.currentUser.requestedAudioPermission) {
|
||||
await updateUser((u) => u.requestedAudioPermission = true);
|
||||
await UserService.update((u) => u.requestedAudioPermission = true);
|
||||
await requestMicrophonePermission();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
if (!mounted) return;
|
||||
setState(() {});
|
||||
if (storeAsDefault) {
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.defaultShowTime = maxShowTime;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
if (!userService.currentUser.hideChangeLog &&
|
||||
userService.currentUser.lastChangeLogHash.toString() !=
|
||||
changeLogHash.toString()) {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.lastChangeLogHash = changeLogHash;
|
||||
});
|
||||
if (!mounted) return;
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class _RegisterViewState extends State<RegisterView> {
|
|||
value: jsonEncode(userData),
|
||||
);
|
||||
|
||||
userService.currentUser = userData;
|
||||
await userService.tryInit();
|
||||
|
||||
await apiService.authenticate();
|
||||
widget.callbackOnSuccess();
|
||||
|
|
|
|||
|
|
@ -73,19 +73,19 @@ class _AppearanceViewState extends State<AppearanceView> {
|
|||
}
|
||||
|
||||
Future<void> toggleShowFeedbackIcon() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.showFeedbackShortcut = !u.showFeedbackShortcut;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> toggleStartWithCameraOpen() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.startWithCameraOpen = !u.startWithCameraOpen;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> toggleShowImagePreviewWhenSending() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.showShowImagePreviewWhenSending = !u.showShowImagePreviewWhenSending;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class _BackupServerViewState extends State<BackupServerView> {
|
|||
retentionDays: data['retentionDays']! as int,
|
||||
maxBackupBytes: data['maxBackupBytes']! as int,
|
||||
);
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.backupServer = backupServer;
|
||||
});
|
||||
if (mounted) Navigator.pop(context, backupServer);
|
||||
|
|
@ -166,7 +166,7 @@ class _BackupServerViewState extends State<BackupServerView> {
|
|||
Center(
|
||||
child: OutlinedButton(
|
||||
onPressed: () async {
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.backupServer = null;
|
||||
});
|
||||
if (context.mounted) Navigator.pop(context);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class _ChatReactionSelectionView extends State<ChatReactionSelectionView> {
|
|||
} else {
|
||||
if (_selectedEmojis.length < 12) {
|
||||
_selectedEmojis.add(emoji);
|
||||
await updateUser((user) {
|
||||
await UserService.update((user) {
|
||||
user.preSelectedEmojies = _selectedEmojis;
|
||||
});
|
||||
} else {
|
||||
|
|
@ -90,7 +90,7 @@ class _ChatReactionSelectionView extends State<ChatReactionSelectionView> {
|
|||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: FloatingActionButton(
|
||||
foregroundColor: Colors.white,
|
||||
onPressed: () => updateUser(
|
||||
onPressed: () => UserService.update(
|
||||
(u) => u.preSelectedEmojies = EmojiAnimationComp
|
||||
.animatedIcons
|
||||
.keys
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ class _DataAndStorageViewState extends State<DataAndStorageView> {
|
|||
}
|
||||
|
||||
Future<void> toggleStoreInGallery() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.storeMediaFilesInGallery = !u.storeMediaFilesInGallery;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> toggleAutoStoreMediaFiles() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.autoStoreAllSendUnlimitedMediaFiles =
|
||||
!u.autoStoreAllSendUnlimitedMediaFiles;
|
||||
});
|
||||
|
|
@ -227,7 +227,7 @@ class _AutoDownloadOptionsDialogState extends State<AutoDownloadOptionsDialog> {
|
|||
|
||||
// Call the onUpdate callback to notify the parent widget
|
||||
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.autoDownloadOptions = autoDownloadOptions;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
|
|||
}
|
||||
|
||||
Future<void> toggleDeveloperSettings() async {
|
||||
await updateUser((u) => u.isDeveloper = !u.isDeveloper);
|
||||
await UserService.update((u) => u.isDeveloper = !u.isDeveloper);
|
||||
}
|
||||
|
||||
Future<void> toggleVideoStabilization() async {
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u.videoStabilizationEnabled = !u.videoStabilizationEnabled,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,8 +114,9 @@ class _ChangeLogViewState extends State<ChangeLogView> {
|
|||
Text(context.lang.openChangeLog),
|
||||
Switch(
|
||||
value: !userService.currentUser.hideChangeLog,
|
||||
onChanged: (_) =>
|
||||
updateUser((u) => u.hideChangeLog = !u.hideChangeLog),
|
||||
onChanged: (_) => UserService.update(
|
||||
(u) => u.hideChangeLog = !u.hideChangeLog,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class HelpView extends StatefulWidget {
|
|||
|
||||
class _HelpViewState extends State<HelpView> {
|
||||
Future<void> toggleAllowErrorTrackingViaSentry() async {
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u.allowErrorTrackingViaSentry = !u.allowErrorTrackingViaSentry,
|
||||
);
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ class _HelpViewState extends State<HelpView> {
|
|||
'Do you want to enable the developer settings?',
|
||||
);
|
||||
if (okay) {
|
||||
await updateUser((u) => u.isDeveloper = true);
|
||||
await UserService.update((u) => u.isDeveloper = true);
|
||||
}
|
||||
},
|
||||
title: const Text(
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ class _PrivacyViewState extends State<PrivacyView> {
|
|||
: context.lang.settingsScreenLockAuthMessageEnable,
|
||||
);
|
||||
if (!isAuth) return;
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.screenLockEnabled = !u.screenLockEnabled;
|
||||
});
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future<void> toggleTypingIndicators() async {
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u.typingIndicators = !u.typingIndicators;
|
||||
});
|
||||
setState(() {});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class _UserDiscoverySettingsViewState extends State<UserDiscoverySettingsView> {
|
|||
userService.currentUser.userDiscoveryThreshold !=
|
||||
_userDiscoveryThreshold;
|
||||
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
u
|
||||
..minimumRequiredImagesExchanged = _minimumRequiredImagesExchanged
|
||||
..userDiscoveryThreshold = _userDiscoveryThreshold;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class _ModifyAvatarViewState extends State<ModifyAvatarView> {
|
|||
}
|
||||
|
||||
Future<void> updateUserAvatar(String json, String svg) async {
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u
|
||||
..avatarJson = json
|
||||
..avatarSvg = svg
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class _ProfileViewState extends State<ProfileView> {
|
|||
}
|
||||
|
||||
Future<void> updateUserDisplayName(String displayName) async {
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u
|
||||
..displayName = displayName
|
||||
..avatarCounter = u.avatarCounter + 1,
|
||||
|
|
@ -93,7 +93,7 @@ class _ProfileViewState extends State<ProfileView> {
|
|||
await removeTwonlySafeFromServer();
|
||||
unawaited(performTwonlySafeBackup(force: true));
|
||||
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u
|
||||
..username = username
|
||||
..avatarCounter = u.avatarCounter + 1,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class _UserStudyQuestionnaireViewState
|
|||
Future<void> _submitData() async {
|
||||
await KeyValueStore.put(userStudySurveyKey, _responses);
|
||||
|
||||
await updateUser((u) {
|
||||
await UserService.update((u) {
|
||||
// generate a random participants id to identify data send later while keeping the user anonym
|
||||
u
|
||||
..userStudyParticipantsToken = getRandomString(25)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class _UserStudyWelcomeViewState extends State<UserStudyWelcomeView> {
|
|||
Center(
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
await updateUser(
|
||||
await UserService.update(
|
||||
(u) => u.askedForUserStudyPermission = true,
|
||||
);
|
||||
if (context.mounted) context.pop();
|
||||
|
|
|
|||
Loading…
Reference in a new issue