import threading from git_monitor.logger import logger # Modern Windows 10/11 toasts with buttons try: from windows_toasts import WindowsToaster, ToastText2, ToastActivatedEventArgs, ToastButton WINDOWS_TOASTS_AVAILABLE = True toaster = WindowsToaster('Git Monitor') except ImportError: logger.warning("windows-toasts not found. Interactive buttons will not be available.") WINDOWS_TOASTS_AVAILABLE = False # Fallbacks try: from plyer import notification PLYER_AVAILABLE = True except ImportError: PLYER_AVAILABLE = False try: from win10toast import ToastNotifier WIN10TOAST_AVAILABLE = True legacy_toaster = ToastNotifier() except ImportError: WIN10TOAST_AVAILABLE = False class Notifier: def notify(self, title, message): """Simple notification (no buttons).""" logger.info(f"Notification: {title} - {message}") if WINDOWS_TOASTS_AVAILABLE: try: toast = ToastText2() toast.headline = title toast.body = message toaster.show_toast(toast) return except Exception as e: logger.error(f"windows-toasts simple notification failed: {e}") # Fallback to older libraries if PLYER_AVAILABLE: try: notification.notify(title=title, message=message, app_name="Git Monitor") return except: pass if WIN10TOAST_AVAILABLE: try: legacy_toaster.show_toast(title, message, duration=5, threaded=True) return except: pass def notify_interactive(self, title, message, on_save, on_later): """Interactive notification with 'Save now' and 'Ask in 5 min' buttons.""" logger.info(f"Interactive Notification: {title} - {message}") if not WINDOWS_TOASTS_AVAILABLE: logger.warning("Interactive notifications not available, performing default action (Save).") on_save() return try: toast = ToastText2() toast.headline = title toast.body = message # Action buttons toast.AddAction(ToastButton("Zapisz teraz", "save")) toast.AddAction(ToastButton("Zapytaj mnie za 5 min", "later")) # Handler for button clicks def on_activated(args: ToastActivatedEventArgs): if args.arguments == "save": logger.info("User clicked 'Zapisz teraz'") on_save() elif args.arguments == "later": logger.info("User clicked 'Zapytaj mnie za 5 min'") on_later() else: # Default click on toast body on_save() toast.on_activated = on_activated toaster.show_toast(toast) except Exception as e: logger.error(f"Interactive notification error: {e}") # Fallback to immediate save if notification fails on_save() notifier = Notifier()