mirror of
https://github.com/krille-chan/fluffychat
synced 2024-08-11 07:53:48 +00:00
feat: Add notification shortcuts to android
This commit is contained in:
parent
aa68e8fe3b
commit
dee9323d47
6 changed files with 96 additions and 29 deletions
|
@ -2469,5 +2469,6 @@
|
||||||
"sender": {}
|
"sender": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"transparent": "Transparent"
|
"transparent": "Transparent",
|
||||||
|
"incomingMessages": "Incoming messages"
|
||||||
}
|
}
|
|
@ -56,9 +56,6 @@ abstract class AppConfig {
|
||||||
static const String deepLinkPrefix = 'im.fluffychat://chat/';
|
static const String deepLinkPrefix = 'im.fluffychat://chat/';
|
||||||
static const String schemePrefix = 'matrix:';
|
static const String schemePrefix = 'matrix:';
|
||||||
static const String pushNotificationsChannelId = 'fluffychat_push';
|
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 pushNotificationsAppId = 'chat.fluffy.fluffychat';
|
||||||
static const String pushNotificationsGatewayUrl =
|
static const String pushNotificationsGatewayUrl =
|
||||||
'https://push.fluffychat.im/_matrix/push/v1/notify';
|
'https://push.fluffychat.im/_matrix/push/v1/notify';
|
||||||
|
|
|
@ -159,9 +159,8 @@ abstract class ClientManager {
|
||||||
body,
|
body,
|
||||||
const NotificationDetails(
|
const NotificationDetails(
|
||||||
android: AndroidNotificationDetails(
|
android: AndroidNotificationDetails(
|
||||||
AppConfig.pushNotificationsChannelId,
|
'error_message',
|
||||||
AppConfig.pushNotificationsChannelName,
|
'Error Messages',
|
||||||
channelDescription: AppConfig.pushNotificationsChannelDescription,
|
|
||||||
importance: Importance.max,
|
importance: Importance.max,
|
||||||
priority: Priority.max,
|
priority: Priority.max,
|
||||||
fullScreenIntent: true, // To show notification popup
|
fullScreenIntent: true, // To show notification popup
|
||||||
|
|
|
@ -2,11 +2,13 @@ import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:flutter_shortcuts/flutter_shortcuts.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
@ -55,8 +57,7 @@ Future<void> pushHelper(
|
||||||
iOS: const DarwinNotificationDetails(),
|
iOS: const DarwinNotificationDetails(),
|
||||||
android: AndroidNotificationDetails(
|
android: AndroidNotificationDetails(
|
||||||
AppConfig.pushNotificationsChannelId,
|
AppConfig.pushNotificationsChannelId,
|
||||||
AppConfig.pushNotificationsChannelName,
|
l10n.incomingMessages,
|
||||||
channelDescription: AppConfig.pushNotificationsChannelDescription,
|
|
||||||
number: notification.counts?.unread,
|
number: notification.counts?.unread,
|
||||||
ticker: l10n.unreadChats(notification.counts?.unread ?? 1),
|
ticker: l10n.unreadChats(notification.counts?.unread ?? 1),
|
||||||
importance: Importance.max,
|
importance: Importance.max,
|
||||||
|
@ -170,34 +171,53 @@ Future<void> _tryPushHelper(
|
||||||
final avatar = event.room.avatar
|
final avatar = event.room.avatar
|
||||||
?.getThumbnail(
|
?.getThumbnail(
|
||||||
client,
|
client,
|
||||||
width: 126,
|
width: 128,
|
||||||
height: 126,
|
height: 128,
|
||||||
)
|
)
|
||||||
.toString();
|
.toString();
|
||||||
File? avatarFile;
|
final senderAvatar = event.room.isDirectChat
|
||||||
|
? avatar
|
||||||
|
: event.senderFromMemoryOrFallback.avatarUrl
|
||||||
|
?.getThumbnail(
|
||||||
|
client,
|
||||||
|
width: 128,
|
||||||
|
height: 128,
|
||||||
|
)
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
File? roomAvatarFile, senderAvatarFile;
|
||||||
try {
|
try {
|
||||||
avatarFile = avatar == null
|
roomAvatarFile = avatar == null
|
||||||
? null
|
? null
|
||||||
: await DefaultCacheManager().getSingleFile(avatar);
|
: await DefaultCacheManager().getSingleFile(avatar);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logs().e('Unable to get avatar picture', 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);
|
final id = await mapRoomIdToInt(event.room.id);
|
||||||
|
|
||||||
// Show notification
|
// 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(
|
final newMessage = Message(
|
||||||
body,
|
body,
|
||||||
event.originServerTs,
|
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
|
final messagingStyleInformation = PlatformInfos.isAndroid
|
||||||
|
@ -232,15 +252,21 @@ Future<void> _tryPushHelper(
|
||||||
?.createNotificationChannel(roomsChannel);
|
?.createNotificationChannel(roomsChannel);
|
||||||
|
|
||||||
final androidPlatformChannelSpecifics = AndroidNotificationDetails(
|
final androidPlatformChannelSpecifics = AndroidNotificationDetails(
|
||||||
event.room.id,
|
AppConfig.pushNotificationsChannelId,
|
||||||
roomName,
|
l10n.incomingMessages,
|
||||||
channelDescription: groupName,
|
|
||||||
number: notification.counts?.unread,
|
number: notification.counts?.unread,
|
||||||
category: AndroidNotificationCategory.message,
|
category: AndroidNotificationCategory.message,
|
||||||
shortcutId: event.room.id,
|
shortcutId: event.room.id,
|
||||||
styleInformation: messagingStyleInformation ??
|
styleInformation: messagingStyleInformation ??
|
||||||
MessagingStyleInformation(
|
MessagingStyleInformation(
|
||||||
person,
|
Person(
|
||||||
|
name: event.senderFromMemoryOrFallback.calcDisplayname(),
|
||||||
|
icon: roomAvatarFile == null
|
||||||
|
? null
|
||||||
|
: BitmapFilePathAndroidIcon(roomAvatarFile.path),
|
||||||
|
key: event.roomId,
|
||||||
|
important: event.room.isFavourite,
|
||||||
|
),
|
||||||
conversationTitle: roomName,
|
conversationTitle: roomName,
|
||||||
groupConversation: !event.room.isDirectChat,
|
groupConversation: !event.room.isDirectChat,
|
||||||
messages: [newMessage],
|
messages: [newMessage],
|
||||||
|
@ -257,11 +283,15 @@ Future<void> _tryPushHelper(
|
||||||
iOS: iOSPlatformChannelSpecifics,
|
iOS: iOSPlatformChannelSpecifics,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final title = event.room.getLocalizedDisplayname(MatrixLocals(l10n));
|
||||||
|
|
||||||
|
if (PlatformInfos.isAndroid) {
|
||||||
|
_setShortcut(event, l10n, title, roomAvatarFile);
|
||||||
|
}
|
||||||
|
|
||||||
await flutterLocalNotificationsPlugin.show(
|
await flutterLocalNotificationsPlugin.show(
|
||||||
id,
|
id,
|
||||||
event.room.getLocalizedDisplayname(
|
title,
|
||||||
MatrixLocals(l10n),
|
|
||||||
),
|
|
||||||
body,
|
body,
|
||||||
platformChannelSpecifics,
|
platformChannelSpecifics,
|
||||||
payload: event.roomId,
|
payload: event.roomId,
|
||||||
|
@ -269,6 +299,35 @@ Future<void> _tryPushHelper(
|
||||||
Logs().v('Push helper has been completed!');
|
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
|
/// 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
|
/// 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.
|
/// IDs we map the [roomId] to a number and store this number.
|
||||||
|
|
|
@ -712,6 +712,15 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
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:
|
flutter_svg:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -46,6 +46,8 @@ dependencies:
|
||||||
flutter_openssl_crypto: ^0.3.0
|
flutter_openssl_crypto: ^0.3.0
|
||||||
flutter_ringtone_player: ^4.0.0+2
|
flutter_ringtone_player: ^4.0.0+2
|
||||||
flutter_secure_storage: ^9.0.0
|
flutter_secure_storage: ^9.0.0
|
||||||
|
flutter_shortcuts:
|
||||||
|
git: https://github.com/krille-chan/flutter_shortcuts.git
|
||||||
flutter_typeahead: ^4.8.0
|
flutter_typeahead: ^4.8.0
|
||||||
flutter_web_auth_2: ^3.0.4
|
flutter_web_auth_2: ^3.0.4
|
||||||
flutter_webrtc: ^0.9.46
|
flutter_webrtc: ^0.9.46
|
||||||
|
|
Loading…
Reference in a new issue