mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-12-23 22:12:34 +01:00
refactor: New push
This commit is contained in:
parent
cafd9ccaa6
commit
6fe94d5910
@ -2779,5 +2779,50 @@
|
||||
"widgetName": "Name",
|
||||
"widgetUrlError": "This is not a valid URL.",
|
||||
"widgetNameError": "Please provide a display name.",
|
||||
"errorAddingWidget": "Error adding the widget."
|
||||
"errorAddingWidget": "Error adding the widget.",
|
||||
"youRejectedTheInvitation": "You rejected the invitation",
|
||||
"youJoinedTheChat": "You joined the chat",
|
||||
"youAcceptedTheInvitation": "You accepted the invitation",
|
||||
"youBannedUser": "You banned {user}",
|
||||
"@youBannedUser": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"youHaveWithdrawnTheInvitationFor": "You have withdrawn the invitation for {user}",
|
||||
"@youHaveWithdrawnTheInvitationFor": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"youInvitedBy": "You have been invited by {user}",
|
||||
"@youInvitedBy": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"youInvitedUser": "You invited {user}",
|
||||
"@youInvitedUser": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"youKicked": "You kicked {user}",
|
||||
"@youKicked": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"youKickedAndBanned": "You kicked and banned {user}",
|
||||
"@youKickedAndBanned": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"youUnbannedUser": "You unbanned {user}",
|
||||
"@youUnbannedUser": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import 'dart:ui';
|
||||
|
||||
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:http/http.dart' as http;
|
||||
@ -34,10 +33,10 @@ import 'package:unifiedpush/unifiedpush.dart';
|
||||
import 'package:vrouter/vrouter.dart';
|
||||
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
|
||||
import 'package:fluffychat/utils/push_helper.dart';
|
||||
import '../config/app_config.dart';
|
||||
import '../config/setting_keys.dart';
|
||||
import 'famedlysdk_store.dart';
|
||||
import 'matrix_sdk_extensions.dart/matrix_locals.dart';
|
||||
import 'platform_infos.dart';
|
||||
|
||||
//import 'package:fcm_shared_isolate/fcm_shared_isolate.dart';
|
||||
@ -66,6 +65,8 @@ class BackgroundPush {
|
||||
|
||||
final pendingTests = <String, Completer<void>>{};
|
||||
|
||||
final dynamic firebase = null; //FcmSharedIsolate();
|
||||
|
||||
DateTime? lastReceivedPush;
|
||||
|
||||
bool upAction = false;
|
||||
@ -76,8 +77,15 @@ class BackgroundPush {
|
||||
onRoomSync ??= client.onSync.stream
|
||||
.where((s) => s.hasRoomUpdate)
|
||||
.listen((s) => _onClearingPush(getFromServer: false));
|
||||
_fcmSharedIsolate?.setListeners(
|
||||
onMessage: _onFcmMessage,
|
||||
firebase?.setListeners(
|
||||
onMessage: (message) => pushHelper(
|
||||
PushNotification.fromJson(
|
||||
Map<String, dynamic>.from(message['data'] ?? message)),
|
||||
client: client,
|
||||
l10n: l10n,
|
||||
activeRoomId: router?.currentState?.pathParameters['roomid'],
|
||||
onSelectNotification: goToRoom,
|
||||
),
|
||||
onNewToken: _newFcmToken,
|
||||
);
|
||||
if (Platform.isAndroid) {
|
||||
@ -112,16 +120,14 @@ class BackgroundPush {
|
||||
|
||||
void handleLoginStateChanged(_) => setupPush();
|
||||
|
||||
StreamSubscription<LoginState>? onLogin;
|
||||
StreamSubscription<SyncUpdate>? onRoomSync;
|
||||
|
||||
void _newFcmToken(String token) {
|
||||
_fcmToken = token;
|
||||
setupPush();
|
||||
}
|
||||
|
||||
final dynamic _fcmSharedIsolate = null; //FcmSharedIsolate();
|
||||
|
||||
StreamSubscription<LoginState>? onLogin;
|
||||
StreamSubscription<SyncUpdate>? onRoomSync;
|
||||
|
||||
Future<void> setupPusher({
|
||||
String? gatewayUrl,
|
||||
String? token,
|
||||
@ -129,7 +135,7 @@ class BackgroundPush {
|
||||
bool useDeviceSpecificAppId = false,
|
||||
}) async {
|
||||
if (PlatformInfos.isIOS) {
|
||||
await _fcmSharedIsolate?.requestPermission();
|
||||
await firebase?.requestPermission();
|
||||
}
|
||||
final clientName = PlatformInfos.clientName;
|
||||
oldTokens ??= <String>{};
|
||||
@ -213,7 +219,6 @@ class BackgroundPush {
|
||||
|
||||
Future<void> setupPush() async {
|
||||
Logs().d("SetupPush");
|
||||
await setupLocalNotificationsPlugin();
|
||||
if (client.loginState != LoginState.loggedIn ||
|
||||
!PlatformInfos.isMobile ||
|
||||
context == null) {
|
||||
@ -272,7 +277,7 @@ class BackgroundPush {
|
||||
Logs().v('Setup firebase');
|
||||
if (_fcmToken?.isEmpty ?? true) {
|
||||
try {
|
||||
_fcmToken = await _fcmSharedIsolate?.getToken();
|
||||
_fcmToken = await firebase?.getToken();
|
||||
if (_fcmToken == null) throw ('PushToken is null');
|
||||
} catch (e, s) {
|
||||
Logs().w('[Push] cannot get token', e, e is String ? null : s);
|
||||
@ -306,43 +311,10 @@ class BackgroundPush {
|
||||
}
|
||||
}
|
||||
|
||||
bool _notificationsPluginSetUp = false;
|
||||
Future<void> setupLocalNotificationsPlugin() async {
|
||||
if (_notificationsPluginSetUp) {
|
||||
return;
|
||||
}
|
||||
|
||||
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
|
||||
const initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('notifications_icon');
|
||||
final initializationSettingsIOS = IOSInitializationSettings(
|
||||
onDidReceiveLocalNotification: (i, a, b, c) async => null,
|
||||
);
|
||||
final initializationSettings = InitializationSettings(
|
||||
android: initializationSettingsAndroid,
|
||||
iOS: initializationSettingsIOS,
|
||||
);
|
||||
await _flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
||||
onSelectNotification: goToRoom);
|
||||
|
||||
_notificationsPluginSetUp = true;
|
||||
}
|
||||
|
||||
Future<void> setupUp() async {
|
||||
await UnifiedPush.registerAppWithDialog(context!);
|
||||
}
|
||||
|
||||
Future<void> _onFcmMessage(Map<dynamic, dynamic> message) async {
|
||||
Logs().v('[Push] Foreground message received');
|
||||
final data = Map<String, dynamic>.from(message['data'] ?? message);
|
||||
try {
|
||||
await _onMessage(data);
|
||||
} catch (e, s) {
|
||||
Logs().e('[Push] Error while processing notification', e, s);
|
||||
await _showDefaultNotification(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _newUpEndpoint(String newEndpoint, String i) async {
|
||||
upAction = true;
|
||||
if (newEndpoint.isEmpty) {
|
||||
@ -374,7 +346,7 @@ class BackgroundPush {
|
||||
Logs().i('[Push] UnifiedPush using endpoint ' + endpoint);
|
||||
final oldTokens = <String?>{};
|
||||
try {
|
||||
final fcmToken = await _fcmSharedIsolate?.getToken();
|
||||
final fcmToken = await firebase?.getToken();
|
||||
oldTokens.add(fcmToken);
|
||||
} catch (_) {}
|
||||
await setupPusher(
|
||||
@ -405,80 +377,12 @@ class BackgroundPush {
|
||||
upAction = true;
|
||||
final data = Map<String, dynamic>.from(
|
||||
json.decode(utf8.decode(message))['notification']);
|
||||
try {
|
||||
await _onMessage(data);
|
||||
} catch (e, s) {
|
||||
Logs().e('[Push] Error while processing notification', e, s);
|
||||
await _showDefaultNotification(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onMessage(Map<String, dynamic> data) async {
|
||||
Logs().v('[Push] _onMessage');
|
||||
lastReceivedPush = DateTime.now();
|
||||
final roomId = data['room_id'];
|
||||
final eventId = data['event_id'];
|
||||
if (roomId == 'test') {
|
||||
Logs().v('[Push] Test $eventId was successful!');
|
||||
pendingTests.remove(eventId)?.complete();
|
||||
return;
|
||||
}
|
||||
|
||||
// For legacy reasons the counts map could be a String encoded JSON:
|
||||
final countsMap =
|
||||
data.tryGetMap<String, dynamic>('counts', TryGet.silent) ??
|
||||
(jsonDecode(data.tryGet<String>('counts') ?? '{}')
|
||||
as Map<String, dynamic>);
|
||||
final unread = countsMap.tryGet<int>('unread');
|
||||
|
||||
if ((roomId?.isEmpty ?? true) ||
|
||||
(eventId?.isEmpty ?? true) ||
|
||||
unread == 0) {
|
||||
await _onClearingPush();
|
||||
return;
|
||||
}
|
||||
var giveUp = false;
|
||||
var loaded = false;
|
||||
final stopwatch = Stopwatch();
|
||||
stopwatch.start();
|
||||
final syncSubscription = client.onSync.stream.listen((r) {
|
||||
if (stopwatch.elapsed.inSeconds >= 30) {
|
||||
giveUp = true;
|
||||
}
|
||||
});
|
||||
final eventSubscription = client.onEvent.stream.listen((e) {
|
||||
if (e.content['event_id'] == eventId) {
|
||||
loaded = true;
|
||||
}
|
||||
});
|
||||
try {
|
||||
if (!(await eventExists(roomId, eventId)) && !loaded) {
|
||||
do {
|
||||
Logs().v('[Push] getting ' + roomId + ', event ' + eventId);
|
||||
await client
|
||||
.oneShotSync()
|
||||
.catchError((e) => Logs().v('[Push] Error one-shot syncing', e));
|
||||
if (stopwatch.elapsed.inSeconds >= 60) {
|
||||
giveUp = true;
|
||||
}
|
||||
} while (!loaded && !giveUp);
|
||||
}
|
||||
Logs().v('[Push] ' +
|
||||
(giveUp ? 'gave up on ' : 'got ') +
|
||||
roomId +
|
||||
', event ' +
|
||||
eventId);
|
||||
} finally {
|
||||
await syncSubscription.cancel();
|
||||
await eventSubscription.cancel();
|
||||
}
|
||||
await _showNotification(roomId, eventId);
|
||||
}
|
||||
|
||||
Future<bool> eventExists(String roomId, String? eventId) async {
|
||||
final room = client.getRoomById(roomId);
|
||||
if (room == null) return false;
|
||||
return (await client.database!.getEventById(eventId!, room)) != null;
|
||||
await pushHelper(
|
||||
PushNotification.fromJson(data),
|
||||
client: client,
|
||||
l10n: l10n,
|
||||
activeRoomId: router?.currentState?.pathParameters['roomid'],
|
||||
);
|
||||
}
|
||||
|
||||
/// Workaround for the problem that local notification IDs must be int but we
|
||||
@ -584,139 +488,4 @@ class BackgroundPush {
|
||||
_clearingPushLock = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showNotification(String roomId, String eventId) async {
|
||||
await setupLocalNotificationsPlugin();
|
||||
final room = client.getRoomById(roomId);
|
||||
if (room == null) {
|
||||
throw 'Room not found';
|
||||
}
|
||||
await room.postLoad();
|
||||
final event = await client.database!.getEventById(eventId, room);
|
||||
|
||||
final activeRoomId = router!.currentState!.pathParameters['roomid'];
|
||||
|
||||
if (((activeRoomId?.isNotEmpty ?? false) &&
|
||||
activeRoomId == room.id &&
|
||||
client.syncPresence == null) ||
|
||||
(event != null && (room.notificationCount == 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load the locale
|
||||
await loadLocale();
|
||||
|
||||
// Calculate title
|
||||
final title = l10n!.unreadMessages(room.notificationCount);
|
||||
|
||||
// Calculate the body
|
||||
final body = event!.getLocalizedBody(
|
||||
MatrixLocals(L10n.of(context!)!),
|
||||
withSenderNamePrefix: !room.isDirectChat,
|
||||
plaintextBody: true,
|
||||
hideReply: true,
|
||||
hideEdit: true,
|
||||
);
|
||||
|
||||
// The person object for the android message style notification
|
||||
final avatar = room.avatar == null
|
||||
? null
|
||||
: await DefaultCacheManager().getSingleFile(
|
||||
event.room.avatar!
|
||||
.getThumbnail(
|
||||
client,
|
||||
width: 126,
|
||||
height: 126,
|
||||
)
|
||||
.toString(),
|
||||
);
|
||||
final person = Person(
|
||||
name: room.getLocalizedDisplayname(MatrixLocals(l10n!)),
|
||||
icon: avatar == null ? null : BitmapFilePathAndroidIcon(avatar.path),
|
||||
);
|
||||
|
||||
// Show notification
|
||||
final androidPlatformChannelSpecifics = _getAndroidNotificationDetails(
|
||||
styleInformation: MessagingStyleInformation(
|
||||
person,
|
||||
conversationTitle: title,
|
||||
messages: [
|
||||
Message(
|
||||
body,
|
||||
event.originServerTs,
|
||||
person,
|
||||
)
|
||||
],
|
||||
),
|
||||
ticker: l10n!.newMessageInFluffyChat,
|
||||
);
|
||||
const iOSPlatformChannelSpecifics = IOSNotificationDetails();
|
||||
final platformChannelSpecifics = NotificationDetails(
|
||||
android: androidPlatformChannelSpecifics,
|
||||
iOS: iOSPlatformChannelSpecifics,
|
||||
);
|
||||
await _flutterLocalNotificationsPlugin.show(
|
||||
await mapRoomIdToInt(room.id),
|
||||
room.getLocalizedDisplayname(MatrixLocals(l10n!)),
|
||||
body,
|
||||
platformChannelSpecifics,
|
||||
payload: roomId,
|
||||
);
|
||||
}
|
||||
|
||||
Future<dynamic> _showDefaultNotification(Map<String, dynamic> data) async {
|
||||
try {
|
||||
await setupLocalNotificationsPlugin();
|
||||
|
||||
await loadLocale();
|
||||
final String? eventId = data['event_id'];
|
||||
final String? roomId = data['room_id'];
|
||||
|
||||
// For legacy reasons the counts map could be a String encoded JSON:
|
||||
final countsMap = data.tryGetMap<String, dynamic>('counts') ??
|
||||
(jsonDecode(data.tryGet<String>('counts') ?? '{}')
|
||||
as Map<String, dynamic>);
|
||||
final unread = countsMap.tryGet<int>('unread') ?? 1;
|
||||
|
||||
if (unread == 0 || roomId == null || eventId == null) {
|
||||
await _onClearingPush();
|
||||
return;
|
||||
}
|
||||
|
||||
// Display notification
|
||||
final androidPlatformChannelSpecifics = _getAndroidNotificationDetails();
|
||||
const iOSPlatformChannelSpecifics = IOSNotificationDetails();
|
||||
final platformChannelSpecifics = NotificationDetails(
|
||||
android: androidPlatformChannelSpecifics,
|
||||
iOS: iOSPlatformChannelSpecifics,
|
||||
);
|
||||
final title = l10n!.unreadChats(unread);
|
||||
await _flutterLocalNotificationsPlugin.show(
|
||||
await mapRoomIdToInt(roomId),
|
||||
title,
|
||||
l10n!.openAppToReadMessages,
|
||||
platformChannelSpecifics,
|
||||
payload: roomId,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().e('[Push] Error while processing background notification', e, s);
|
||||
}
|
||||
}
|
||||
|
||||
AndroidNotificationDetails _getAndroidNotificationDetails(
|
||||
{MessagingStyleInformation? styleInformation, String? ticker}) {
|
||||
final color = (context != null ? Theme.of(context!).primaryColor : null) ??
|
||||
const Color(0xFF5625BA);
|
||||
|
||||
return AndroidNotificationDetails(
|
||||
AppConfig.pushNotificationsChannelId,
|
||||
AppConfig.pushNotificationsChannelName,
|
||||
AppConfig.pushNotificationsChannelDescription,
|
||||
styleInformation: styleInformation,
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
ticker: ticker,
|
||||
color: color,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import 'matrix_sdk_extensions.dart/flutter_matrix_hive_database.dart';
|
||||
|
||||
abstract class ClientManager {
|
||||
static const String clientNamespace = 'im.fluffychat.store.clients';
|
||||
static Future<List<Client>> getClients() async {
|
||||
static Future<List<Client>> getClients({bool initialize = true}) async {
|
||||
if (PlatformInfos.isLinux) {
|
||||
Hive.init((await getApplicationSupportDirectory()).path);
|
||||
} else {
|
||||
@ -37,12 +37,15 @@ abstract class ClientManager {
|
||||
await Store().setItem(clientNamespace, jsonEncode(clientNames.toList()));
|
||||
}
|
||||
final clients = clientNames.map(createClient).toList();
|
||||
await Future.wait(clients.map((client) => client
|
||||
.init(
|
||||
waitForFirstSync: false,
|
||||
waitUntilLoadCompletedLoaded: false,
|
||||
)
|
||||
.catchError((e, s) => Logs().e('Unable to initialize client', e, s))));
|
||||
if (initialize) {
|
||||
await Future.wait(clients.map((client) => client
|
||||
.init(
|
||||
waitForFirstSync: false,
|
||||
waitUntilLoadCompletedLoaded: false,
|
||||
)
|
||||
.catchError(
|
||||
(e, s) => Logs().e('Unable to initialize client', e, s))));
|
||||
}
|
||||
if (clients.length > 1 && clients.any((c) => !c.isLogged())) {
|
||||
final loggedOutClients = clients.where((c) => !c.isLogged()).toList();
|
||||
for (final client in loggedOutClients) {
|
||||
|
@ -265,4 +265,39 @@ class MatrixLocals extends MatrixLocalizations {
|
||||
@override
|
||||
String sentReaction(String senderName, String reactionKey) =>
|
||||
l10n.reactedWith(senderName, reactionKey);
|
||||
|
||||
@override
|
||||
// TODO: implement youAcceptedTheInvitation
|
||||
String get youAcceptedTheInvitation => l10n.youAcceptedTheInvitation;
|
||||
|
||||
@override
|
||||
String youBannedUser(String targetName) => l10n.youBannedUser(targetName);
|
||||
|
||||
@override
|
||||
String youHaveWithdrawnTheInvitationFor(String targetName) =>
|
||||
l10n.youHaveWithdrawnTheInvitationFor(targetName);
|
||||
|
||||
@override
|
||||
String youInvitedBy(String senderName) => l10n.youInvitedBy(senderName);
|
||||
|
||||
@override
|
||||
String youInvitedUser(String targetName) => l10n.youInvitedUser(targetName);
|
||||
|
||||
@override
|
||||
// TODO: implement youJoinedTheChat
|
||||
String get youJoinedTheChat => l10n.youJoinedTheChat;
|
||||
|
||||
@override
|
||||
String youKicked(String targetName) => l10n.youKicked(targetName);
|
||||
|
||||
@override
|
||||
String youKickedAndBanned(String targetName) =>
|
||||
l10n.youKickedAndBanned(targetName);
|
||||
|
||||
@override
|
||||
// TODO: implement youRejectedTheInvitation
|
||||
String get youRejectedTheInvitation => l10n.youRejectedTheInvitation;
|
||||
|
||||
@override
|
||||
String youUnbannedUser(String targetName) => l10n.youUnbannedUser(targetName);
|
||||
}
|
||||
|
146
lib/utils/push_helper.dart
Normal file
146
lib/utils/push_helper.dart
Normal file
@ -0,0 +1,146 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/utils/client_manager.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart';
|
||||
|
||||
Future<void> pushHelper(
|
||||
PushNotification notification, {
|
||||
Client? client,
|
||||
L10n? l10n,
|
||||
String? activeRoomId,
|
||||
Future<dynamic> Function(String?)? onSelectNotification,
|
||||
}) async {
|
||||
final isBackgroundMessage = client == null;
|
||||
Logs().v(
|
||||
'Push helper has been started (background=$isBackgroundMessage).',
|
||||
notification.toJson(),
|
||||
);
|
||||
|
||||
if (!isBackgroundMessage &&
|
||||
activeRoomId == notification.roomId &&
|
||||
activeRoomId != null &&
|
||||
client?.syncPresence == null) {
|
||||
Logs().v('Room is in foreground. Stop push helper here.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
|
||||
final _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
await _flutterLocalNotificationsPlugin.initialize(
|
||||
InitializationSettings(
|
||||
android: const AndroidInitializationSettings('notifications_icon'),
|
||||
iOS: IOSInitializationSettings(
|
||||
onDidReceiveLocalNotification: (i, a, b, c) async => null,
|
||||
),
|
||||
),
|
||||
onSelectNotification: onSelectNotification,
|
||||
);
|
||||
|
||||
client ??= (await ClientManager.getClients(initialize: false)).first;
|
||||
final event = await client.getEventByPushNotification(
|
||||
notification,
|
||||
storeInDatabase: isBackgroundMessage,
|
||||
);
|
||||
|
||||
if (event == null) {
|
||||
Logs().v('Notification is a clearing indicator.');
|
||||
await _flutterLocalNotificationsPlugin.cancelAll();
|
||||
final store = await SharedPreferences.getInstance();
|
||||
await store.setString(SettingKeys.notificationCurrentIds, json.encode({}));
|
||||
return;
|
||||
}
|
||||
Logs().v('Push helper got notification event.');
|
||||
|
||||
l10n ??= await L10n.delegate.load(window.locale);
|
||||
final matrixLocals = MatrixLocals(l10n);
|
||||
|
||||
// Display notification// Calculate title
|
||||
final title = l10n.unreadMessages(notification.counts?.unread ?? 1);
|
||||
|
||||
// Calculate the body
|
||||
final body = event.getLocalizedBody(
|
||||
matrixLocals,
|
||||
plaintextBody: true,
|
||||
hideReply: true,
|
||||
hideEdit: true,
|
||||
removeMarkdown: true,
|
||||
);
|
||||
|
||||
// The person object for the android message style notification
|
||||
if (isBackgroundMessage) WidgetsFlutterBinding.ensureInitialized();
|
||||
final avatar = event.room.avatar?.toString();
|
||||
final person = Person(
|
||||
name: event.room.getLocalizedDisplayname(matrixLocals),
|
||||
icon: avatar == null ? null : ContentUriAndroidIcon(avatar),
|
||||
);
|
||||
|
||||
// Show notification
|
||||
final androidPlatformChannelSpecifics = AndroidNotificationDetails(
|
||||
AppConfig.pushNotificationsChannelId,
|
||||
AppConfig.pushNotificationsChannelName,
|
||||
AppConfig.pushNotificationsChannelDescription,
|
||||
styleInformation: MessagingStyleInformation(
|
||||
person,
|
||||
conversationTitle: title,
|
||||
groupConversation: !event.room.isDirectChat,
|
||||
messages: [
|
||||
Message(
|
||||
body,
|
||||
event.originServerTs,
|
||||
person,
|
||||
)
|
||||
],
|
||||
),
|
||||
ticker: l10n.newMessageInFluffyChat,
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
);
|
||||
const iOSPlatformChannelSpecifics = IOSNotificationDetails();
|
||||
final platformChannelSpecifics = NotificationDetails(
|
||||
android: androidPlatformChannelSpecifics,
|
||||
iOS: iOSPlatformChannelSpecifics,
|
||||
);
|
||||
await _flutterLocalNotificationsPlugin.show(
|
||||
await mapRoomIdToInt(event.room.id),
|
||||
event.room.displayname,
|
||||
body,
|
||||
platformChannelSpecifics,
|
||||
payload: event.roomId,
|
||||
);
|
||||
Logs().v('Push helper has been completed!');
|
||||
}
|
||||
|
||||
/// 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.
|
||||
Future<int> mapRoomIdToInt(String roomId) async {
|
||||
final store = await SharedPreferences.getInstance();
|
||||
final idMap = Map<String, int>.from(jsonDecode(
|
||||
(store.getString(SettingKeys.notificationCurrentIds)) ?? '{}'));
|
||||
int? currentInt;
|
||||
try {
|
||||
currentInt = idMap[roomId];
|
||||
} catch (_) {
|
||||
currentInt = null;
|
||||
}
|
||||
if (currentInt != null) {
|
||||
return currentInt;
|
||||
}
|
||||
var nCurrentInt = 0;
|
||||
while (idMap.values.contains(currentInt)) {
|
||||
nCurrentInt++;
|
||||
}
|
||||
idMap[roomId] = nCurrentInt;
|
||||
await store.setString(SettingKeys.notificationCurrentIds, json.encode(idMap));
|
||||
return nCurrentInt;
|
||||
}
|
@ -983,7 +983,7 @@ packages:
|
||||
name: matrix
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.18"
|
||||
version: "0.8.19"
|
||||
matrix_api_lite:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -24,8 +24,7 @@ dependencies:
|
||||
email_validator: ^2.0.1
|
||||
emoji_picker_flutter: ^1.1.2
|
||||
encrypt: ^5.0.1
|
||||
#fcm_shared_isolate:
|
||||
# git: https://gitlab.com/famedly/libraries/fcm_shared_isolate.git
|
||||
#fcm_shared_isolate: ^0.1.0
|
||||
file_picker_cross: ^4.5.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
@ -58,7 +57,7 @@ dependencies:
|
||||
keyboard_shortcuts: ^0.1.4
|
||||
localstorage: ^4.0.0+1
|
||||
lottie: ^1.2.2
|
||||
matrix: ^0.8.18
|
||||
matrix: ^0.8.19
|
||||
matrix_link_text: ^1.0.2
|
||||
open_noti_settings: ^0.4.0
|
||||
package_info_plus: ^1.3.0
|
||||
|
@ -1,5 +1,5 @@
|
||||
diff --git a/android/app/build.gradle b/android/app/build.gradle
|
||||
index 4e018b38..eebf7582 100644
|
||||
index ad9ffb87..37baafb1 100644
|
||||
--- a/android/app/build.gradle
|
||||
+++ b/android/app/build.gradle
|
||||
@@ -44,7 +44,7 @@ android {
|
||||
@ -11,7 +11,7 @@ index 4e018b38..eebf7582 100644
|
||||
targetSdkVersion 30
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
@@ -81,7 +81,7 @@ flutter {
|
||||
@@ -82,11 +82,11 @@ flutter {
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
@ -20,7 +20,6 @@ index 4e018b38..eebf7582 100644
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
@@ -89,4 +89,4 @@ dependencies {
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
}
|
||||
|
||||
@ -56,11 +55,11 @@ index 85aa8647..3b7e09e7 100644
|
||||
}
|
||||
|
||||
diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart
|
||||
index 3347f176..e304abb4 100644
|
||||
index 00ca2aaa..8bb8a156 100644
|
||||
--- a/lib/utils/background_push.dart
|
||||
+++ b/lib/utils/background_push.dart
|
||||
@@ -39,7 +39,7 @@ import 'famedlysdk_store.dart';
|
||||
import 'matrix_sdk_extensions.dart/matrix_locals.dart';
|
||||
@@ -39,7 +39,7 @@ import '../config/setting_keys.dart';
|
||||
import 'famedlysdk_store.dart';
|
||||
import 'platform_infos.dart';
|
||||
|
||||
-//import 'package:fcm_shared_isolate/fcm_shared_isolate.dart';
|
||||
@ -68,28 +67,25 @@ index 3347f176..e304abb4 100644
|
||||
|
||||
class NoTokenException implements Exception {
|
||||
String get cause => 'Cannot get firebase token';
|
||||
@@ -117,7 +117,7 @@ class BackgroundPush {
|
||||
setupPush();
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class BackgroundPush {
|
||||
|
||||
- final dynamic _fcmSharedIsolate = null; //FcmSharedIsolate();
|
||||
+ final dynamic _fcmSharedIsolate = FcmSharedIsolate();
|
||||
final pendingTests = <String, Completer<void>>{};
|
||||
|
||||
- final dynamic firebase = null; //FcmSharedIsolate();
|
||||
+ final dynamic firebase = FcmSharedIsolate();
|
||||
|
||||
DateTime? lastReceivedPush;
|
||||
|
||||
StreamSubscription<LoginState>? onLogin;
|
||||
StreamSubscription<SyncUpdate>? onRoomSync;
|
||||
diff --git a/pubspec.yaml b/pubspec.yaml
|
||||
index 73b9eca2..5e6f9f16 100644
|
||||
index c6295788..8dd17ce4 100644
|
||||
--- a/pubspec.yaml
|
||||
+++ b/pubspec.yaml
|
||||
@@ -25,8 +25,8 @@ dependencies:
|
||||
@@ -24,7 +24,7 @@ dependencies:
|
||||
email_validator: ^2.0.1
|
||||
emoji_picker_flutter: ^1.1.2
|
||||
encrypt: ^5.0.1
|
||||
- #fcm_shared_isolate:
|
||||
- # git: https://gitlab.com/famedly/libraries/fcm_shared_isolate.git
|
||||
+ fcm_shared_isolate:
|
||||
+ git: https://gitlab.com/famedly/libraries/fcm_shared_isolate.git
|
||||
- #fcm_shared_isolate: ^0.1.0
|
||||
+ fcm_shared_isolate: ^0.1.0
|
||||
file_picker_cross: ^4.5.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
Loading…
Reference in New Issue
Block a user