mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-07-18 02:24:07 +00:00
improve error logging
This commit is contained in:
parent
4c42d55afd
commit
e8829ed2c9
20 changed files with 142 additions and 49 deletions
|
|
@ -36,7 +36,7 @@ abstract class VideoCompressionChannel {
|
||||||
});
|
});
|
||||||
return outputPath;
|
return outputPath;
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
Log.error('Failed to compress video: $e');
|
Log.warn('Failed to compress video: $e');
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
_currentProgressCallback = null;
|
_currentProgressCallback = null;
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,15 @@ class ReactionsDao extends DatabaseAccessor<TwonlyDB> with _$ReactionsDaoMixin {
|
||||||
.getMessageById(messageId)
|
.getMessageById(messageId)
|
||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
Log.error('updateReaction: Message $messageId not found!');
|
Log.warn('updateReaction: Message $messageId not found!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg.groupId != groupId) {
|
if (msg.groupId != groupId) {
|
||||||
Log.error('updateReaction: Message groupId ${msg.groupId} != $groupId');
|
Log.warn('updateReaction: Message groupId ${msg.groupId} != $groupId');
|
||||||
|
Log.error(
|
||||||
|
'updateReaction: Message groupId mismatch',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,8 +201,8 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
||||||
);
|
);
|
||||||
final updatedReceipt = await getReceiptById(newReceiptId);
|
final updatedReceipt = await getReceiptById(newReceiptId);
|
||||||
if (updatedReceipt == null) {
|
if (updatedReceipt == null) {
|
||||||
Log.error(
|
Log.warn(
|
||||||
'Tried to change the receipt ID, but could not get the updated receipt...',
|
'[$oldReceiptId] Tried to change the receipt ID to $newReceiptId, but could not get the updated receipt...',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return updatedReceipt;
|
return updatedReceipt;
|
||||||
|
|
@ -253,6 +253,9 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
||||||
Future<void> gotReceipt(String receiptId) async {
|
Future<void> gotReceipt(String receiptId) async {
|
||||||
await into(
|
await into(
|
||||||
receivedReceipts,
|
receivedReceipts,
|
||||||
).insert(ReceivedReceiptsCompanion(receiptId: Value(receiptId)));
|
).insert(
|
||||||
|
ReceivedReceiptsCompanion(receiptId: Value(receiptId)),
|
||||||
|
mode: InsertMode.insertOrIgnore,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -684,11 +684,11 @@ class ApiService {
|
||||||
final req = createClientToServerFromHandshake(handshake);
|
final req = createClientToServerFromHandshake(handshake);
|
||||||
final result = await sendRequestSync(req, authenticated: false);
|
final result = await sendRequestSync(req, authenticated: false);
|
||||||
if (result.isError) {
|
if (result.isError) {
|
||||||
Log.error('could not request proof of work params', result);
|
Log.error('could not request proof of work params', error: result);
|
||||||
if (result.error == ErrorCode.RegistrationDisabled) {
|
if (result.error == ErrorCode.RegistrationDisabled) {
|
||||||
return (null, true);
|
return (null, true);
|
||||||
}
|
}
|
||||||
Log.error('could not request proof of work params', result);
|
Log.error('could not request proof of work params', error: result);
|
||||||
return (null, false);
|
return (null, false);
|
||||||
}
|
}
|
||||||
return (result.value.proofOfWork as Response_ProofOfWork, false);
|
return (result.value.proofOfWork as Response_ProofOfWork, false);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ Future<void> handleErrorMessage(
|
||||||
String receiptId, {
|
String receiptId, {
|
||||||
String? groupId,
|
String? groupId,
|
||||||
}) async {
|
}) async {
|
||||||
Log.error('[$receiptId] Got error from $fromUserId: $error');
|
Log.warn('[$receiptId] Got error from $fromUserId: $error');
|
||||||
|
|
||||||
switch (error.type) {
|
switch (error.type) {
|
||||||
case EncryptedContent_ErrorMessages_Type
|
case EncryptedContent_ErrorMessages_Type
|
||||||
|
|
@ -38,14 +38,14 @@ Future<void> handleErrorMessage(
|
||||||
break; // The other user initiated a new signal session, so ignore the error in this case, as the new session works...
|
break; // The other user initiated a new signal session, so ignore the error in this case, as the new session works...
|
||||||
case EncryptedContent_ErrorMessages_Type.GROUP_NOT_FOUND_OR_NOT_A_MEMBER:
|
case EncryptedContent_ErrorMessages_Type.GROUP_NOT_FOUND_OR_NOT_A_MEMBER:
|
||||||
if (groupId == null) {
|
if (groupId == null) {
|
||||||
Log.error(
|
Log.warn(
|
||||||
'[$receiptId] GROUP_NOT_FOUND_OR_NOT_A_MEMBER error received, but groupId is null.',
|
'[$receiptId] GROUP_NOT_FOUND_OR_NOT_A_MEMBER error received, but groupId is null.',
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final group = await twonlyDB.groupsDao.getGroup(groupId);
|
final group = await twonlyDB.groupsDao.getGroup(groupId);
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
Log.error(
|
Log.warn(
|
||||||
'[$receiptId] GROUP_NOT_FOUND_OR_NOT_A_MEMBER error received, but group $groupId is not found in database.',
|
'[$receiptId] GROUP_NOT_FOUND_OR_NOT_A_MEMBER error received, but group $groupId is not found in database.',
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,12 @@ Future<void> handleDownloadStatusUpdate(TaskStatusUpdate update) async {
|
||||||
failed = false;
|
failed = false;
|
||||||
} else {
|
} else {
|
||||||
failed = true;
|
failed = true;
|
||||||
|
Log.warn(
|
||||||
|
'[$mediaId] Got invalid response status code: ${update.responseStatusCode}',
|
||||||
|
);
|
||||||
Log.error(
|
Log.error(
|
||||||
'Got invalid response status code: ${update.responseStatusCode}',
|
'Got invalid response status code: ${update.responseStatusCode}',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -227,7 +231,7 @@ Future<void> startDownloadMedia(MediaFile media, bool force) async {
|
||||||
try {
|
try {
|
||||||
await downloadFileFast(media, apiUrl, mediaService.encryptedPath);
|
await downloadFileFast(media, apiUrl, mediaService.encryptedPath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('Fast download failed: $e');
|
Log.warn('Fast download failed: $e');
|
||||||
await FileDownloader().enqueue(task);
|
await FileDownloader().enqueue(task);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -251,9 +255,13 @@ Future<void> downloadFileFast(
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (response.statusCode == 404 || response.statusCode == 403) {
|
if (response.statusCode == 404 || response.statusCode == 403) {
|
||||||
Log.error(
|
Log.warn(
|
||||||
'Got ${response.statusCode} from server for media ID ${media.mediaId}. Requesting upload again',
|
'Got ${response.statusCode} from server for media ID ${media.mediaId}. Requesting upload again',
|
||||||
);
|
);
|
||||||
|
Log.error(
|
||||||
|
'Got ${response.statusCode} from server for media ID.',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
|
);
|
||||||
// Message was deleted from the server. Requesting it again from the sender to upload it again...
|
// Message was deleted from the server. Requesting it again from the sender to upload it again...
|
||||||
await requestMediaReupload(media.mediaId);
|
await requestMediaReupload(media.mediaId);
|
||||||
return;
|
return;
|
||||||
|
|
@ -293,7 +301,7 @@ Future<void> handleEncryptedFile(String mediaId) async {
|
||||||
action: () async {
|
action: () async {
|
||||||
final mediaService = await MediaFileService.fromMediaId(mediaId);
|
final mediaService = await MediaFileService.fromMediaId(mediaId);
|
||||||
if (mediaService == null) {
|
if (mediaService == null) {
|
||||||
Log.error('Media file not found in database.');
|
Log.warn('[$mediaId] Media file not found in database.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,13 @@ Future<void> handleUploadStatusUpdate(TaskStatusUpdate update) async {
|
||||||
await markUploadAsSuccessful(media);
|
await markUploadAsSuccessful(media);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.error(
|
Log.warn(
|
||||||
'Got HTTP error ${update.responseStatusCode} for $mediaId',
|
'Got HTTP error ${update.responseStatusCode} for $mediaId',
|
||||||
);
|
);
|
||||||
|
Log.error(
|
||||||
|
'Got HTTP error ${update.responseStatusCode} for media.',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update.status == TaskStatus.notFound) {
|
if (update.status == TaskStatus.notFound) {
|
||||||
|
|
@ -118,9 +122,13 @@ Future<void> handleUploadStatusUpdate(TaskStatusUpdate update) async {
|
||||||
|
|
||||||
if (update.status == TaskStatus.failed ||
|
if (update.status == TaskStatus.failed ||
|
||||||
update.status == TaskStatus.canceled) {
|
update.status == TaskStatus.canceled) {
|
||||||
Log.error(
|
Log.warn(
|
||||||
'Background upload failed for $mediaId with status ${update.status} and ${update.responseStatusCode}. ',
|
'Background upload failed for $mediaId with status ${update.status} and ${update.responseStatusCode}. ',
|
||||||
);
|
);
|
||||||
|
Log.error(
|
||||||
|
'Background upload failed with status ${update.status} and ${update.responseStatusCode}.',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
|
);
|
||||||
final mediaService = MediaFileService(media);
|
final mediaService = MediaFileService(media);
|
||||||
|
|
||||||
// in case the media file is already uploaded to not reqtry
|
// in case the media file is already uploaded to not reqtry
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,11 @@ Future<void> _handleClient2ClientMessage(
|
||||||
await twonlyDB.receiptsDao.gotReceipt(receiptId);
|
await twonlyDB.receiptsDao.gotReceipt(receiptId);
|
||||||
Log.info('[$receiptId] Finished processing');
|
Log.info('[$receiptId] Finished processing');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('[$receiptId] Error marking message as received: $e');
|
Log.warn('[$receiptId] Error marking message as received: $e');
|
||||||
|
Log.error(
|
||||||
|
'Error marking message as received: $e',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,7 +430,14 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!content.hasGroupId()) {
|
if (!content.hasGroupId()) {
|
||||||
Log.error('[$receiptId] Messages should have a groupId $fromUserId.');
|
final type = _getEncryptedContentType(content);
|
||||||
|
Log.warn(
|
||||||
|
'[$receiptId] Messages should have a groupId $fromUserId. Type: $type',
|
||||||
|
);
|
||||||
|
Log.error(
|
||||||
|
'Messages should have a groupId. Type: $type',
|
||||||
|
onlyIfSentryEnabled: true,
|
||||||
|
);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,7 +464,7 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
||||||
);
|
);
|
||||||
if (contact == null || !contact.accepted || contact.deletedByUser) {
|
if (contact == null || !contact.accepted || contact.deletedByUser) {
|
||||||
await handleNewContactRequest(fromUserId);
|
await handleNewContactRequest(fromUserId);
|
||||||
Log.error(
|
Log.warn(
|
||||||
'[$receiptId] User tries to send message to direct chat while the user does not exist!',
|
'[$receiptId] User tries to send message to direct chat while the user does not exist!',
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -478,7 +489,7 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (content.hasGroupJoin()) {
|
if (content.hasGroupJoin()) {
|
||||||
Log.error(
|
Log.warn(
|
||||||
'[$receiptId] Got group join message, but group does not exist yet, retry later. As probably the GroupCreate was not yet received.',
|
'[$receiptId] Got group join message, but group does not exist yet, retry later. As probably the GroupCreate was not yet received.',
|
||||||
);
|
);
|
||||||
// In case the group join was received before the GroupCreate the sender should send it later again.
|
// In case the group join was received before the GroupCreate the sender should send it later again.
|
||||||
|
|
@ -489,7 +500,7 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.error(
|
Log.warn(
|
||||||
'[$receiptId] User $fromUserId tried to access group ${content.groupId}. Sending GROUP_NOT_FOUND_OR_NOT_A_MEMBER error.',
|
'[$receiptId] User $fromUserId tried to access group ${content.groupId}. Sending GROUP_NOT_FOUND_OR_NOT_A_MEMBER error.',
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -598,3 +609,26 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
||||||
|
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _getEncryptedContentType(EncryptedContent content) {
|
||||||
|
if (content.hasMessageUpdate()) return 'messageUpdate';
|
||||||
|
if (content.hasMedia()) return 'media';
|
||||||
|
if (content.hasMediaUpdate()) return 'mediaUpdate';
|
||||||
|
if (content.hasContactUpdate()) return 'contactUpdate';
|
||||||
|
if (content.hasContactRequest()) return 'contactRequest';
|
||||||
|
if (content.hasFlameSync()) return 'flameSync';
|
||||||
|
if (content.hasPushKeys()) return 'pushKeys';
|
||||||
|
if (content.hasReaction()) return 'reaction';
|
||||||
|
if (content.hasTextMessage()) return 'textMessage';
|
||||||
|
if (content.hasGroupCreate()) return 'groupCreate';
|
||||||
|
if (content.hasGroupJoin()) return 'groupJoin';
|
||||||
|
if (content.hasGroupUpdate()) return 'groupUpdate';
|
||||||
|
if (content.hasResendGroupPublicKey()) return 'resendGroupPublicKey';
|
||||||
|
if (content.hasErrorMessages()) return 'errorMessages';
|
||||||
|
if (content.hasAdditionalDataMessage()) return 'additionalDataMessage';
|
||||||
|
if (content.hasTypingIndicator()) return 'typingIndicator';
|
||||||
|
if (content.hasUserDiscoveryRequest()) return 'userDiscoveryRequest';
|
||||||
|
if (content.hasUserDiscoveryUpdate()) return 'userDiscoveryUpdate';
|
||||||
|
if (content.hasKeyVerificationProof()) return 'keyVerificationProof';
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,9 @@ class BackupService {
|
||||||
))) {
|
))) {
|
||||||
final backupId = await RustBackupIdentity.getBackupId();
|
final backupId = await RustBackupIdentity.getBackupId();
|
||||||
if (backupId == null) {
|
if (backupId == null) {
|
||||||
Log.error('No backup password was set by the user.');
|
Log.warn('No backup password was set by the user.');
|
||||||
backup.identityState = LastBackupUploadState.failed;
|
backup.identityState = LastBackupUploadState.failed;
|
||||||
|
await UserService.update((u) => u.isBackupEnabled = false);
|
||||||
} else {
|
} else {
|
||||||
Log.info('Performing a identity backup.');
|
Log.info('Performing a identity backup.');
|
||||||
final encryptedBackup =
|
final encryptedBackup =
|
||||||
|
|
@ -162,7 +163,7 @@ class BackupService {
|
||||||
(backupDownloadToken, backupArchive) =
|
(backupDownloadToken, backupArchive) =
|
||||||
await RustBackupArchive.createBackupArchive();
|
await RustBackupArchive.createBackupArchive();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error(e);
|
Log.warn('Creating archive backup failed: $e');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.info(
|
Log.info(
|
||||||
|
|
@ -337,7 +338,7 @@ class BackupService {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('Error fetching backup: $e');
|
Log.warn('Error fetching backup: $e');
|
||||||
return (null, RecoveryError.noInternet);
|
return (null, RecoveryError.noInternet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:twonly/locator.dart';
|
import 'package:twonly/locator.dart';
|
||||||
|
|
@ -128,6 +130,12 @@ Future<void> handleUserStudyUpload() async {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (e is http.ClientException ||
|
||||||
|
e is SocketException ||
|
||||||
|
e is TimeoutException) {
|
||||||
|
Log.warn('Error uploading user study data: $e');
|
||||||
|
} else {
|
||||||
Log.error(e);
|
Log.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,14 @@ class Log {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void error(
|
static void error(
|
||||||
Object? messageInput, [
|
Object? messageInput, {
|
||||||
Object? error,
|
Object? error,
|
||||||
StackTrace? stackTrace,
|
StackTrace? stackTrace,
|
||||||
]) {
|
bool onlyIfSentryEnabled = false,
|
||||||
|
}) {
|
||||||
|
if (!AppState.allowErrorTrackingViaSentry && onlyIfSentryEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final message = filterLogMessage('$messageInput');
|
final message = filterLogMessage('$messageInput');
|
||||||
if (AppState.allowErrorTrackingViaSentry) {
|
if (AppState.allowErrorTrackingViaSentry) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class ScreenshotImageHelper {
|
||||||
try {
|
try {
|
||||||
return imageBytes = await imageBytesFuture;
|
return imageBytes = await imageBytesFuture;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('Could not resolve imageBytesFuture: $e');
|
Log.warn('Could not resolve imageBytesFuture: $e');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,14 +36,14 @@ class ScreenshotImageHelper {
|
||||||
try {
|
try {
|
||||||
return imageBytes = await file!.readAsBytes();
|
return imageBytes = await file!.readAsBytes();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('Could not read bytes from file: $e');
|
Log.warn('Could not read bytes from file: $e');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (image == null) return null;
|
if (image == null) return null;
|
||||||
final img = await image!.toByteData(format: io.ImageByteFormat.png);
|
final img = await image!.toByteData(format: io.ImageByteFormat.png);
|
||||||
if (img == null) {
|
if (img == null) {
|
||||||
Log.error('Got no image');
|
Log.warn('Got no image');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return imageBytes = img.buffer.asUint8List();
|
return imageBytes = img.buffer.asUint8List();
|
||||||
|
|
@ -94,7 +94,7 @@ class ScreenshotController {
|
||||||
});
|
});
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
Log.error(e);
|
Log.warn('Could not capture screenshot: $e');
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -289,12 +289,18 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
mc.cameraController == null) {
|
mc.cameraController == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await mc.cameraController?.setZoomLevel(
|
try {
|
||||||
|
if (mc.cameraController!.value.isInitialized) {
|
||||||
|
await mc.cameraController!.setZoomLevel(
|
||||||
newScale.clamp(
|
newScale.clamp(
|
||||||
mc.selectedCameraDetails.minAvailableZoom,
|
mc.selectedCameraDetails.minAvailableZoom,
|
||||||
mc.selectedCameraDetails.maxAvailableZoom,
|
mc.selectedCameraDetails.maxAvailableZoom,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} on CameraException catch (e) {
|
||||||
|
Log.warn('Failed to set zoom level: $e');
|
||||||
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
mc.selectedCameraDetails.scaleFactor = newScale;
|
mc.selectedCameraDetails.scaleFactor = newScale;
|
||||||
});
|
});
|
||||||
|
|
@ -491,9 +497,16 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
(_basePanY - (details.localPosition.dy as double)) / 30)
|
(_basePanY - (details.localPosition.dy as double)) / 30)
|
||||||
.clamp(1, mc.selectedCameraDetails.maxAvailableZoom);
|
.clamp(1, mc.selectedCameraDetails.maxAvailableZoom);
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
|
if (mc.cameraController != null &&
|
||||||
|
mc.cameraController!.value.isInitialized) {
|
||||||
await mc.cameraController!.setZoomLevel(
|
await mc.cameraController!.setZoomLevel(
|
||||||
mc.selectedCameraDetails.scaleFactor,
|
mc.selectedCameraDetails.scaleFactor,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} on CameraException catch (e) {
|
||||||
|
Log.warn('Failed to set zoom level: $e');
|
||||||
|
}
|
||||||
if (!userService.currentUser.hasZoomed) {
|
if (!userService.currentUser.hasZoomed) {
|
||||||
await UserService.update((u) => u.hasZoomed = true);
|
await UserService.update((u) => u.hasZoomed = true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ class PermissionHandlerViewState extends State<PermissionHandlerView>
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _checkAndTriggerSuccess() async {
|
Future<void> _checkAndTriggerSuccess() async {
|
||||||
|
if (!mounted) return;
|
||||||
if (_isSuccessTriggered) return;
|
if (_isSuccessTriggered) return;
|
||||||
final route = ModalRoute.of(context);
|
final route = ModalRoute.of(context);
|
||||||
if (route != null && !route.isCurrent) {
|
if (route != null && !route.isCurrent) {
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||||
pixelRatio: pixelRatio,
|
pixelRatio: pixelRatio,
|
||||||
);
|
);
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
Log.error('screenshotController did not return image bytes');
|
Log.warn('screenshotController did not return image bytes');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,7 +544,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||||
if (image == null) return null;
|
if (image == null) return null;
|
||||||
final bytes = await image.getBytes();
|
final bytes = await image.getBytes();
|
||||||
if (bytes == null) {
|
if (bytes == null) {
|
||||||
Log.error('imageBytes are empty');
|
Log.warn('imageBytes are empty');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (media.type == MediaType.image || media.type == MediaType.gif) {
|
if (media.type == MediaType.image || media.type == MediaType.gif) {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,13 @@ Future<List<Sticker>> getStickerIndex() async {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('$e');
|
if (e is http.ClientException ||
|
||||||
|
e is SocketException ||
|
||||||
|
e is TimeoutException) {
|
||||||
|
Log.warn('Could not load stickers index: $e');
|
||||||
|
} else {
|
||||||
|
Log.error('Could not load stickers index: $e');
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ class _TypingIndicatorSubtitleCompState
|
||||||
extends State<TypingIndicatorSubtitleComp> {
|
extends State<TypingIndicatorSubtitleComp> {
|
||||||
List<GroupMember> _groupMembers = [];
|
List<GroupMember> _groupMembers = [];
|
||||||
|
|
||||||
late StreamSubscription<List<(Contact, GroupMember)>> membersSub;
|
StreamSubscription<List<(Contact, GroupMember)>>? membersSub;
|
||||||
|
|
||||||
late Timer _periodicUpdate;
|
Timer? _periodicUpdate;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
@ -50,8 +50,8 @@ class _TypingIndicatorSubtitleCompState
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
membersSub.cancel();
|
membersSub?.cancel();
|
||||||
_periodicUpdate.cancel();
|
_periodicUpdate?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView>
|
||||||
// }
|
// }
|
||||||
|
|
||||||
bool _isViewActive() {
|
bool _isViewActive() {
|
||||||
|
if (!mounted) return false;
|
||||||
return !AppState.isAppInBackground &&
|
return !AppState.isAppInBackground &&
|
||||||
(ModalRoute.of(context)?.isCurrent ?? false);
|
(ModalRoute.of(context)?.isCurrent ?? false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ class _RegisterViewState extends State<RegisterView> {
|
||||||
await apiService.authenticate();
|
await apiService.authenticate();
|
||||||
widget.callbackOnSuccess();
|
widget.callbackOnSuccess();
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
Log.error('Error creating new user', e, stack);
|
Log.error('Error creating new user', error: e, stackTrace: stack);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isTryingToRegister = false;
|
_isTryingToRegister = false;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ class _SubscriptionViewState extends State<SubscriptionView> {
|
||||||
additionalOwnerName = ownerId.toString();
|
additionalOwnerName = ownerId.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!mounted) return;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
await apiService.forceIpaCheck();
|
await apiService.forceIpaCheck();
|
||||||
}
|
}
|
||||||
|
|
@ -224,6 +225,7 @@ class _PlanCardState extends State<PlanCard> {
|
||||||
});
|
});
|
||||||
await context.read<PurchasesProvider>().buy(product);
|
await context.read<PurchasesProvider>().buy(product);
|
||||||
await widget.onPurchase!();
|
await widget.onPurchase!();
|
||||||
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = null;
|
_isLoading = null;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue