2022-02-02 20:18:08 +00:00
|
|
|
import 'dart:async';
|
2022-02-18 23:50:34 +00:00
|
|
|
import 'dart:convert';
|
2022-01-25 00:03:46 +00:00
|
|
|
import 'dart:io';
|
|
|
|
|
2022-01-26 16:31:07 +00:00
|
|
|
import 'package:cwtch/main.dart';
|
2022-04-15 00:02:08 +00:00
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
import 'package:flutter/widgets.dart';
|
2022-02-02 20:18:08 +00:00
|
|
|
import 'package:win_toast/win_toast.dart';
|
2022-04-15 00:02:08 +00:00
|
|
|
import 'package:desktop_notifications/desktop_notifications.dart' as linux_notifications;
|
2022-02-18 23:50:34 +00:00
|
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
2022-02-23 19:13:03 +00:00
|
|
|
import 'package:flutter_local_notifications_linux/flutter_local_notifications_linux.dart';
|
|
|
|
import 'package:flutter_local_notifications_linux/src/model/hint.dart';
|
2022-06-10 21:03:15 +00:00
|
|
|
import 'package:flutter_local_notifications_linux/src/model/icon.dart';
|
|
|
|
|
2021-06-24 23:10:45 +00:00
|
|
|
import 'package:path/path.dart' as path;
|
|
|
|
|
2022-01-25 00:03:46 +00:00
|
|
|
import 'config.dart';
|
|
|
|
|
2021-06-24 23:10:45 +00:00
|
|
|
// NotificationsManager provides a wrapper around platform specific notifications logic.
|
|
|
|
abstract class NotificationsManager {
|
2022-02-18 23:50:34 +00:00
|
|
|
Future<void> notify(String message, String profile, int conversationId);
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NullNotificationsManager ignores all notification requests
|
|
|
|
class NullNotificationsManager implements NotificationsManager {
|
|
|
|
@override
|
2022-02-18 23:50:34 +00:00
|
|
|
Future<void> notify(String message, String profile, int conversationId) async {}
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
2021-06-28 21:32:26 +00:00
|
|
|
|
2022-01-25 00:03:46 +00:00
|
|
|
// Windows Notification Manager uses https://pub.dev/packages/desktoasts to implement
|
|
|
|
// windows notifications
|
|
|
|
class WindowsNotificationManager implements NotificationsManager {
|
2022-01-26 16:31:07 +00:00
|
|
|
bool active = false;
|
2022-02-02 20:18:08 +00:00
|
|
|
bool initialized = false;
|
2022-01-25 00:03:46 +00:00
|
|
|
|
|
|
|
WindowsNotificationManager() {
|
2022-02-02 20:18:08 +00:00
|
|
|
scheduleMicrotask(() async {
|
2022-02-03 21:58:51 +00:00
|
|
|
initialized = await WinToast.instance().initialize(appName: 'cwtch', productName: 'Cwtch', companyName: 'Open Privacy Research Society');
|
2022-01-26 16:31:07 +00:00
|
|
|
});
|
2022-01-25 00:03:46 +00:00
|
|
|
}
|
|
|
|
|
2022-02-18 23:50:34 +00:00
|
|
|
Future<void> notify(String message, String profile, int conversationId) async {
|
2022-02-02 20:18:08 +00:00
|
|
|
if (initialized && !globalAppState.focus) {
|
2022-01-26 16:31:07 +00:00
|
|
|
if (!active) {
|
|
|
|
active = true;
|
2022-02-03 21:58:51 +00:00
|
|
|
WinToast.instance().clear();
|
|
|
|
final toast = await WinToast.instance().showToast(type: ToastType.text01, title: message);
|
2022-02-02 20:18:08 +00:00
|
|
|
toast?.eventStream.listen((event) {
|
|
|
|
if (event is ActivatedEvent) {
|
|
|
|
WinToast.instance().bringWindowToFront();
|
|
|
|
}
|
|
|
|
active = false;
|
|
|
|
});
|
2022-01-26 16:31:07 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-25 00:03:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-18 23:50:34 +00:00
|
|
|
class NotificationPayload {
|
|
|
|
late String profileOnion;
|
|
|
|
late int convoId;
|
|
|
|
|
|
|
|
NotificationPayload(String po, int cid) {
|
|
|
|
profileOnion = po;
|
|
|
|
convoId = cid;
|
|
|
|
}
|
|
|
|
|
|
|
|
NotificationPayload.fromJson(Map<String, dynamic> json)
|
|
|
|
: profileOnion = json['profileOnion'],
|
|
|
|
convoId = json['convoId'];
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() => {
|
2022-04-26 19:16:09 +00:00
|
|
|
'profileOnion': profileOnion,
|
|
|
|
'convoId': convoId,
|
|
|
|
};
|
2022-02-18 23:50:34 +00:00
|
|
|
}
|
|
|
|
|
2022-12-11 17:08:28 +00:00
|
|
|
// FlutterLocalNotificationsPlugin based NotificationManager that handles MacOS <s>and Linux</s>
|
|
|
|
// TODO: Upgrade from 9.6 to 12.x but there are breaking changes (including for mac)
|
2022-06-20 23:10:46 +00:00
|
|
|
// TODO: Windows support is being worked on, check back and migrate to that too when it lands
|
2022-02-18 23:50:34 +00:00
|
|
|
class NixNotificationManager implements NotificationsManager {
|
|
|
|
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
|
|
|
late Future<void> Function(String, int) notificationSelectConvo;
|
2022-06-10 21:03:15 +00:00
|
|
|
late String linuxAssetsPath;
|
|
|
|
|
|
|
|
// Cwtch can install in non flutter supported ways on linux, this code detects where the assets are on Linux
|
|
|
|
Future<String> detectLinuxAssetsPath() async {
|
2022-06-20 23:10:46 +00:00
|
|
|
var devStat = FileStat.stat("assets");
|
|
|
|
var localStat = FileStat.stat("data/flutter_assets");
|
2022-06-10 21:03:15 +00:00
|
|
|
var homeStat = FileStat.stat((Platform.environment["HOME"] ?? "") + "/.local/share/cwtch/data/flutter_assets");
|
|
|
|
var rootStat = FileStat.stat("/usr/share/cwtch/data/flutter_assets");
|
|
|
|
|
2022-06-20 23:10:46 +00:00
|
|
|
if ((await devStat).type == FileSystemEntityType.directory) {
|
2022-06-10 21:03:15 +00:00
|
|
|
return Directory.current.path; //appPath;
|
|
|
|
} else if ((await localStat).type == FileSystemEntityType.directory) {
|
|
|
|
return path.join(Directory.current.path, "data/flutter_assets/");
|
2022-06-20 23:10:46 +00:00
|
|
|
} else if ((await homeStat).type == FileSystemEntityType.directory) {
|
2022-06-10 21:03:15 +00:00
|
|
|
return (Platform.environment["HOME"] ?? "") + "/.local/share/cwtch/data/flutter_assets/";
|
|
|
|
} else if ((await rootStat).type == FileSystemEntityType.directory) {
|
|
|
|
return "/usr/share/cwtch/data/flutter_assets/";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2022-02-18 23:50:34 +00:00
|
|
|
|
|
|
|
NixNotificationManager(Future<void> Function(String, int) notificationSelectConvo) {
|
|
|
|
this.notificationSelectConvo = notificationSelectConvo;
|
|
|
|
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
2022-04-15 00:02:08 +00:00
|
|
|
|
2022-02-18 23:50:34 +00:00
|
|
|
scheduleMicrotask(() async {
|
2022-06-10 21:03:15 +00:00
|
|
|
if (Platform.isLinux) {
|
|
|
|
linuxAssetsPath = await detectLinuxAssetsPath();
|
|
|
|
} else {
|
|
|
|
linuxAssetsPath = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
final MacOSInitializationSettings initializationSettingsMacOS = MacOSInitializationSettings(defaultPresentSound: false);
|
2022-06-21 21:58:09 +00:00
|
|
|
var linuxIcon = FilePathLinuxIcon(path.join(linuxAssetsPath, 'assets/knott.png'));
|
2022-06-10 21:03:15 +00:00
|
|
|
|
2022-06-21 21:58:09 +00:00
|
|
|
final LinuxInitializationSettings initializationSettingsLinux = LinuxInitializationSettings(defaultActionName: 'Open notification', defaultIcon: linuxIcon, defaultSuppressSound: true);
|
2022-06-10 21:03:15 +00:00
|
|
|
|
|
|
|
final InitializationSettings initializationSettings = InitializationSettings(android: null, iOS: null, macOS: initializationSettingsMacOS, linux: initializationSettingsLinux);
|
|
|
|
|
2022-04-15 00:02:08 +00:00
|
|
|
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<MacOSFlutterLocalNotificationsPlugin>()?.requestPermissions(
|
2022-04-26 19:16:09 +00:00
|
|
|
alert: true,
|
|
|
|
badge: false,
|
|
|
|
sound: false,
|
|
|
|
);
|
2022-04-15 00:02:08 +00:00
|
|
|
|
2022-02-18 23:50:34 +00:00
|
|
|
await flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: selectNotification);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-02-23 19:13:03 +00:00
|
|
|
Future<void> notify(String message, String profile, int conversationId) async {
|
2022-02-23 19:27:15 +00:00
|
|
|
if (!globalAppState.focus) {
|
|
|
|
// Warning: Only use title field on Linux, body field will render links as clickable
|
2022-06-21 21:58:09 +00:00
|
|
|
await flutterLocalNotificationsPlugin.show(
|
|
|
|
0,
|
|
|
|
message,
|
|
|
|
'',
|
|
|
|
NotificationDetails(
|
|
|
|
linux: LinuxNotificationDetails(suppressSound: true, category: LinuxNotificationCategory.imReceived(), icon: FilePathLinuxIcon(path.join(linuxAssetsPath, 'assets/knott.png')))),
|
2022-02-23 19:27:15 +00:00
|
|
|
payload: jsonEncode(NotificationPayload(profile, conversationId)));
|
|
|
|
}
|
2022-02-23 19:13:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Notification click response function, triggers ui jump to conversation
|
2022-02-18 23:50:34 +00:00
|
|
|
void selectNotification(String? payloadJson) async {
|
|
|
|
if (payloadJson != null) {
|
|
|
|
Map<String, dynamic> payloadMap = jsonDecode(payloadJson);
|
2022-02-23 19:13:03 +00:00
|
|
|
var payload = NotificationPayload.fromJson(payloadMap);
|
2022-02-18 23:50:34 +00:00
|
|
|
notificationSelectConvo(payload.profileOnion, payload.convoId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NotificationsManager newDesktopNotificationsManager(Future<void> Function(String profileOnion, int convoId) notificationSelectConvo) {
|
2023-02-01 22:48:36 +00:00
|
|
|
|
|
|
|
// We don't want notifications in Dev Mode
|
|
|
|
if (EnvironmentConfig.TEST_MODE) {
|
|
|
|
return NullNotificationsManager();
|
|
|
|
}
|
|
|
|
|
2022-04-15 00:02:08 +00:00
|
|
|
if (Platform.isLinux && !Platform.isAndroid) {
|
|
|
|
try {
|
2022-06-10 21:03:15 +00:00
|
|
|
return NixNotificationManager(notificationSelectConvo);
|
2022-04-15 00:02:08 +00:00
|
|
|
} catch (e) {
|
|
|
|
EnvironmentConfig.debugLog("Failed to create LinuxNotificationManager. Switching off notifications.");
|
|
|
|
}
|
|
|
|
} else if (Platform.isMacOS) {
|
2022-01-25 00:03:46 +00:00
|
|
|
try {
|
2022-02-18 23:50:34 +00:00
|
|
|
return NixNotificationManager(notificationSelectConvo);
|
2022-01-25 00:03:46 +00:00
|
|
|
} catch (e) {
|
2022-02-18 23:50:34 +00:00
|
|
|
EnvironmentConfig.debugLog("Failed to create NixNotificationManager. Switching off notifications.");
|
2022-01-25 00:03:46 +00:00
|
|
|
}
|
|
|
|
} else if (Platform.isWindows) {
|
|
|
|
try {
|
|
|
|
return WindowsNotificationManager();
|
|
|
|
} catch (e) {
|
2022-02-03 21:58:51 +00:00
|
|
|
EnvironmentConfig.debugLog("Failed to create Windows desktoasts notification manager");
|
2022-01-25 00:03:46 +00:00
|
|
|
}
|
2021-06-28 21:32:26 +00:00
|
|
|
}
|
2022-02-18 23:50:34 +00:00
|
|
|
|
2021-06-28 21:32:26 +00:00
|
|
|
return NullNotificationsManager();
|
2021-06-30 20:59:52 +00:00
|
|
|
}
|