|
|
|
@ -2,11 +2,13 @@ import 'dart:convert';
|
|
|
|
|
import 'dart:io';
|
|
|
|
|
import 'dart:ui';
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
|
|
|
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
|
|
|
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
|
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
|
|
|
import 'package:flutter_shortcuts/flutter_shortcuts.dart';
|
|
|
|
|
import 'package:matrix/matrix.dart';
|
|
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
|
|
|
|
|
@ -55,8 +57,7 @@ Future<void> pushHelper(
|
|
|
|
|
iOS: const DarwinNotificationDetails(),
|
|
|
|
|
android: AndroidNotificationDetails(
|
|
|
|
|
AppConfig.pushNotificationsChannelId,
|
|
|
|
|
AppConfig.pushNotificationsChannelName,
|
|
|
|
|
channelDescription: AppConfig.pushNotificationsChannelDescription,
|
|
|
|
|
l10n.incomingMessages,
|
|
|
|
|
number: notification.counts?.unread,
|
|
|
|
|
ticker: l10n.unreadChats(notification.counts?.unread ?? 1),
|
|
|
|
|
importance: Importance.max,
|
|
|
|
@ -170,34 +171,53 @@ Future<void> _tryPushHelper(
|
|
|
|
|
final avatar = event.room.avatar
|
|
|
|
|
?.getThumbnail(
|
|
|
|
|
client,
|
|
|
|
|
width: 126,
|
|
|
|
|
height: 126,
|
|
|
|
|
width: 128,
|
|
|
|
|
height: 128,
|
|
|
|
|
)
|
|
|
|
|
.toString();
|
|
|
|
|
File? avatarFile;
|
|
|
|
|
final senderAvatar = event.room.isDirectChat
|
|
|
|
|
? avatar
|
|
|
|
|
: event.senderFromMemoryOrFallback.avatarUrl
|
|
|
|
|
?.getThumbnail(
|
|
|
|
|
client,
|
|
|
|
|
width: 128,
|
|
|
|
|
height: 128,
|
|
|
|
|
)
|
|
|
|
|
.toString();
|
|
|
|
|
|
|
|
|
|
File? roomAvatarFile, senderAvatarFile;
|
|
|
|
|
try {
|
|
|
|
|
avatarFile = avatar == null
|
|
|
|
|
roomAvatarFile = avatar == null
|
|
|
|
|
? null
|
|
|
|
|
: await DefaultCacheManager().getSingleFile(avatar);
|
|
|
|
|
} catch (e, s) {
|
|
|
|
|
Logs().e('Unable to get avatar picture', e, s);
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
senderAvatarFile = event.room.isDirectChat
|
|
|
|
|
? roomAvatarFile
|
|
|
|
|
: senderAvatar == null
|
|
|
|
|
? null
|
|
|
|
|
: await DefaultCacheManager().getSingleFile(senderAvatar);
|
|
|
|
|
} catch (e, s) {
|
|
|
|
|
Logs().e('Unable to get avatar picture', e, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final id = await mapRoomIdToInt(event.room.id);
|
|
|
|
|
|
|
|
|
|
// Show notification
|
|
|
|
|
final person = Person(
|
|
|
|
|
name: event.senderFromMemoryOrFallback.calcDisplayname(),
|
|
|
|
|
icon:
|
|
|
|
|
avatarFile == null ? null : BitmapFilePathAndroidIcon(avatarFile.path),
|
|
|
|
|
key: event.senderId,
|
|
|
|
|
uri: 'matrix:${event.senderId.replaceFirst('@', '')}',
|
|
|
|
|
important: event.room.isFavourite,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
final newMessage = Message(
|
|
|
|
|
body,
|
|
|
|
|
event.originServerTs,
|
|
|
|
|
person,
|
|
|
|
|
Person(
|
|
|
|
|
bot: event.messageType == MessageTypes.Notice,
|
|
|
|
|
key: event.senderId,
|
|
|
|
|
name: event.senderFromMemoryOrFallback.calcDisplayname(),
|
|
|
|
|
icon: senderAvatarFile == null
|
|
|
|
|
? null
|
|
|
|
|
: BitmapFilePathAndroidIcon(senderAvatarFile.path),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
final messagingStyleInformation = PlatformInfos.isAndroid
|
|
|
|
@ -232,15 +252,21 @@ Future<void> _tryPushHelper(
|
|
|
|
|
?.createNotificationChannel(roomsChannel);
|
|
|
|
|
|
|
|
|
|
final androidPlatformChannelSpecifics = AndroidNotificationDetails(
|
|
|
|
|
event.room.id,
|
|
|
|
|
roomName,
|
|
|
|
|
channelDescription: groupName,
|
|
|
|
|
AppConfig.pushNotificationsChannelId,
|
|
|
|
|
l10n.incomingMessages,
|
|
|
|
|
number: notification.counts?.unread,
|
|
|
|
|
category: AndroidNotificationCategory.message,
|
|
|
|
|
shortcutId: event.room.id,
|
|
|
|
|
styleInformation: messagingStyleInformation ??
|
|
|
|
|
MessagingStyleInformation(
|
|
|
|
|
person,
|
|
|
|
|
Person(
|
|
|
|
|
name: event.senderFromMemoryOrFallback.calcDisplayname(),
|
|
|
|
|
icon: roomAvatarFile == null
|
|
|
|
|
? null
|
|
|
|
|
: BitmapFilePathAndroidIcon(roomAvatarFile.path),
|
|
|
|
|
key: event.roomId,
|
|
|
|
|
important: event.room.isFavourite,
|
|
|
|
|
),
|
|
|
|
|
conversationTitle: roomName,
|
|
|
|
|
groupConversation: !event.room.isDirectChat,
|
|
|
|
|
messages: [newMessage],
|
|
|
|
@ -257,11 +283,15 @@ Future<void> _tryPushHelper(
|
|
|
|
|
iOS: iOSPlatformChannelSpecifics,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
final title = event.room.getLocalizedDisplayname(MatrixLocals(l10n));
|
|
|
|
|
|
|
|
|
|
if (PlatformInfos.isAndroid) {
|
|
|
|
|
_setShortcut(event, l10n, title, roomAvatarFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await flutterLocalNotificationsPlugin.show(
|
|
|
|
|
id,
|
|
|
|
|
event.room.getLocalizedDisplayname(
|
|
|
|
|
MatrixLocals(l10n),
|
|
|
|
|
),
|
|
|
|
|
title,
|
|
|
|
|
body,
|
|
|
|
|
platformChannelSpecifics,
|
|
|
|
|
payload: event.roomId,
|
|
|
|
@ -269,6 +299,35 @@ Future<void> _tryPushHelper(
|
|
|
|
|
Logs().v('Push helper has been completed!');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a shortcut for Android platform but does not block displaying the
|
|
|
|
|
/// notification. This is optional but provides a nicer view of the
|
|
|
|
|
/// notification popup.
|
|
|
|
|
void _setShortcut(
|
|
|
|
|
Event event,
|
|
|
|
|
L10n l10n,
|
|
|
|
|
String title,
|
|
|
|
|
File? avatarFile,
|
|
|
|
|
) async {
|
|
|
|
|
final flutterShortcuts = FlutterShortcuts();
|
|
|
|
|
await flutterShortcuts.initialize(debug: !kReleaseMode);
|
|
|
|
|
await flutterShortcuts.pushShortcutItem(
|
|
|
|
|
shortcut: ShortcutItem(
|
|
|
|
|
id: event.room.id,
|
|
|
|
|
action: l10n.openChat,
|
|
|
|
|
shortLabel: title,
|
|
|
|
|
conversationShortcut: true,
|
|
|
|
|
icon: avatarFile == null
|
|
|
|
|
? null
|
|
|
|
|
: ShortcutMemoryIcon(jpegImage: await avatarFile.readAsBytes())
|
|
|
|
|
.toString(),
|
|
|
|
|
shortcutIconAsset: avatarFile == null
|
|
|
|
|
? ShortcutIconAsset.androidAsset
|
|
|
|
|
: ShortcutIconAsset.memoryAsset,
|
|
|
|
|
isImportant: event.room.isFavourite,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Workaround for the problem that local notification IDs must be int but we
|
|
|
|
|
/// sort by [roomId] which is a String. To make sure that we don't have duplicated
|
|
|
|
|
/// IDs we map the [roomId] to a number and store this number.
|
|
|
|
|