# -*- coding: utf-8 -*-"""NSUserNotificationCenter backend for macOS.* Should be used for macOS 10.13 and earlier.* Deprecated but still available in macOS 11.0.* Requires a running CFRunLoop to invoke callbacks."""# system importsimportuuidimportplatformimportloggingfromtypingimportcast,Optional# external importsfromrubicon.objcimportNSObject,ObjCClass,objc_method,py_from_nsfromrubicon.objc.runtimeimportload_library# local importsfrom.baseimportNotification,DesktopNotifierBase__all__=["CocoaNotificationCenterLegacy"]logger=logging.getLogger(__name__)macos_version,*_=platform.mac_ver()foundation=load_library("Foundation")NSUserNotification=ObjCClass("NSUserNotification")NSUserNotificationCenter=ObjCClass("NSUserNotificationCenter")NSDate=ObjCClass("NSDate")NSUserNotificationActivationTypeContentsClicked=1NSUserNotificationActivationTypeActionButtonClicked=2NSUserNotificationActivationTypeAdditionalActionClicked=4NSUserNotificationDefaultSoundName="DefaultSoundName"classNotificationCenterDelegate(NSObject):# type: ignore"""Delegate to handle user interactions with notifications"""@objc_method# type:ignoredefuserNotificationCenter_didActivateNotification_(self,center,notification)->None:platform_nid=py_from_ns(notification.identifier)py_notification=self.interface._notification_for_nid[platform_nid]py_notification=cast(Notification,py_notification)self.interface._clear_notification_from_cache(py_notification)if(notification.activationType==NSUserNotificationActivationTypeContentsClicked):ifpy_notification.on_clicked:py_notification.on_clicked()elif(notification.activationType==NSUserNotificationActivationTypeActionButtonClicked):callback=py_notification.buttons[0].on_pressedifcallback:callback()
[docs]classCocoaNotificationCenterLegacy(DesktopNotifierBase):"""NSUserNotificationCenter backend for macOS Should be used for macOS High Sierra and earlier. Supports only a single button per notification. Both app name and bundle identifier will be ignored. The notification center automatically uses the values provided by the app bundle or the Python framework. :param app_name: The name of the app. Does not have any effect because the app name is automatically determined from the bundle or framework. :param notification_limit: Maximum number of notifications to keep in the system's notification center. """def__init__(self,app_name:str="Python",notification_limit:Optional[int]=None,)->None:super().__init__(app_name,notification_limit)self.nc=NSUserNotificationCenter.defaultUserNotificationCenterself.nc_delegate=NotificationCenterDelegate.alloc().init()self.nc_delegate.interface=selfself.nc.delegate=self.nc_delegate
[docs]asyncdefrequest_authorisation(self)->bool:""" Request authorisation to send notifications. :returns: Whether authorisation has been granted. """returnTrue
[docs]asyncdefhas_authorisation(self)->bool:""" Whether we have authorisation to send notifications. """returnTrue
[docs]asyncdef_send(self,notification:Notification,notification_to_replace:Optional[Notification],)->str:""" Uses NSUserNotificationCenter to schedule a notification. :param notification: Notification to send. :param notification_to_replace: Notification to replace, if any. """ifnotification_to_replace:platform_nid=str(notification_to_replace.identifier)else:platform_nid=str(uuid.uuid4())n=NSUserNotification.alloc().init()n.title=notification.titlen.informativeText=notification.messagen.identifier=platform_nidn.deliveryDate=NSDate.dateWithTimeInterval(0,sinceDate=NSDate.date())# store the notification instance for clearingnotification._native=n# type: ignoreifnotification.sound:n.soundName=NSUserNotificationDefaultSoundNameifnotification.buttons:iflen(notification.buttons)>1:logger.debug("NSUserNotificationCenter: only a single button is supported")n.hasActionButton=Truen.actionButtonTitle=notification.buttons[0].titleself.nc.scheduleNotification(n)returnplatform_nid
[docs]asyncdef_clear(self,notification:Notification)->None:""" Removes a notifications from the notification center :param notification: Notification to clear. """ifhasattr(notification,"_native"):self.nc.removeDeliveredNotification(notification._native)
[docs]asyncdef_clear_all(self)->None:""" Clears all notifications from notification center """self.nc.removeAllDeliveredNotifications()