//go:build darwin #import #import // cdropNotify posts a user notification via UNUserNotificationCenter. // // Guarded for the unsigned case: UNUserNotificationCenter raises // NSInternalInconsistencyException ("bundleProxyForCurrentProcess is nil") when // the process has no signed bundle proxy. We bail when there's no bundle // identifier and wrap the calls in @try/@catch, so an unsigned / ad-hoc build // degrades to a silent no-op instead of crashing the app. On a signed build it // requests authorization once (idempotent after the first grant) and delivers. void cdropNotify(const char *title, const char *body) { if (title == NULL || body == NULL) { return; } NSString *nsTitle = [NSString stringWithUTF8String:title]; NSString *nsBody = [NSString stringWithUTF8String:body]; // No bundle identifier → unsigned / non-bundle build → UNUserNotificationCenter // would throw. Skip; display lights up once the bundle is signed (D6). if ([[NSBundle mainBundle] bundleIdentifier] == nil) { return; } dispatch_async(dispatch_get_main_queue(), ^{ // UNUserNotificationCenter is macOS 10.14+. Guard so older targets (Wails // defaults the deployment target to 10.13) compile clean and no-op there. if (@available(macOS 10.14, *)) { @try { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError *_Nullable error) { if (!granted) { return; } UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; content.title = nsTitle; content.body = nsBody; content.sound = [UNNotificationSound defaultSound]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[[NSUUID UUID] UUIDString] content:content trigger:nil]; [center addNotificationRequest:request withCompletionHandler:nil]; }]; } @catch (NSException *exception) { // Unsigned bundle or notifications unavailable — ignore. } } }); }