diff --git a/lib/src/database/tables/media_uploads_table.dart b/lib/src/database/tables/media_uploads_table.dart index 4492d63..d4ca964 100644 --- a/lib/src/database/tables/media_uploads_table.dart +++ b/lib/src/database/tables/media_uploads_table.dart @@ -12,6 +12,7 @@ enum UploadState { pending, readyToUpload, + uploadTaskStarted, receiverNotified, // after all users notified all media files that are not storable by the other person will be deleted } diff --git a/lib/src/services/api/media_upload.dart b/lib/src/services/api/media_upload.dart index 5f6e07b..2d46873 100644 --- a/lib/src/services/api/media_upload.dart +++ b/lib/src/services/api/media_upload.dart @@ -357,13 +357,14 @@ Future finalizeUpload(int mediaUploadId, List contactIds, final lockingHandleNextMediaUploadStep = Mutex(); Future handleNextMediaUploadSteps(int mediaUploadId) async { - bool rerun = await lockingHandleNextMediaUploadStep.protect(() async { + await lockingHandleNextMediaUploadStep.protect(() async { var mediaUpload = await twonlyDB.mediaUploadsDao .getMediaUploadById(mediaUploadId) .getSingleOrNull(); if (mediaUpload == null) return false; - if (mediaUpload.state == UploadState.receiverNotified) { + if (mediaUpload.state == UploadState.receiverNotified || + mediaUpload.state == UploadState.uploadTaskStarted) { /// Upload done and all users are notified :) Log.info("$mediaUploadId is already done"); return false; @@ -380,16 +381,13 @@ Future handleNextMediaUploadSteps(int mediaUploadId) async { return false; } - return await handleMediaUpload(mediaUpload); + await handleMediaUpload(mediaUpload); } catch (e) { Log.error("Non recoverable error while sending media file: $e"); await handleUploadError(mediaUpload); } return false; }); - if (rerun) { - handleNextMediaUploadSteps(mediaUploadId); - } } /// @@ -402,6 +400,8 @@ Future handleUploadStatusUpdate(TaskStatusUpdate update) async { bool failed = false; int mediaUploadId = int.parse(update.task.taskId.replaceAll("upload_", "")); + Log.info("Upload $mediaUploadId done."); + MediaUpload? media = await twonlyDB.mediaUploadsDao .getMediaUploadById(mediaUploadId) .getSingleOrNull(); @@ -478,11 +478,11 @@ Future handleUploadError(MediaUpload mediaUpload) async { await twonlyDB.mediaUploadsDao.deleteMediaUpload(mediaUpload.mediaUploadId); } -Future handleMediaUpload(MediaUpload media) async { +Future handleMediaUpload(MediaUpload media) async { Uint8List bytesToUpload = await readSendMediaFile(media.mediaUploadId, "encrypted"); - if (media.messageIds == null) return false; + if (media.messageIds == null) return; List downloadTokens = createDownloadTokens(media.messageIds!.length); @@ -571,7 +571,7 @@ Future handleMediaUpload(MediaUpload media) async { await FlutterSecureStorage().read(key: SecureStorageKeys.apiAuthToken); if (apiAuthToken == null) { Log.error("api auth token not defined."); - return false; + return; } File uploadRequestFile = await writeSendMediaFile( @@ -600,11 +600,17 @@ Future handleMediaUpload(MediaUpload media) async { final result = await FileDownloader().enqueue(task); - return result; + if (result) { + await twonlyDB.mediaUploadsDao.updateMediaUpload( + media.mediaUploadId, + MediaUploadsCompanion( + state: Value(UploadState.uploadTaskStarted), + ), + ); + } } catch (e) { Log.error("Exception during upload: $e"); } - return false; } Future compressVideoIfExists(int mediaUploadId) async { diff --git a/lib/src/services/api/server_messages.dart b/lib/src/services/api/server_messages.dart index 83ffca1..fb2c3f3 100644 --- a/lib/src/services/api/server_messages.dart +++ b/lib/src/services/api/server_messages.dart @@ -206,8 +206,9 @@ Future handleNewMessage(int fromUserId, Uint8List body) async { avatarSvg: Value(content.avatarSvg), displayName: Value(content.displayName), ); - twonlyDB.contactsDao.updateContact(fromUserId, update); + await twonlyDB.contactsDao.updateContact(fromUserId, update); } + createPushAvatars(); break; case MessageKind.requestPushKey: diff --git a/lib/src/services/fcm.service.dart b/lib/src/services/fcm.service.dart index b15c498..d625b9c 100644 --- a/lib/src/services/fcm.service.dart +++ b/lib/src/services/fcm.service.dart @@ -3,8 +3,7 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/constants/secure_storage_keys.dart'; -import 'package:twonly/src/database/twonly_database.dart'; -import 'package:twonly/src/services/notification.service.dart'; +import 'package:twonly/src/services/notification.background.service.dart'; import 'package:twonly/src/utils/log.dart'; import 'dart:io' show Platform; import '../../firebase_options.dart'; @@ -79,9 +78,7 @@ Future initFCMService() async { Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { initLogger(); Log.info('Handling a background message: ${message.messageId}'); - twonlyDB = TwonlyDatabase(); await handleRemoteMessage(message); - // make sure every thing run... await Future.delayed(Duration(milliseconds: 2000)); } diff --git a/lib/src/services/notification.background.service.dart b/lib/src/services/notification.background.service.dart new file mode 100644 index 0000000..1cd1da0 --- /dev/null +++ b/lib/src/services/notification.background.service.dart @@ -0,0 +1,282 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; +import 'package:cryptography_plus/cryptography_plus.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:twonly/src/services/notification.service.dart'; +import 'package:twonly/src/utils/log.dart'; + +final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + +Future customLocalPushNotification(String title, String msg) async { + const AndroidNotificationDetails androidNotificationDetails = + AndroidNotificationDetails( + '1', + 'System', + channelDescription: 'System messages.', + importance: Importance.max, + priority: Priority.max, + ); + + const DarwinNotificationDetails darwinNotificationDetails = + DarwinNotificationDetails(); + const NotificationDetails notificationDetails = NotificationDetails( + android: androidNotificationDetails, iOS: darwinNotificationDetails); + + await flutterLocalNotificationsPlugin.show( + 999999 + Random.secure().nextInt(9999), + title, + msg, + notificationDetails, + ); +} + +Future handlePushData(String pushDataJson) async { + try { + String jsonString = utf8.decode(base64.decode(pushDataJson)); + final pushData = PushNotification.fromJson(jsonDecode(jsonString)); + + PushKind? pushKind; + PushUser? pushUser; + int? fromUserId; + + if (pushData.keyId == 0) { + List key = "InsecureOnlyUsedForAddingContact".codeUnits; + pushKind = await tryDecryptMessage(key, pushData); + } else { + var pushKeys = await getPushKeys("receivingPushKeys"); + for (final userId in pushKeys.keys) { + for (final key in pushKeys[userId]!.keys) { + if (key.id == pushData.keyId) { + pushKind = await tryDecryptMessage(key.key, pushData); + if (pushKind != null) { + pushUser = pushKeys[userId]!; + fromUserId = userId; + break; + } + } + } + // found correct key and user + if (pushUser != null) break; + } + } + + if (pushKind != null) { + if (pushKind == PushKind.testNotification) { + await customLocalPushNotification( + "Test notification", "This is a test notification."); + } else if (pushUser != null && fromUserId != null) { + await showLocalPushNotification(pushUser, fromUserId, pushKind); + } else { + await showLocalPushNotificationWithoutUserId(pushKind); + } + } + } catch (e) { + Log.error(e); + } +} + +Future tryDecryptMessage( + List key, PushNotification noti) async { + try { + final chacha20 = Chacha20.poly1305Aead(); + SecretKeyData secretKeyData = SecretKeyData(key); + + SecretBox secretBox = SecretBox( + noti.cipherText, + nonce: noti.nonce, + mac: Mac(noti.mac), + ); + + final plaintext = + await chacha20.decrypt(secretBox, secretKey: secretKeyData); + final plaintextString = utf8.decode(plaintext); + return PushKindExtension.fromString(plaintextString); + } catch (e) { + // this error is allowed to happen... + return null; + } +} + +Future showLocalPushNotification( + PushUser pushUser, + int fromUserId, + PushKind pushKind, +) async { + String? title; + String? body; + + // do not show notification for blocked users... + if (pushUser.blocked) { + Log.info("Blocked a message from a blocked user!"); + return; + } + + title = pushUser.displayName; + body = getPushNotificationText(pushKind); + if (body == "") { + Log.error("No push notification type defined!"); + } + + FilePathAndroidBitmap? styleInformation; + String? avatarPath = await getAvatarIcon(fromUserId); + if (avatarPath != null) { + styleInformation = FilePathAndroidBitmap(avatarPath); + } + + AndroidNotificationDetails androidNotificationDetails = + AndroidNotificationDetails('0', 'Messages', + channelDescription: 'Messages from other users.', + importance: Importance.max, + priority: Priority.max, + ticker: 'You got a new message.', + largeIcon: styleInformation); + + const DarwinNotificationDetails darwinNotificationDetails = + DarwinNotificationDetails(); + NotificationDetails notificationDetails = NotificationDetails( + android: androidNotificationDetails, iOS: darwinNotificationDetails); + + await flutterLocalNotificationsPlugin.show( + fromUserId, + title, + body, + notificationDetails, + payload: pushKind.name, + ); +} + +Future showLocalPushNotificationWithoutUserId( + PushKind pushKind, +) async { + String? title; + String? body; + + body = getPushNotificationTextWithoutUserId(pushKind); + if (body == "") { + Log.error("No push notification type defined!"); + } + + AndroidNotificationDetails androidNotificationDetails = + AndroidNotificationDetails('0', 'Messages', + channelDescription: 'Messages from other users.', + importance: Importance.max, + priority: Priority.max, + ticker: 'You got a new message.'); + + const DarwinNotificationDetails darwinNotificationDetails = + DarwinNotificationDetails(); + NotificationDetails notificationDetails = NotificationDetails( + android: androidNotificationDetails, iOS: darwinNotificationDetails); + + await flutterLocalNotificationsPlugin.show( + 2, + title, + body, + notificationDetails, + payload: pushKind.name, + ); +} + +Future getAvatarIcon(int contactId) async { + final directory = await getApplicationCacheDirectory(); + final avatarsDirectory = Directory('${directory.path}/avatars'); + final filePath = '${avatarsDirectory.path}/$contactId.png'; + final file = File(filePath); + if (file.existsSync()) { + return filePath; + } + return null; +} + +String getPushNotificationTextWithoutUserId(PushKind pushKind) { + Map pushNotificationText; + + String systemLanguage = Platform.localeName; + + if (systemLanguage.contains("de")) { + pushNotificationText = { + PushKind.text.name: "Du hast eine neue Nachricht erhalten.", + PushKind.twonly.name: "Du hast ein neues twonly erhalten.", + PushKind.video.name: "Du hast ein neues Video erhalten.", + PushKind.image.name: "Du hast ein neues Bild erhalten.", + PushKind.contactRequest.name: + "Du hast eine neue Kontaktanfrage erhalten.", + PushKind.acceptRequest.name: "Deine Kontaktanfrage wurde angenommen.", + PushKind.storedMediaFile.name: "Dein Bild wurde gespeichert.", + PushKind.reaction.name: "Du hast eine Reaktion auf dein Bild erhalten.", + PushKind.reopenedMedia.name: "Dein Bild wurde erneut geöffnet.", + PushKind.reactionToVideo.name: + "Du hast eine Reaktion auf dein Video erhalten.", + PushKind.reactionToText.name: + "Du hast eine Reaktion auf deinen Text erhalten.", + PushKind.reactionToImage.name: + "Du hast eine Reaktion auf dein Bild erhalten.", + PushKind.response.name: "Du hast eine Antwort erhalten.", + }; + } else { + pushNotificationText = { + PushKind.text.name: "You have received a new message.", + PushKind.twonly.name: "You have received a new twonly.", + PushKind.video.name: "You have received a new video.", + PushKind.image.name: "You have received a new image.", + PushKind.contactRequest.name: "You have received a new contact request.", + PushKind.acceptRequest.name: "Your contact request has been accepted.", + PushKind.storedMediaFile.name: "Your image has been saved.", + PushKind.reaction.name: "You have received a reaction to your image.", + PushKind.reopenedMedia.name: "Your image has been reopened.", + PushKind.reactionToVideo.name: + "You have received a reaction to your video.", + PushKind.reactionToText.name: + "You have received a reaction to your text.", + PushKind.reactionToImage.name: + "You have received a reaction to your image.", + PushKind.response.name: "You have received a response.", + }; + } + return pushNotificationText[pushKind.name] ?? ""; +} + +String getPushNotificationText(PushKind pushKind) { + String systemLanguage = Platform.localeName; + + Map pushNotificationText; + + if (systemLanguage.contains("de")) { + pushNotificationText = { + PushKind.text.name: "hat dir eine Nachricht gesendet.", + PushKind.twonly.name: "hat dir ein twonly gesendet.", + PushKind.video.name: "hat dir ein Video gesendet.", + PushKind.image.name: "hat dir ein Bild gesendet.", + PushKind.contactRequest.name: "möchte sich mit dir vernetzen.", + PushKind.acceptRequest.name: "ist jetzt mit dir vernetzt.", + PushKind.storedMediaFile.name: "hat dein Bild gespeichert.", + PushKind.reaction.name: "hat auf dein Bild reagiert.", + PushKind.reopenedMedia.name: "hat dein Bild erneut geöffnet.", + PushKind.reactionToVideo.name: "hat auf dein Video reagiert.", + PushKind.reactionToText.name: "hat auf deinen Text reagiert.", + PushKind.reactionToImage.name: "hat auf dein Bild reagiert.", + PushKind.response.name: "hat dir geantwortet.", + }; + } else { + pushNotificationText = { + PushKind.text.name: "has sent you a message.", + PushKind.twonly.name: "has sent you a twonly.", + PushKind.video.name: "has sent you a video.", + PushKind.image.name: "has sent you an image.", + PushKind.contactRequest.name: "wants to connect with you.", + PushKind.acceptRequest.name: "is now connected with you.", + PushKind.storedMediaFile.name: "has stored your image.", + PushKind.reaction.name: "has reacted to your image.", + PushKind.reopenedMedia.name: "has reopened your image.", + PushKind.reactionToVideo.name: "has reacted to your video.", + PushKind.reactionToText.name: "has reacted to your text.", + PushKind.reactionToImage.name: "has reacted to your image.", + PushKind.response.name: "has responded.", + }; + } + return pushNotificationText[pushKind.name] ?? ""; +} diff --git a/lib/src/services/notification.service.dart b/lib/src/services/notification.service.dart index bd1a4e5..fc3e081 100644 --- a/lib/src/services/notification.service.dart +++ b/lib/src/services/notification.service.dart @@ -290,72 +290,6 @@ Future getPushData(int toUserId, PushKind kind) async { return Utf8Encoder().convert(jsonEncode(res.toJson())); } -Future tryDecryptMessage( - List key, PushNotification noti) async { - try { - final chacha20 = Chacha20.poly1305Aead(); - SecretKeyData secretKeyData = SecretKeyData(key); - - SecretBox secretBox = SecretBox( - noti.cipherText, - nonce: noti.nonce, - mac: Mac(noti.mac), - ); - - final plaintext = - await chacha20.decrypt(secretBox, secretKey: secretKeyData); - final plaintextString = utf8.decode(plaintext); - return PushKindExtension.fromString(plaintextString); - } catch (e) { - // this error is allowed to happen... - return null; - } -} - -Future handlePushData(String pushDataJson) async { - try { - String jsonString = utf8.decode(base64.decode(pushDataJson)); - final pushData = PushNotification.fromJson(jsonDecode(jsonString)); - - PushKind? pushKind; - int? fromUserId; - - if (pushData.keyId == 0) { - List key = "InsecureOnlyUsedForAddingContact".codeUnits; - pushKind = await tryDecryptMessage(key, pushData); - } else { - var pushKeys = await getPushKeys("receivingPushKeys"); - for (final userId in pushKeys.keys) { - for (final key in pushKeys[userId]!.keys) { - if (key.id == pushData.keyId) { - pushKind = await tryDecryptMessage(key.key, pushData); - if (pushKind != null) { - fromUserId = userId; - break; - } - } - } - // found correct key and user - if (fromUserId != null) break; - } - } - - if (pushKind != null) { - if (pushKind == PushKind.testNotification) { - await customLocalPushNotification( - "Test notification", "This is a test notification."); - } else if (fromUserId != null) { - await showLocalPushNotification(fromUserId, pushKind); - } else { - await showLocalPushNotificationWithoutUserId(pushKind); - await setupNotificationWithUsers(); - } - } - } catch (e) { - Log.error(e); - } -} - Future> getPushKeys(String storageKey) async { var storage = FlutterSecureStorage(); String? pushKeysJson = await storage.read( @@ -455,229 +389,34 @@ Future setupPushNotification() async { ); } -Future showLocalPushNotification( - int fromUserId, - PushKind pushKind, -) async { - String? title; - String? body; - - Contact? user = await twonlyDB.contactsDao - .getContactByUserId(fromUserId) - .getSingleOrNull(); - - if (user == null) return; - - // do not show notification for blocked users... - if (user.blocked) { - Log.info("Blocked a message from a blocked user!"); - return; +Future createPushAvatars() async { + if (!Platform.isAndroid) { + return; // avatars currently only shown in Android... } + final contacts = await twonlyDB.contactsDao.getAllNotBlockedContacts(); - title = getContactDisplayName(user); - body = getPushNotificationText(pushKind); - if (body == "") { - Log.error("No push notification type defined!"); + for (final contact in contacts) { + if (contact.avatarSvg == null) return null; + + final PictureInfo pictureInfo = + await vg.loadPicture(SvgStringLoader(contact.avatarSvg!), null); + + final ui.Image image = await pictureInfo.picture.toImage(300, 300); + + final ByteData? byteData = + await image.toByteData(format: ui.ImageByteFormat.png); + final Uint8List pngBytes = byteData!.buffer.asUint8List(); + + // Get the directory to save the image + final directory = await getApplicationCacheDirectory(); + final avatarsDirectory = Directory('${directory.path}/avatars'); + + // Create the avatars directory if it does not exist + if (!await avatarsDirectory.exists()) { + await avatarsDirectory.create(recursive: true); + } + final filePath = '${avatarsDirectory.path}/${contact.userId}.png'; + await File(filePath).writeAsBytes(pngBytes); + pictureInfo.picture.dispose(); } - - FilePathAndroidBitmap? styleInformation; - String? avatarPath = await getAvatarIcon(user); - if (avatarPath != null) { - styleInformation = FilePathAndroidBitmap(avatarPath); - } - - AndroidNotificationDetails androidNotificationDetails = - AndroidNotificationDetails('0', 'Messages', - channelDescription: 'Messages from other users.', - importance: Importance.max, - priority: Priority.max, - ticker: 'You got a new message.', - largeIcon: styleInformation); - - const DarwinNotificationDetails darwinNotificationDetails = - DarwinNotificationDetails(); - NotificationDetails notificationDetails = NotificationDetails( - android: androidNotificationDetails, iOS: darwinNotificationDetails); - - await flutterLocalNotificationsPlugin.show( - fromUserId, - title, - body, - notificationDetails, - payload: pushKind.name, - ); -} - -Future showLocalPushNotificationWithoutUserId( - PushKind pushKind, -) async { - String? title; - String? body; - - body = getPushNotificationTextWithoutUserId(pushKind); - if (body == "") { - Log.error("No push notification type defined!"); - } - - AndroidNotificationDetails androidNotificationDetails = - AndroidNotificationDetails('0', 'Messages', - channelDescription: 'Messages from other users.', - importance: Importance.max, - priority: Priority.max, - ticker: 'You got a new message.'); - - const DarwinNotificationDetails darwinNotificationDetails = - DarwinNotificationDetails(); - NotificationDetails notificationDetails = NotificationDetails( - android: androidNotificationDetails, iOS: darwinNotificationDetails); - - await flutterLocalNotificationsPlugin.show( - 2, - title, - body, - notificationDetails, - payload: pushKind.name, - ); -} - -Future customLocalPushNotification(String title, String msg) async { - const AndroidNotificationDetails androidNotificationDetails = - AndroidNotificationDetails( - '1', - 'System', - channelDescription: 'System messages.', - importance: Importance.max, - priority: Priority.max, - ); - - const DarwinNotificationDetails darwinNotificationDetails = - DarwinNotificationDetails(); - const NotificationDetails notificationDetails = NotificationDetails( - android: androidNotificationDetails, iOS: darwinNotificationDetails); - - await flutterLocalNotificationsPlugin.show( - 999999 + Random.secure().nextInt(9999), - title, - msg, - notificationDetails, - ); -} - -String getPushNotificationTextWithoutUserId(PushKind pushKind) { - Map pushNotificationText; - - String systemLanguage = Platform.localeName; - - if (systemLanguage.contains("de")) { - pushNotificationText = { - PushKind.text.name: "Du hast eine neue Nachricht erhalten.", - PushKind.twonly.name: "Du hast ein neues twonly erhalten.", - PushKind.video.name: "Du hast ein neues Video erhalten.", - PushKind.image.name: "Du hast ein neues Bild erhalten.", - PushKind.contactRequest.name: - "Du hast eine neue Kontaktanfrage erhalten.", - PushKind.acceptRequest.name: "Deine Kontaktanfrage wurde angenommen.", - PushKind.storedMediaFile.name: "Dein Bild wurde gespeichert.", - PushKind.reaction.name: "Du hast eine Reaktion auf dein Bild erhalten.", - PushKind.reopenedMedia.name: "Dein Bild wurde erneut geöffnet.", - PushKind.reactionToVideo.name: - "Du hast eine Reaktion auf dein Video erhalten.", - PushKind.reactionToText.name: - "Du hast eine Reaktion auf deinen Text erhalten.", - PushKind.reactionToImage.name: - "Du hast eine Reaktion auf dein Bild erhalten.", - PushKind.response.name: "Du hast eine Antwort erhalten.", - }; - } else { - pushNotificationText = { - PushKind.text.name: "You have received a new message.", - PushKind.twonly.name: "You have received a new twonly.", - PushKind.video.name: "You have received a new video.", - PushKind.image.name: "You have received a new image.", - PushKind.contactRequest.name: "You have received a new contact request.", - PushKind.acceptRequest.name: "Your contact request has been accepted.", - PushKind.storedMediaFile.name: "Your image has been saved.", - PushKind.reaction.name: "You have received a reaction to your image.", - PushKind.reopenedMedia.name: "Your image has been reopened.", - PushKind.reactionToVideo.name: - "You have received a reaction to your video.", - PushKind.reactionToText.name: - "You have received a reaction to your text.", - PushKind.reactionToImage.name: - "You have received a reaction to your image.", - PushKind.response.name: "You have received a response.", - }; - } - return pushNotificationText[pushKind.name] ?? ""; -} - -String getPushNotificationText(PushKind pushKind) { - String systemLanguage = Platform.localeName; - - Map pushNotificationText; - - if (systemLanguage.contains("de")) { - pushNotificationText = { - PushKind.text.name: "hat dir eine Nachricht gesendet.", - PushKind.twonly.name: "hat dir ein twonly gesendet.", - PushKind.video.name: "hat dir ein Video gesendet.", - PushKind.image.name: "hat dir ein Bild gesendet.", - PushKind.contactRequest.name: "möchte sich mit dir vernetzen.", - PushKind.acceptRequest.name: "ist jetzt mit dir vernetzt.", - PushKind.storedMediaFile.name: "hat dein Bild gespeichert.", - PushKind.reaction.name: "hat auf dein Bild reagiert.", - PushKind.reopenedMedia.name: "hat dein Bild erneut geöffnet.", - PushKind.reactionToVideo.name: "hat auf dein Video reagiert.", - PushKind.reactionToText.name: "hat auf deinen Text reagiert.", - PushKind.reactionToImage.name: "hat auf dein Bild reagiert.", - PushKind.response.name: "hat dir geantwortet.", - }; - } else { - pushNotificationText = { - PushKind.text.name: "has sent you a message.", - PushKind.twonly.name: "has sent you a twonly.", - PushKind.video.name: "has sent you a video.", - PushKind.image.name: "has sent you an image.", - PushKind.contactRequest.name: "wants to connect with you.", - PushKind.acceptRequest.name: "is now connected with you.", - PushKind.storedMediaFile.name: "has stored your image.", - PushKind.reaction.name: "has reacted to your image.", - PushKind.reopenedMedia.name: "has reopened your image.", - PushKind.reactionToVideo.name: "has reacted to your video.", - PushKind.reactionToText.name: "has reacted to your text.", - PushKind.reactionToImage.name: "has reacted to your image.", - PushKind.response.name: "has responded.", - }; - } - return pushNotificationText[pushKind.name] ?? ""; -} - -Future getAvatarIcon(Contact user) async { - if (user.avatarSvg == null) return null; - - final PictureInfo pictureInfo = - await vg.loadPicture(SvgStringLoader(user.avatarSvg!), null); - - final ui.Image image = await pictureInfo.picture.toImage(300, 300); - - final ByteData? byteData = - await image.toByteData(format: ui.ImageByteFormat.png); - final Uint8List pngBytes = byteData!.buffer.asUint8List(); - - // Get the directory to save the image - final directory = await getApplicationCacheDirectory(); - final avatarsDirectory = Directory('${directory.path}/avatars'); - - // Create the avatars directory if it does not exist - if (!await avatarsDirectory.exists()) { - await avatarsDirectory.create(recursive: true); - } - - final filePath = '${avatarsDirectory.path}/${user.userId}.png'; - final file = File(filePath); - await file.writeAsBytes(pngBytes); - - pictureInfo.picture.dispose(); - - return filePath; } diff --git a/lib/src/services/twonly_safe/create_backup.twonly_safe.dart b/lib/src/services/twonly_safe/create_backup.twonly_safe.dart index 02b6a8f..d81b3ba 100644 --- a/lib/src/services/twonly_safe/create_backup.twonly_safe.dart +++ b/lib/src/services/twonly_safe/create_backup.twonly_safe.dart @@ -21,7 +21,6 @@ Future performTwonlySafeBackup({bool force = false}) async { final user = await getUser(); if (user == null || user.twonlySafeBackup == null || user.isDemoUser) { - Log.warn("perform twonly safe backup was called while it is disabled"); return; }