1package notification
2
3import (
4 "log/slog"
5 "sync"
6
7 "git.secluded.site/crush/internal/config"
8 "github.com/gen2brain/beeep"
9)
10
11var (
12 isFocused = true
13 supportsFocus = false
14 focusStateLock sync.RWMutex
15
16 // notifyFunc is the function used to send notifications.
17 // It can be swapped for testing.
18 notifyFunc = beeep.Notify
19)
20
21// SetFocusSupport sets whether the terminal supports focus reporting.
22func SetFocusSupport(supported bool) {
23 focusStateLock.Lock()
24 defer focusStateLock.Unlock()
25 supportsFocus = supported
26}
27
28// SetFocused sets whether the terminal window is currently focused.
29func SetFocused(focused bool) {
30 focusStateLock.Lock()
31 defer focusStateLock.Unlock()
32 isFocused = focused
33}
34
35// IsFocused returns whether the terminal window is currently focused.
36func IsFocused() bool {
37 focusStateLock.RLock()
38 defer focusStateLock.RUnlock()
39 return isFocused
40}
41
42// Send sends a desktop notification with the given title and message.
43// Notifications are only sent when focus reporting is supported, the terminal window is not focused, and notifications are not disabled in config.
44// On darwin (macOS), icons are omitted due to platform limitations.
45func Send(title, message string) error {
46 // Check if notifications are disabled in config
47 cfg := config.Get()
48 if cfg != nil && cfg.Options != nil && cfg.Options.DisableNotifications {
49 slog.Debug("skipping notification: disabled in config")
50 return nil
51 }
52
53 focusStateLock.RLock()
54 focused := isFocused
55 supported := supportsFocus
56 focusStateLock.RUnlock()
57
58 slog.Debug("notification.Send called", "title", title, "message", message, "focused", focused, "supported", supported)
59
60 // Only send notifications if focus reporting is supported and window is not focused.
61 if !supported || focused {
62 slog.Debug("skipping notification: focus not supported or window is focused")
63 return nil
64 }
65
66 beeep.AppName = "Crush"
67
68 err := notifyFunc(title, message, notificationIcon)
69
70 if err != nil {
71 slog.Error("failed to send notification", "error", err)
72 } else {
73 slog.Debug("notification sent successfully")
74 }
75
76 return err
77}