fluffychat/lib/utils/background_push.dart
ggurdin 7d79ed4c4f
1125 merge upstream fluffychat into main (#1184)
* chore: Nicer invite selection view

* chore: Do not request thousands of users on invite page

* build(deps): bump rexml from 3.3.6 to 3.3.9 in /ios

Bumps [rexml](https://github.com/ruby/rexml) from 3.3.6 to 3.3.9.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/rexml/compare/v3.3.6...v3.3.9)

---
updated-dependencies:
- dependency-name: rexml
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* design: Highlight emoji only messages

* chore: Follow up emoji only messages

* Translated using Weblate (Galician)

Currently translated at 100.0% (672 of 672 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/

* Translated using Weblate (Russian)

Currently translated at 99.7% (670 of 672 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ru/

* design: New login design

* chore: Improve spaces design

* chore: Improve spaces design

* chore: Improved UX for creating groups and spaces

* Translated using Weblate (German)

Currently translated at 100.0% (672 of 672 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/de/

* feat: Better wallpapers with blur and opacity sliders and improved styles page

* chore: Follow up wallpaper configs

* chore: Add max length to state messages

* chore: Follow up wallpaper design

* feat: Open account manage url when using MAS

* chore: follow up wellknown fetch

* Translated using Weblate (Arabic)

Currently translated at 100.0% (674 of 674 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (674 of 674 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (674 of 674 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (674 of 674 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/

* Translated using Weblate (Finnish)

Currently translated at 79.0% (533 of 674 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fi/

* Translated using Weblate (Latvian)

Currently translated at 100.0% (674 of 674 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/lv/

* build: Add links to snapcraft.yaml file

* chore: Nicer empty page

* chore: Polish chat bubble colors

* chore: Follow up chat bubble design

* refactor: Remove unnecessary builder widget

* chore: Design adjustments

* chore: Follow up design

* refactor: Display two lines on new messages

* chore: Design follow up

* Translated using Weblate (Arabic)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/

* Translated using Weblate (German)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/de/

* Translated using Weblate (Estonian)

Currently translated at 99.7% (676 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Basque)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/

* chore: Follow up message bubbles

* chore: Follow up design

* chore: Follow up design

* chore: Follow up colors

* chore: Follow up homeserverpicker UX

* chore: Design follow up

* feat: Add about server page

* chore: Follow up update snackbar

* chore: Polish login design

* chore: Follow up login page

* chore: Follow up homeserver picker

* chore: Follow up appbar shadow

* refactor: Performance boost for avatar widget

* Revert "refactor: Performance boost for avatar widget"

This reverts commit 58577bb9e8.

* Translated using Weblate (Estonian)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/

* Translated using Weblate (Latvian)

Currently translated at 100.0% (678 of 678 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/lv/

* Translated using Weblate (Arabic)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Basque)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/

* Translated using Weblate (Galician)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/

* Translated using Weblate (Latvian)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/lv/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/

* Translated using Weblate (Korean)

Currently translated at 100.0% (687 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ko/

* chore: Follow up homeserver input field

* refactor: Move to upstream geolocator

* chore: Follow up send file dialog

* Translated using Weblate (Spanish)

Currently translated at 74.6% (513 of 687 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/es/

* refactor: Migrate to newer keyboard shortcuts package

* refactor: Remove keyboard shortcuts

This package right now
makes the web app
nearly unusable as it
throws multiple errors on
every key press. The
package seems to be
unmaintained. I tried
two other packages
and none of them worked.

* build: Update matrix dart sdk to 0.35.0

* chore: Better FluffyChat Logo for PWA

* build: (deps): bump samuelmeuli/action-snapcraft from 2 to 3

Bumps [samuelmeuli/action-snapcraft](https://github.com/samuelmeuli/action-snapcraft) from 2 to 3.
- [Release notes](https://github.com/samuelmeuli/action-snapcraft/releases)
- [Commits](https://github.com/samuelmeuli/action-snapcraft/compare/v2...v3)

---
updated-dependencies:
- dependency-name: samuelmeuli/action-snapcraft
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: Follow up send file dialog

* feat: Add markdown context actions for text input

* build: Update flutter to 3.24.5

* build: Remove snapcraft build workaround

* chore: Better error message when join room failed

* chore: Follow up join room

* chore: Make error dialog show full error

* chore: Follow up loading dialog

* chore: Follow up loading dialog

* build: Snapcraft from local build file

* chore: Follow up build snap

* chore: Follow up snapcraft in ci

* build: Revert build snapcraft changes

* build: Try downgrading flutter web auth

* chore: add hint in pubspec.yaml regarding flutter_web_auth_2

* Translated using Weblate (Estonian)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Galician)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/

* Translated using Weblate (Irish)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ga/

* Translated using Weblate (Arabic)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/

* Translated using Weblate (Basque)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/

* Translated using Weblate (Latvian)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/lv/

* Translated using Weblate (Italian)

Currently translated at 100.0% (688 of 688 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/it/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/

* Translated using Weblate (Arabic)

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/

* Translated using Weblate (Basque)

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/

* Translated using Weblate (Irish)

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ga/

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/

* Translated using Weblate (Latvian)

Currently translated at 100.0% (694 of 694 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/lv/

* Translated using Weblate (Arabic)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/

* Translated using Weblate (Estonian)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/

* Translated using Weblate (Irish)

Currently translated at 99.8% (694 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ga/

* Translated using Weblate (German)

Currently translated at 99.5% (692 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/de/

* fix: dont use thumbnails for emoticons

* chore: Improve presence performance

* Translated using Weblate (Basque)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/

* Translated using Weblate (Galician)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/

* Translated using Weblate (Italian)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/it/

* Translated using Weblate (Irish)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ga/

* Translated using Weblate (Russian)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ru/

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (695 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/

* Translated using Weblate (Catalan)

Currently translated at 95.1% (661 of 695 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ca/

* build: Bump version

* chore: Follow up send file dialog for images

* chore: Follow up send multiple images

* build: Add android build workaround for new flutter version

* build: Use file selector to save files

* chore: Follow up save file on desktop

* chore: Adjust default linux window height

* refactor: Update to new receive sharing intent package

* fluffychat merge

* fluffychat merge

* fluffychat merge

* fix android build

* fluffychat merge

* fluffychat merge

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Krille <c.kussowski@famedly.com>
Co-authored-by: Krille-chan <christian-kussowski@posteo.de>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: josé m <correoxm@disroot.org>
Co-authored-by: v1s7 <v1s7@users.noreply.hosted.weblate.org>
Co-authored-by: Christian <christian-pauly@posteo.de>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Co-authored-by: Linerly <linerly@proton.me>
Co-authored-by: Edgars Andersons <Edgars+Weblate@gaitenis.id.lv>
Co-authored-by: xabirequejo <xabi.rn@gmail.com>
Co-authored-by: Bezruchenko Simon <worcposj44@gmail.com>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Bruno Roh <kane.roh429@gmail.com>
Co-authored-by: Kimby <kimisaes@naver.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Angelo Schirinzi <muten619@hotmail.it>
Co-authored-by: Marek Vospěl <marek@vospel.cz>
Co-authored-by: Александр (Alexandr1995) <stupino19951406@gmail.com>
2024-12-09 14:17:44 -05:00

523 lines
16 KiB
Dart

/*
* Famedly
* Copyright (C) 2020, 2021 Famedly GmbH
* Copyright (C) 2021 Fluffychat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:fcm_shared_isolate/fcm_shared_isolate.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:fluffychat/pangea/constants/language_constants.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/utils/push_helper.dart';
import 'package:fluffychat/widgets/fluffy_chat_app.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_badger/flutter_app_badger.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;
import 'package:matrix/matrix.dart';
import 'package:unifiedpush/unifiedpush.dart';
import 'package:unifiedpush_ui/unifiedpush_ui.dart';
import '../config/app_config.dart';
import '../config/setting_keys.dart';
import '../widgets/matrix.dart';
import 'platform_infos.dart';
//import 'package:fcm_shared_isolate/fcm_shared_isolate.dart';
class NoTokenException implements Exception {
String get cause => 'Cannot get firebase token';
}
class BackgroundPush {
static BackgroundPush? _instance;
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Client client;
MatrixState? matrix;
String? _fcmToken;
void Function(String errorMsg, {Uri? link})? onFcmError;
L10n? l10n;
Future<void> loadLocale() async {
final context = matrix?.context;
// inspired by _lookupL10n in .dart_tool/flutter_gen/gen_l10n/l10n.dart
l10n ??= (context != null ? L10n.of(context) : null) ??
(await L10n.delegate.load(PlatformDispatcher.instance.locale));
}
final pendingTests = <String, Completer<void>>{};
// final dynamic firebase = null; //FcmSharedIsolate();
// #Pangea
// uncommented to enable notifications on IOS
final FcmSharedIsolate? firebase = FcmSharedIsolate();
// Pangea#
DateTime? lastReceivedPush;
bool upAction = false;
void _init() async {
try {
// #Pangea
onLogin ??=
client.onLoginStateChanged.stream.listen(handleLoginStateChanged);
// Pangea#
await _flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('notifications_icon'),
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: goToRoom,
);
Logs().v('Flutter Local Notifications initialized');
firebase?.setListeners(
onMessage: (message) => pushHelper(
PushNotification.fromJson(
Map<String, dynamic>.from(message['data'] ?? message),
),
client: client,
l10n: l10n,
activeRoomId: matrix?.activeRoomId,
flutterLocalNotificationsPlugin: _flutterLocalNotificationsPlugin,
),
// #Pangea
onNewToken: _newFcmToken,
// Pangea#
);
if (Platform.isAndroid) {
await UnifiedPush.initialize(
onNewEndpoint: _newUpEndpoint,
onRegistrationFailed: _upUnregistered,
onUnregistered: _upUnregistered,
onMessage: _onUpMessage,
);
}
} catch (e, s) {
Logs().e('Unable to initialize Flutter local notifications', e, s);
}
}
BackgroundPush._(this.client) {
_init();
}
factory BackgroundPush.clientOnly(Client client) {
return _instance ??= BackgroundPush._(client);
}
factory BackgroundPush(
MatrixState matrix, {
final void Function(String errorMsg, {Uri? link})? onFcmError,
}) {
final instance = BackgroundPush.clientOnly(matrix.client);
instance.matrix = matrix;
// ignore: prefer_initializing_formals
instance.onFcmError = onFcmError;
// #Pangea
instance.fullInit();
// Pangea#
return instance;
}
// #Pangea
Future<void> fullInit() => setupPush();
void handleLoginStateChanged(_) => setupPush();
StreamSubscription<LoginState>? onLogin;
void _newFcmToken(String token) {
_fcmToken = token;
debugPrint('Fcm foken $_fcmToken');
setupPush();
}
// Pangea#
Future<void> cancelNotification(String roomId) async {
Logs().v('Cancel notification for room', roomId);
await _flutterLocalNotificationsPlugin.cancel(roomId.hashCode);
// Workaround for app icon badge not updating
if (Platform.isIOS) {
final unreadCount = client.rooms
.where((room) => room.isUnreadOrInvited && room.id != roomId)
.length;
if (unreadCount == 0) {
FlutterAppBadger.removeBadge();
} else {
FlutterAppBadger.updateBadgeCount(unreadCount);
}
return;
}
}
Future<void> setupPusher({
String? gatewayUrl,
String? token,
Set<String?>? oldTokens,
bool useDeviceSpecificAppId = false,
}) async {
// #Pangea
try {
// Pangea#
if (PlatformInfos.isIOS) {
await firebase?.requestPermission();
} else if (PlatformInfos.isAndroid) {
_flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.requestNotificationsPermission();
}
// #Pangea
} catch (err, s) {
ErrorHandler.logError(
e: "Error requesting notifications permission: $err",
s: s,
);
}
// Pangea#
final clientName = PlatformInfos.clientName;
oldTokens ??= <String>{};
final pushers = await (client.getPushers().catchError((e) {
Logs().w('[Push] Unable to request pushers', e);
return <Pusher>[];
})) ??
[];
var setNewPusher = false;
// Just the plain app id, we add the .data_message suffix later
var appId = AppConfig.pushNotificationsAppId;
// we need the deviceAppId to remove potential legacy UP pusher
var deviceAppId = '$appId.${client.deviceID}';
// appId may only be up to 64 chars as per spec
if (deviceAppId.length > 64) {
deviceAppId = deviceAppId.substring(0, 64);
}
if (!useDeviceSpecificAppId && PlatformInfos.isAndroid) {
appId += '.data_message';
}
final thisAppId = useDeviceSpecificAppId ? deviceAppId : appId;
if (gatewayUrl != null && token != null) {
final currentPushers = pushers.where((pusher) => pusher.pushkey == token);
if (currentPushers.length == 1 &&
currentPushers.first.kind == 'http' &&
currentPushers.first.appId == thisAppId &&
currentPushers.first.appDisplayName == clientName &&
currentPushers.first.deviceDisplayName == client.deviceName &&
currentPushers.first.lang == 'en' &&
// #Pangea
currentPushers.first.lang == LanguageKeys.defaultLanguage &&
// Pangea#
currentPushers.first.data.url.toString() == gatewayUrl &&
currentPushers.first.data.format ==
AppConfig.pushNotificationsPusherFormat &&
mapEquals(
currentPushers.single.data.additionalProperties,
{"data_message": pusherDataMessageFormat},
)) {
Logs().i('[Push] Pusher already set');
} else {
Logs().i('Need to set new pusher');
oldTokens.add(token);
if (client.isLogged()) {
setNewPusher = true;
}
}
} else {
Logs().w('[Push] Missing required push credentials');
}
for (final pusher in pushers) {
if ((token != null &&
pusher.pushkey != token &&
deviceAppId == pusher.appId) ||
oldTokens.contains(pusher.pushkey)) {
try {
await client.deletePusher(pusher);
Logs().i('[Push] Removed legacy pusher for this device');
} catch (err) {
Logs().w('[Push] Failed to remove old pusher', err);
}
}
}
if (setNewPusher) {
try {
await client.postPusher(
Pusher(
pushkey: token!,
appId: thisAppId,
appDisplayName: clientName,
deviceDisplayName: client.deviceName!,
//#Pangea
// lang: 'en',
lang: LanguageKeys.defaultLanguage,
// Pangea#
data: PusherData(
url: Uri.parse(gatewayUrl!),
format: AppConfig.pushNotificationsPusherFormat,
additionalProperties: {"data_message": pusherDataMessageFormat},
),
kind: 'http',
),
append: false,
);
} catch (e, s) {
Logs().e('[Push] Unable to set pushers', e, s);
// #Pangea
ErrorHandler.logError(e: e, s: s);
// Pangea#
}
}
}
final pusherDataMessageFormat = Platform.isAndroid
? 'android'
: Platform.isIOS
? 'ios'
: null;
static bool _wentToRoomOnStartup = false;
Future<void> setupPush() async {
Logs().d("SetupPush");
if (client.onLoginStateChanged.value != LoginState.loggedIn ||
!PlatformInfos.isMobile ||
matrix == null) {
return;
}
// Do not setup unifiedpush if this has been initialized by
// an unifiedpush action
if (upAction) {
return;
}
if (!PlatformInfos.isIOS &&
(await UnifiedPush.getDistributors()).isNotEmpty) {
await setupUp();
} else {
await setupFirebase();
}
// ignore: unawaited_futures
_flutterLocalNotificationsPlugin
.getNotificationAppLaunchDetails()
.then((details) {
if (details == null ||
!details.didNotificationLaunchApp ||
_wentToRoomOnStartup) {
return;
}
_wentToRoomOnStartup = true;
goToRoom(details.notificationResponse);
});
}
Future<void> _noFcmWarning() async {
if (matrix == null) {
return;
}
if ((matrix?.store.getBool(SettingKeys.showNoGoogle) ?? false) == true) {
return;
}
await loadLocale();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (PlatformInfos.isAndroid) {
onFcmError?.call(
l10n!.noGoogleServicesWarning,
link: Uri.parse(
AppConfig.enablePushTutorial,
),
);
return;
}
onFcmError?.call(l10n!.oopsPushError);
});
}
Future<void> setupFirebase() async {
Logs().v('Setup firebase');
if (_fcmToken?.isEmpty ?? true) {
try {
// #Pangea
// _fcmToken = await firebase?.getToken();
_fcmToken = await _getToken();
// Pangea#
if (_fcmToken == null) throw ('PushToken is null');
} catch (e, s) {
Logs().w('[Push] cannot get token', e, e is String ? null : s);
await _noFcmWarning();
return;
}
}
await setupPusher(
gatewayUrl: AppConfig.pushNotificationsGatewayUrl,
token: _fcmToken,
);
}
Future<void> goToRoom(NotificationResponse? response) async {
try {
final roomId = response?.payload;
Logs().v('[Push] Attempting to go to room $roomId...');
if (roomId == null) {
return;
}
await client.roomsLoading;
await client.accountDataLoading;
if (client.getRoomById(roomId) == null) {
await client
.waitForRoomInSync(roomId)
.timeout(const Duration(seconds: 30));
}
FluffyChatApp.router.go(
client.getRoomById(roomId)?.membership == Membership.invite
? '/rooms'
: '/rooms/$roomId',
);
} catch (e, s) {
Logs().e('[Push] Failed to open room', e, s);
// #Pangea
ErrorHandler.logError(e: e, s: s);
// Pangea#
}
}
Future<void> setupUp() async {
await UnifiedPushUi(matrix!.context, ["default"], UPFunctions())
.registerAppWithDialog();
}
Future<void> _newUpEndpoint(String newEndpoint, String i) async {
upAction = true;
if (newEndpoint.isEmpty) {
await _upUnregistered(i);
return;
}
var endpoint =
'https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify';
try {
final url = Uri.parse(newEndpoint)
.replace(
path: '/_matrix/push/v1/notify',
query: '',
)
.toString()
.split('?')
.first;
final res =
json.decode(utf8.decode((await http.get(Uri.parse(url))).bodyBytes));
if (res['gateway'] == 'matrix' ||
(res['unifiedpush'] is Map &&
res['unifiedpush']['gateway'] == 'matrix')) {
endpoint = url;
}
} catch (e) {
Logs().i(
'[Push] No self-hosted unified push gateway present: $newEndpoint',
);
}
Logs().i('[Push] UnifiedPush using endpoint $endpoint');
final oldTokens = <String?>{};
try {
// #Pangea
// final fcmToken = await firebase?.getToken();
final fcmToken = await _getToken();
// Pangea#
oldTokens.add(fcmToken);
} catch (_) {}
await setupPusher(
gatewayUrl: endpoint,
token: newEndpoint,
oldTokens: oldTokens,
useDeviceSpecificAppId: true,
);
await matrix?.store.setString(SettingKeys.unifiedPushEndpoint, newEndpoint);
await matrix?.store.setBool(SettingKeys.unifiedPushRegistered, true);
}
Future<void> _upUnregistered(String i) async {
upAction = true;
Logs().i('[Push] Removing UnifiedPush endpoint...');
final oldEndpoint =
matrix?.store.getString(SettingKeys.unifiedPushEndpoint);
await matrix?.store.setBool(SettingKeys.unifiedPushRegistered, false);
await matrix?.store.remove(SettingKeys.unifiedPushEndpoint);
if (oldEndpoint?.isNotEmpty ?? false) {
// remove the old pusher
await setupPusher(
oldTokens: {oldEndpoint},
);
}
}
Future<void> _onUpMessage(Uint8List message, String i) async {
upAction = true;
final data = Map<String, dynamic>.from(
json.decode(utf8.decode(message))['notification'],
);
// UP may strip the devices list
data['devices'] ??= [];
await pushHelper(
PushNotification.fromJson(data),
client: client,
l10n: l10n,
activeRoomId: matrix?.activeRoomId,
flutterLocalNotificationsPlugin: _flutterLocalNotificationsPlugin,
);
}
// #Pangea
Future<String?> _getToken() async {
if (Platform.isAndroid) {
await Firebase.initializeApp(
// options: DefaultFirebaseOptions.currentPlatform,
);
return (await FirebaseMessaging.instance.getToken());
}
return await firebase?.getToken();
}
// Pangea#
}
class UPFunctions extends UnifiedPushFunctions {
final List<String> features = [/*list of features*/];
@override
Future<String?> getDistributor() async {
return await UnifiedPush.getDistributor();
}
@override
Future<List<String>> getDistributors() async {
return await UnifiedPush.getDistributors(features);
}
@override
Future<void> registerApp(String instance) async {
await UnifiedPush.registerApp(instance, features);
}
@override
Future<void> saveDistributor(String distributor) async {
await UnifiedPush.saveDistributor(distributor);
}
}