diff --git a/packages/app/pubspec.lock b/packages/app/pubspec.lock index a272b1d4..76221138 100644 --- a/packages/app/pubspec.lock +++ b/packages/app/pubspec.lock @@ -33,6 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bitmap: + dependency: transitive + description: + name: bitmap + sha256: d4ec0147d64eff00efbbeead5c04d517ea4fbb528022adaa3551e3586e80f4d4 + url: "https://pub.dev" + source: hosted + version: "0.1.3" boolean_selector: dependency: transitive description: diff --git a/packages/neon/neon/lib/neon.dart b/packages/neon/neon/lib/neon.dart index db0fef35..d8011d1c 100644 --- a/packages/neon/neon/lib/neon.dart +++ b/packages/neon/neon/lib/neon.dart @@ -3,7 +3,10 @@ library neon; import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'dart:math'; +import 'dart:ui'; +import 'package:bitmap/bitmap.dart'; import 'package:crypto/crypto.dart'; import 'package:file_picker/file_picker.dart'; import 'package:filesize/filesize.dart'; diff --git a/packages/neon/neon/lib/src/utils/push_utils.dart b/packages/neon/neon/lib/src/utils/push_utils.dart index 6d715bdb..9aa3d676 100644 --- a/packages/neon/neon/lib/src/utils/push_utils.dart +++ b/packages/neon/neon/lib/src/utils/push_utils.dart @@ -76,15 +76,43 @@ class PushUtils { final cache = Cache(platform); await cache.init(); - NextcloudNotificationsNotification? notification; var accounts = []; Account? account; + NextcloudNotificationsNotification? notification; + AndroidBitmap? largeIconBitmap; try { accounts = loadAccounts(AppStorage('accounts', sharedPreferences)); account = accounts.find(instance); if (account != null) { notification = (await account.client.notifications.getNotification(id: pushNotification.subject.nid!)).ocs.data; + if (notification.icon?.endsWith('.svg') ?? false) { + // Only SVG icons are supported right now (should be most of them) + + final cacheManager = DefaultCacheManager(); + final file = await cacheManager.getSingleFile(notification.icon!); + + final pictureInfo = await vg.loadPicture(SvgFileLoader(file), null); + + const largeIconSize = 256; + final scale = min(largeIconSize / pictureInfo.size.width, largeIconSize / pictureInfo.size.height); + final scaledWidth = (pictureInfo.size.width * scale).toInt(); + final scaledHeight = (pictureInfo.size.height * scale).toInt(); + + final recorder = PictureRecorder(); + Canvas(recorder) + ..scale(scale) + ..drawPicture(pictureInfo.picture) + ..drawColor(themePrimaryColor, BlendMode.srcIn); + + pictureInfo.picture.dispose(); + + final image = recorder.endRecording().toImageSync(scaledWidth, scaledHeight); + final bytes = await image.toByteData(format: ImageByteFormat.png); + + final bitmap = await Bitmap.fromProvider(MemoryImage(bytes!.buffer.asUint8List())); + largeIconBitmap = ByteArrayAndroidBitmap(bitmap.buildHeaded()); + } } } catch (e, s) { debugPrint(e.toString()); @@ -113,6 +141,7 @@ class PushUtils { subText: accounts.length > 1 && account != null ? account.client.humanReadableID : null, groupKey: 'app_$appID', icon: '@mipmap/ic_launcher', + largeIcon: largeIconBitmap, when: when?.millisecondsSinceEpoch, color: themePrimaryColor, category: pushNotification.type == 'voip' ? AndroidNotificationCategory.call : null, diff --git a/packages/neon/neon/pubspec.yaml b/packages/neon/neon/pubspec.yaml index beda1682..48d2f451 100644 --- a/packages/neon/neon/pubspec.yaml +++ b/packages/neon/neon/pubspec.yaml @@ -7,6 +7,7 @@ environment: flutter: '>=3.10.0' dependencies: + bitmap: ^0.1.3 collection: ^1.17.1 crypto: ^3.0.3 file_picker: ^5.3.0