forked from fyne-io/fyne
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace deprecated NSNotificationCentre with UNNotificationCentre
Sadly this requires the apps to be signed, so it only really works for store-distributed apps. But it's required because of the deprecations. Fixes fyne-io#1833
- Loading branch information
1 parent
2af008e
commit fc94fa3
Showing
6 changed files
with
132 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,59 @@ | ||
// +build !ci | ||
|
||
// +build !ios | ||
|
||
package app | ||
|
||
/* | ||
#cgo CFLAGS: -x objective-c | ||
#cgo LDFLAGS: -framework Foundation | ||
#cgo LDFLAGS: -framework Foundation -framework UserNotifications | ||
#include <AppKit/AppKit.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
bool isBundled(); | ||
bool isDarkMode(); | ||
void sendNotification(const char *title, const char *content); | ||
void watchTheme(); | ||
void sendNotification(char *title, char *content); | ||
*/ | ||
import "C" | ||
import ( | ||
"fmt" | ||
"net/url" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"unsafe" | ||
|
||
"fyne.io/fyne/v2" | ||
"fyne.io/fyne/v2/theme" | ||
|
||
"golang.org/x/sys/execabs" | ||
) | ||
|
||
func defaultVariant() fyne.ThemeVariant { | ||
if C.isDarkMode() { | ||
return theme.VariantDark | ||
} | ||
return theme.VariantLight | ||
} | ||
|
||
func rootConfigDir() string { | ||
homeDir, _ := os.UserHomeDir() | ||
|
||
desktopConfig := filepath.Join(filepath.Join(homeDir, "Library"), "Preferences") | ||
return filepath.Join(desktopConfig, "fyne") | ||
} | ||
|
||
func (a *fyneApp) OpenURL(url *url.URL) error { | ||
cmd := a.exec("open", url.String()) | ||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr | ||
return cmd.Run() | ||
} | ||
|
||
func (a *fyneApp) SendNotification(n *fyne.Notification) { | ||
if C.isBundled() { | ||
title := C.CString(n.Title) | ||
defer C.free(unsafe.Pointer(title)) | ||
content := C.CString(n.Content) | ||
defer C.free(unsafe.Pointer(content)) | ||
titleStr := C.CString(n.Title) | ||
defer C.free(unsafe.Pointer(titleStr)) | ||
contentStr := C.CString(n.Content) | ||
defer C.free(unsafe.Pointer(contentStr)) | ||
|
||
C.sendNotification(title, content) | ||
C.sendNotification(titleStr, contentStr) | ||
return | ||
} | ||
|
||
title := escapeNotificationString(n.Title) | ||
content := escapeNotificationString(n.Content) | ||
template := `display notification "%s" with title "%s"` | ||
script := fmt.Sprintf(template, content, title) | ||
|
||
err := execabs.Command("osascript", "-e", script).Start() | ||
if err != nil { | ||
fyne.LogError("Failed to launch darwin notify script", err) | ||
} | ||
fallbackNotification(n.Title, n.Content) | ||
} | ||
|
||
func escapeNotificationString(in string) string { | ||
noSlash := strings.ReplaceAll(in, "\\", "\\\\") | ||
return strings.ReplaceAll(noSlash, "\"", "\\\"") | ||
} | ||
|
||
//export themeChanged | ||
func themeChanged() { | ||
fyne.CurrentApp().Settings().(*settings).setupTheme() | ||
//export fallbackSend | ||
func fallbackSend(cTitle, cContent *C.char) { | ||
title := C.GoString(cTitle) | ||
content := C.GoString(cContent) | ||
fallbackNotification(title, content) | ||
} | ||
|
||
func watchTheme() { | ||
C.watchTheme() | ||
func fallbackNotification(title, content string) { | ||
template := `display notification "%s" with title "%s"` | ||
script := fmt.Sprintf(template, escapeNotificationString(content), escapeNotificationString(title)) | ||
|
||
err := execabs.Command("osascript", "-e", script).Start() | ||
if err != nil { | ||
fyne.LogError("Failed to launch darwin notify script", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,51 @@ | ||
// +build !ci | ||
// +build !ios | ||
|
||
extern void themeChanged(); | ||
#import <UserNotifications/UserNotifications.h> | ||
|
||
#import <Foundation/Foundation.h> | ||
static int notifyNum = 0; | ||
|
||
@interface FyneUserNotificationCenterDelegate : NSObject<NSUserNotificationCenterDelegate> | ||
extern void fallbackSend(char *cTitle, char *cBody); | ||
|
||
- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center | ||
shouldPresentNotification:(NSUserNotification*)notification; | ||
void doSendNotification(UNUserNotificationCenter *center, NSString *title, NSString *body) { | ||
UNMutableNotificationContent *content = [UNMutableNotificationContent new]; | ||
[content autorelease]; | ||
content.title = title; | ||
content.body = body; | ||
|
||
@end | ||
notifyNum++; | ||
NSString *identifier = [NSString stringWithFormat:@"fyne-notify-%d", notifyNum]; | ||
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier | ||
content:content trigger:nil]; | ||
|
||
@implementation FyneUserNotificationCenterDelegate | ||
|
||
- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center | ||
shouldPresentNotification:(NSUserNotification*)notification | ||
{ | ||
return YES; | ||
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { | ||
if (error != nil) { | ||
NSLog(@"Could not send notification: %@", error); | ||
} | ||
}]; | ||
} | ||
|
||
@end | ||
|
||
void sendNSUserNotification(const char *, const char *); | ||
|
||
bool isBundled() { | ||
return [[NSBundle mainBundle] bundleIdentifier] != nil; | ||
} | ||
|
||
bool isDarkMode() { | ||
NSString *style = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]; | ||
return [@"Dark" isEqualToString:style]; | ||
} | ||
|
||
void sendNotification(const char *title, const char *body) { | ||
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; | ||
if (center.delegate == nil) { | ||
center.delegate = [[FyneUserNotificationCenterDelegate new] autorelease]; | ||
} | ||
|
||
NSString *uuid = [[NSUUID UUID] UUIDString]; | ||
NSUserNotification *notification = [[NSUserNotification new] autorelease]; | ||
notification.title = [NSString stringWithUTF8String:title]; | ||
notification.informativeText = [NSString stringWithUTF8String:body]; | ||
notification.identifier = [NSString stringWithFormat:@"%@-fyne-notify-%@", [[NSBundle mainBundle] bundleIdentifier], uuid]; | ||
[center scheduleNotification:notification]; | ||
} | ||
|
||
void watchTheme() { | ||
[[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"AppleInterfaceThemeChangedNotification" object:nil queue:nil | ||
usingBlock:^(NSNotification *note) { | ||
themeChanged(); // calls back into Go | ||
}]; | ||
void sendNotification(char *cTitle, char *cBody) { | ||
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; | ||
NSString *title = [NSString stringWithUTF8String:cTitle]; | ||
NSString *body = [NSString stringWithUTF8String:cBody]; | ||
|
||
UNAuthorizationOptions options = UNAuthorizationOptionAlert; | ||
[center requestAuthorizationWithOptions:options | ||
completionHandler:^(BOOL granted, NSError *_Nullable error) { | ||
if (!granted) { | ||
if (error != NULL) { | ||
NSLog(@"Error asking for permission to send notifications %@", error); | ||
// this happens if our app was not signed, so do it the old way | ||
fallbackSend((char *)[title UTF8String], (char *)[body UTF8String]); | ||
} else { | ||
NSLog(@"Unable to get permission to send notifications"); | ||
} | ||
} else { | ||
doSendNotification(center, title, body); | ||
} | ||
}]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// +build !ci | ||
|
||
// +build !ios | ||
|
||
package app | ||
|
||
/* | ||
#cgo CFLAGS: -x objective-c | ||
#cgo LDFLAGS: -framework Foundation | ||
#include <AppKit/AppKit.h> | ||
bool isBundled(); | ||
bool isDarkMode(); | ||
void watchTheme(); | ||
*/ | ||
import "C" | ||
import ( | ||
"net/url" | ||
"os" | ||
"path/filepath" | ||
|
||
"fyne.io/fyne/v2" | ||
"fyne.io/fyne/v2/theme" | ||
) | ||
|
||
func defaultVariant() fyne.ThemeVariant { | ||
if C.isDarkMode() { | ||
return theme.VariantDark | ||
} | ||
return theme.VariantLight | ||
} | ||
|
||
func rootConfigDir() string { | ||
homeDir, _ := os.UserHomeDir() | ||
|
||
desktopConfig := filepath.Join(filepath.Join(homeDir, "Library"), "Preferences") | ||
return filepath.Join(desktopConfig, "fyne") | ||
} | ||
|
||
func (a *fyneApp) OpenURL(url *url.URL) error { | ||
cmd := a.exec("open", url.String()) | ||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr | ||
return cmd.Run() | ||
} | ||
|
||
//export themeChanged | ||
func themeChanged() { | ||
fyne.CurrentApp().Settings().(*settings).setupTheme() | ||
} | ||
|
||
func watchTheme() { | ||
C.watchTheme() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// +build !ci | ||
// +build !ios | ||
|
||
extern void themeChanged(); | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
bool isDarkMode() { | ||
NSString *style = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]; | ||
return [@"Dark" isEqualToString:style]; | ||
} | ||
|
||
void watchTheme() { | ||
[[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"AppleInterfaceThemeChangedNotification" object:nil queue:nil | ||
usingBlock:^(NSNotification *note) { | ||
themeChanged(); // calls back into Go | ||
}]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters