feat: Add notification shortcuts to android

This commit is contained in:
krille-chan 2024-02-15 12:02:32 +01:00
parent aa68e8fe3b
commit dee9323d47
No known key found for this signature in database
6 changed files with 96 additions and 29 deletions

View file

@ -2469,5 +2469,6 @@
"sender": {}
}
},
"transparent": "Transparent"
"transparent": "Transparent",
"incomingMessages": "Incoming messages"
}

View file

@ -56,9 +56,6 @@ abstract class AppConfig {
static const String deepLinkPrefix = 'im.fluffychat://chat/';
static const String schemePrefix = 'matrix:';
static const String pushNotificationsChannelId = 'fluffychat_push';
static const String pushNotificationsChannelName = 'FluffyChat push channel';
static const String pushNotificationsChannelDescription =
'Push notifications for FluffyChat';
static const String pushNotificationsAppId = 'chat.fluffy.fluffychat';
static const String pushNotificationsGatewayUrl =
'https://push.fluffychat.im/_matrix/push/v1/notify';

View file

@ -159,9 +159,8 @@ abstract class ClientManager {
body,
const NotificationDetails(
android: AndroidNotificationDetails(
AppConfig.pushNotificationsChannelId,
AppConfig.pushNotificationsChannelName,
channelDescription: AppConfig.pushNotificationsChannelDescription,
'error_message',
'Error Messages',
importance: Importance.max,
priority: Priority.max,
fullScreenIntent: true, // To show notification popup

View file

@ -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.

View file

@ -712,6 +712,15 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
flutter_shortcuts:
dependency: "direct main"
description:
path: "."
ref: HEAD
resolved-ref: "67158a31e066265ad43463befb57c29ec2cbd77a"
url: "https://github.com/krille-chan/flutter_shortcuts.git"
source: git
version: "1.4.0"
flutter_svg:
dependency: transitive
description:

View file

@ -46,6 +46,8 @@ dependencies:
flutter_openssl_crypto: ^0.3.0
flutter_ringtone_player: ^4.0.0+2
flutter_secure_storage: ^9.0.0
flutter_shortcuts:
git: https://github.com/krille-chan/flutter_shortcuts.git
flutter_typeahead: ^4.8.0
flutter_web_auth_2: ^3.0.4
flutter_webrtc: ^0.9.46