windows fixes: especially new version of win toast

This commit is contained in:
Dan Ballard 2023-05-22 12:54:40 -07:00
parent 2c0e0e16f2
commit 471ab96743
4 changed files with 109 additions and 36 deletions

View File

@ -44,6 +44,8 @@ Future<void> main() async {
print("Cwtch version: ${EnvironmentConfig.BUILD_VER} built on: ${EnvironmentConfig.BUILD_DATE}"); print("Cwtch version: ${EnvironmentConfig.BUILD_VER} built on: ${EnvironmentConfig.BUILD_DATE}");
LicenseRegistry.addLicense(() => licenses()); LicenseRegistry.addLicense(() => licenses());
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
// window_manager requires (await recommended but probably not required if not using immediately)
windowManager.ensureInitialized();
print("runApp()"); print("runApp()");
return runApp(Flwtch()); return runApp(Flwtch());
} }
@ -104,9 +106,10 @@ class FlwtchState extends State<Flwtch> with WindowListener {
new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this); new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this);
cwtch = CwtchFfi(cwtchNotifier); cwtch = CwtchFfi(cwtchNotifier);
} }
startConnectivityListener();
print("initState: invoking cwtch.Start()"); print("initState: invoking cwtch.Start()");
cwtch.Start(); cwtch.Start();
print("initState: starting connectivityListener");
startConnectivityListener();
print("initState: done!"); print("initState: done!");
super.initState(); super.initState();
} }
@ -288,7 +291,8 @@ class FlwtchState extends State<Flwtch> with WindowListener {
); );
// On Gnome follows up a clicked notification with a "Cwtch is ready" notification that takes you to the app. AFAICT just because Gnome is bad // On Gnome follows up a clicked notification with a "Cwtch is ready" notification that takes you to the app. AFAICT just because Gnome is bad
// https://askubuntu.com/questions/1286206/how-to-skip-the-is-ready-notification-and-directly-open-apps-in-ubuntu-20-4 // https://askubuntu.com/questions/1286206/how-to-skip-the-is-ready-notification-and-directly-open-apps-in-ubuntu-20-4
windowManager.focus(); await windowManager.show();
await windowManager.focus();
} }
// using windowManager flutter plugin until proper lifecycle management lands in desktop // using windowManager flutter plugin until proper lifecycle management lands in desktop
@ -303,6 +307,9 @@ class FlwtchState extends State<Flwtch> with WindowListener {
globalAppState.focus = false; globalAppState.focus = false;
} }
void onWindowClose() {
}
@override @override
void dispose() { void dispose() {
globalAppState.SetModalState(ModalState.shutdown); globalAppState.SetModalState(ModalState.shutdown);

View File

@ -23,7 +23,8 @@ abstract class NotificationsManager {
// NullNotificationsManager ignores all notification requests // NullNotificationsManager ignores all notification requests
class NullNotificationsManager implements NotificationsManager { class NullNotificationsManager implements NotificationsManager {
@override @override
Future<void> notify(String message, String profile, int conversationId) async {} Future<void> notify(
String message, String profile, int conversationId) async {}
} }
// Windows Notification Manager uses https://pub.dev/packages/desktoasts to implement // Windows Notification Manager uses https://pub.dev/packages/desktoasts to implement
@ -31,11 +32,32 @@ class NullNotificationsManager implements NotificationsManager {
class WindowsNotificationManager implements NotificationsManager { class WindowsNotificationManager implements NotificationsManager {
bool active = false; bool active = false;
bool initialized = false; bool initialized = false;
late Future<void> Function(String, int) notificationSelectConvo;
// TODO This needs testing and redefining...
WindowsNotificationManager() { WindowsNotificationManager(Future<void> Function(String, int) notificationSelectConvo) {
this.notificationSelectConvo = notificationSelectConvo;
scheduleMicrotask(() async { scheduleMicrotask(() async {
initialized = await WinToast.instance().initialize(clsid: 'cwtch', displayName: 'Cwtch', aumId: 'Open Privacy Research Society', iconPath: ''); //initialized = await WinToast.instance().initialize(clsid: 'cwtch', displayName: 'Cwtch', aumId: 'Open Privacy Research Society', iconPath: '');
// initialize toast with you aumId, displayName and iconPath
var init = await WinToast.instance().initialize(
aumId: 'OpenPrivacyResearchSociety.Cwtch',
displayName: 'Cwtch',
iconPath: '', // TODO NEED ICON
clsid: 'cwtch',
);
WinToast.instance().setActivatedCallback((event) {
if (event.argument != "close") {
try {
Map<String, dynamic> payloadMap = jsonDecode(event.argument);
var payload = NotificationPayload.fromJson(payloadMap);
notificationSelectConvo(payload.profileOnion, payload.convoId);
} catch (e) {
/* it failed, is ok, may have been 'close'? */
}
}
});
initialized = true;
}); });
} }
@ -43,14 +65,31 @@ class WindowsNotificationManager implements NotificationsManager {
if (initialized && !globalAppState.focus) { if (initialized && !globalAppState.focus) {
if (!active) { if (!active) {
active = true; active = true;
// WinToast.instance().clear(); WinToast.instance().clear();
//final toast = await WinToast.instance().showToast(toast: Toast(children: ,type: ToastType.text01, title: message)); await WinToast.instance().showToast(
//toast?.eventStream.listen((event) { toast: Toast(
// if (event is ActivatedEvent) { duration: ToastDuration.short,
// WinToast.instance().bringWindowToFront(); children: [
// } ToastChildAudio(source: ToastAudioSource.im),
active = false; ToastChildVisual(
// }); binding: ToastVisualBinding(children: [
ToastVisualBindingChildText(
text: message,
id: 1,
),
])),
ToastChildActions(children: [
ToastAction(
content: "Open",
arguments: jsonEncode(NotificationPayload(profile, conversationId)),
),
ToastAction(
content: "Close",
arguments: "close",
),
]),
]));
active = false;
} }
} }
} }
@ -87,7 +126,8 @@ class NixNotificationManager implements NotificationsManager {
Future<String> detectLinuxAssetsPath() async { Future<String> detectLinuxAssetsPath() async {
var devStat = FileStat.stat("assets"); var devStat = FileStat.stat("assets");
var localStat = FileStat.stat("data/flutter_assets"); var localStat = FileStat.stat("data/flutter_assets");
var homeStat = FileStat.stat((Platform.environment["HOME"] ?? "") + "/.local/share/cwtch/data/flutter_assets"); var homeStat = FileStat.stat((Platform.environment["HOME"] ?? "") +
"/.local/share/cwtch/data/flutter_assets");
var rootStat = FileStat.stat("/usr/share/cwtch/data/flutter_assets"); var rootStat = FileStat.stat("/usr/share/cwtch/data/flutter_assets");
if ((await devStat).type == FileSystemEntityType.directory) { if ((await devStat).type == FileSystemEntityType.directory) {
@ -95,14 +135,16 @@ class NixNotificationManager implements NotificationsManager {
} else if ((await localStat).type == FileSystemEntityType.directory) { } else if ((await localStat).type == FileSystemEntityType.directory) {
return path.join(Directory.current.path, "data/flutter_assets/"); return path.join(Directory.current.path, "data/flutter_assets/");
} else if ((await homeStat).type == FileSystemEntityType.directory) { } else if ((await homeStat).type == FileSystemEntityType.directory) {
return (Platform.environment["HOME"] ?? "") + "/.local/share/cwtch/data/flutter_assets/"; return (Platform.environment["HOME"] ?? "") +
"/.local/share/cwtch/data/flutter_assets/";
} else if ((await rootStat).type == FileSystemEntityType.directory) { } else if ((await rootStat).type == FileSystemEntityType.directory) {
return "/usr/share/cwtch/data/flutter_assets/"; return "/usr/share/cwtch/data/flutter_assets/";
} }
return ""; return "";
} }
NixNotificationManager(Future<void> Function(String, int) notificationSelectConvo) { NixNotificationManager(
Future<void> Function(String, int) notificationSelectConvo) {
this.notificationSelectConvo = notificationSelectConvo; this.notificationSelectConvo = notificationSelectConvo;
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
@ -113,24 +155,39 @@ class NixNotificationManager implements NotificationsManager {
linuxAssetsPath = ""; linuxAssetsPath = "";
} }
var linuxIcon =
FilePathLinuxIcon(path.join(linuxAssetsPath, 'assets/knott.png'));
var linuxIcon = FilePathLinuxIcon(path.join(linuxAssetsPath, 'assets/knott.png')); final LinuxInitializationSettings initializationSettingsLinux =
LinuxInitializationSettings(
defaultActionName: 'Open notification',
defaultIcon: linuxIcon,
defaultSuppressSound: true);
final LinuxInitializationSettings initializationSettingsLinux = LinuxInitializationSettings(defaultActionName: 'Open notification', defaultIcon: linuxIcon, defaultSuppressSound: true); final InitializationSettings initializationSettings =
InitializationSettings(
android: null,
iOS: null,
macOS: DarwinInitializationSettings(defaultPresentSound: false),
linux: initializationSettingsLinux);
final InitializationSettings initializationSettings = InitializationSettings(android: null, iOS: null, macOS: DarwinInitializationSettings(defaultPresentSound: false), linux: initializationSettingsLinux); flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<MacOSFlutterLocalNotificationsPlugin>()?.requestPermissions( MacOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true, alert: true,
badge: false, badge: false,
sound: false, sound: false,
); );
await flutterLocalNotificationsPlugin.initialize(initializationSettings, ); await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
);
}); });
} }
Future<void> notify(String message, String profile, int conversationId) async { Future<void> notify(
String message, String profile, int conversationId) async {
if (!globalAppState.focus) { if (!globalAppState.focus) {
// Warning: Only use title field on Linux, body field will render links as clickable // Warning: Only use title field on Linux, body field will render links as clickable
await flutterLocalNotificationsPlugin.show( await flutterLocalNotificationsPlugin.show(
@ -138,7 +195,11 @@ class NixNotificationManager implements NotificationsManager {
message, message,
'', '',
NotificationDetails( NotificationDetails(
linux: LinuxNotificationDetails(suppressSound: true, category: LinuxNotificationCategory.imReceived, icon: FilePathLinuxIcon(path.join(linuxAssetsPath, 'assets/knott.png')))), linux: LinuxNotificationDetails(
suppressSound: true,
category: LinuxNotificationCategory.imReceived,
icon: FilePathLinuxIcon(
path.join(linuxAssetsPath, 'assets/knott.png')))),
payload: jsonEncode(NotificationPayload(profile, conversationId))); payload: jsonEncode(NotificationPayload(profile, conversationId)));
} }
} }
@ -153,7 +214,9 @@ class NixNotificationManager implements NotificationsManager {
} }
} }
NotificationsManager newDesktopNotificationsManager(Future<void> Function(String profileOnion, int convoId) notificationSelectConvo) { NotificationsManager newDesktopNotificationsManager(
Future<void> Function(String profileOnion, int convoId)
notificationSelectConvo) {
// We don't want notifications in Dev Mode // We don't want notifications in Dev Mode
if (EnvironmentConfig.TEST_MODE) { if (EnvironmentConfig.TEST_MODE) {
return NullNotificationsManager(); return NullNotificationsManager();
@ -163,19 +226,22 @@ NotificationsManager newDesktopNotificationsManager(Future<void> Function(String
try { try {
return NixNotificationManager(notificationSelectConvo); return NixNotificationManager(notificationSelectConvo);
} catch (e) { } catch (e) {
EnvironmentConfig.debugLog("Failed to create LinuxNotificationManager. Switching off notifications."); EnvironmentConfig.debugLog(
"Failed to create LinuxNotificationManager. Switching off notifications.");
} }
} else if (Platform.isMacOS) { } else if (Platform.isMacOS) {
try { try {
return NixNotificationManager(notificationSelectConvo); return NixNotificationManager(notificationSelectConvo);
} catch (e) { } catch (e) {
EnvironmentConfig.debugLog("Failed to create NixNotificationManager. Switching off notifications."); EnvironmentConfig.debugLog(
"Failed to create NixNotificationManager. Switching off notifications.");
} }
} else if (Platform.isWindows) { } else if (Platform.isWindows) {
try { try {
return WindowsNotificationManager(); return WindowsNotificationManager(notificationSelectConvo);
} catch (e) { } catch (e) {
EnvironmentConfig.debugLog("Failed to create Windows desktoasts notification manager"); EnvironmentConfig.debugLog(
"Failed to create Windows desktoasts notification manager");
} }
} }

View File

@ -81,7 +81,7 @@ ShowInstDetails show
Section Section
# define the output path for this file # define the output path for this file
SetOutPath $INSTDIR SetOutPath "$INSTDIR"
# define what to install and place it in the output path # define what to install and place it in the output path
# Filler for .sh to populate with contents of deploy/windows # Filler for .sh to populate with contents of deploy/windows

View File

@ -69,14 +69,14 @@ IDI_APP_ICON_16 ICON "resources\\knot_16.ico"
// Version // Version
// //
#ifdef FLUTTER_BUILD_NUMBER #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
#else #else
#define VERSION_AS_NUMBER 1,0,0 #define VERSION_AS_NUMBER 1,0,0,0
#endif #endif
#ifdef FLUTTER_BUILD_NAME #if defined(FLUTTER_VERSION)
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME #define VERSION_AS_STRING FLUTTER_VERSION
#else #else
#define VERSION_AS_STRING "1.0.0" #define VERSION_AS_STRING "1.0.0"
#endif #endif