Skip to content

Commit 40fd258

Browse files
authored
Merge pull request #20 from ready-to-review/mute
Add sound toggle for Goose-haters
2 parents 7ebe750 + 92900eb commit 40fd258

File tree

4 files changed

+162
-5
lines changed

4 files changed

+162
-5
lines changed

cmd/goose/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ type App struct {
132132
hideStaleIncoming bool
133133
loadingTurnData bool
134134
enableReminders bool // Whether to send daily reminder notifications
135+
enableAudioCues bool // Whether to play audio cues for notifications
135136
}
136137

137138
func main() {
@@ -183,8 +184,12 @@ func main() {
183184
updateInterval: updateInterval,
184185
pendingTurnResults: make([]TurnResult, 0),
185186
enableReminders: true,
187+
enableAudioCues: true,
186188
}
187189

190+
// Load saved settings
191+
app.loadSettings()
192+
188193
log.Println("Initializing GitHub clients...")
189194
err = app.initClients(ctx)
190195
if err != nil {

cmd/goose/settings.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Package main - settings.go provides persistent settings storage.
2+
package main
3+
4+
import (
5+
"encoding/json"
6+
"log"
7+
"os"
8+
"path/filepath"
9+
)
10+
11+
// Settings represents persistent user settings.
12+
type Settings struct {
13+
EnableAudioCues bool `json:"enable_audio_cues"`
14+
EnableReminders bool `json:"enable_reminders"`
15+
HideStale bool `json:"hide_stale"`
16+
}
17+
18+
// getSettingsDir returns the configuration directory for settings.
19+
func getSettingsDir() (string, error) {
20+
configDir, err := os.UserConfigDir()
21+
if err != nil {
22+
return "", err
23+
}
24+
return filepath.Join(configDir, "ready-to-review"), nil
25+
}
26+
27+
// loadSettings loads settings from disk or returns defaults.
28+
func (app *App) loadSettings() {
29+
settingsDir, err := getSettingsDir()
30+
if err != nil {
31+
log.Printf("Failed to get settings directory: %v", err)
32+
// Use defaults
33+
app.enableAudioCues = true
34+
app.enableReminders = true
35+
app.hideStaleIncoming = true
36+
return
37+
}
38+
39+
settingsPath := filepath.Join(settingsDir, "settings.json")
40+
41+
data, err := os.ReadFile(settingsPath)
42+
if err != nil {
43+
if !os.IsNotExist(err) {
44+
log.Printf("Failed to read settings: %v", err)
45+
}
46+
// Use defaults
47+
app.enableAudioCues = true
48+
app.enableReminders = true
49+
app.hideStaleIncoming = true
50+
return
51+
}
52+
53+
var settings Settings
54+
if err := json.Unmarshal(data, &settings); err != nil {
55+
log.Printf("Failed to parse settings: %v", err)
56+
// Use defaults
57+
app.enableAudioCues = true
58+
app.enableReminders = true
59+
app.hideStaleIncoming = true
60+
return
61+
}
62+
63+
app.enableAudioCues = settings.EnableAudioCues
64+
app.enableReminders = settings.EnableReminders
65+
app.hideStaleIncoming = settings.HideStale
66+
log.Printf("Loaded settings: audio_cues=%v, reminders=%v, hide_stale=%v",
67+
app.enableAudioCues, app.enableReminders, app.hideStaleIncoming)
68+
}
69+
70+
// saveSettings saves current settings to disk.
71+
func (app *App) saveSettings() {
72+
settingsDir, err := getSettingsDir()
73+
if err != nil {
74+
log.Printf("Failed to get settings directory: %v", err)
75+
return
76+
}
77+
78+
app.mu.RLock()
79+
settings := Settings{
80+
EnableAudioCues: app.enableAudioCues,
81+
EnableReminders: app.enableReminders,
82+
HideStale: app.hideStaleIncoming,
83+
}
84+
app.mu.RUnlock()
85+
86+
// Ensure directory exists
87+
if err := os.MkdirAll(settingsDir, 0o700); err != nil {
88+
log.Printf("Failed to create settings directory: %v", err)
89+
return
90+
}
91+
92+
settingsPath := filepath.Join(settingsDir, "settings.json")
93+
94+
data, err := json.MarshalIndent(settings, "", " ")
95+
if err != nil {
96+
log.Printf("Failed to marshal settings: %v", err)
97+
return
98+
}
99+
100+
if err := os.WriteFile(settingsPath, data, 0o600); err != nil {
101+
log.Printf("Failed to save settings: %v", err)
102+
return
103+
}
104+
105+
log.Printf("Saved settings: audio_cues=%v, reminders=%v, hide_stale=%v",
106+
settings.EnableAudioCues, settings.EnableReminders, settings.HideStale)
107+
}

cmd/goose/sound.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ func (app *App) initSoundCache() {
5252

5353
// playSound plays a cached sound file using platform-specific commands.
5454
func (app *App) playSound(ctx context.Context, soundType string) {
55+
// Check if audio cues are enabled
56+
app.mu.RLock()
57+
audioEnabled := app.enableAudioCues
58+
app.mu.RUnlock()
59+
60+
if !audioEnabled {
61+
log.Printf("[SOUND] Sound playback skipped (audio cues disabled): %s", soundType)
62+
return
63+
}
64+
5565
log.Printf("[SOUND] Playing %s sound", soundType)
5666
// Ensure sounds are cached
5767
app.initSoundCache()

cmd/goose/ui.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,18 +287,24 @@ func (app *App) addStaticMenuItems(ctx context.Context) {
287287
hideStaleItem.Check()
288288
}
289289
hideStaleItem.Click(func() {
290+
app.mu.Lock()
290291
app.hideStaleIncoming = !app.hideStaleIncoming
291-
if app.hideStaleIncoming {
292+
hideStale := app.hideStaleIncoming
293+
// Clear menu state to force rebuild
294+
app.lastMenuState = nil
295+
app.mu.Unlock()
296+
297+
if hideStale {
292298
hideStaleItem.Check()
293299
} else {
294300
hideStaleItem.Uncheck()
295301
}
302+
303+
// Save settings to disk
304+
app.saveSettings()
305+
296306
// Toggle hide stale PRs setting
297307
// Force menu rebuild since hideStaleIncoming changed
298-
app.mu.Lock()
299-
// Clear menu state to force rebuild
300-
app.lastMenuState = nil
301-
app.mu.Unlock()
302308
app.rebuildMenu(ctx)
303309
})
304310

@@ -323,11 +329,40 @@ func (app *App) addStaticMenuItems(ctx context.Context) {
323329
reminderItem.Uncheck()
324330
log.Println("[SETTINGS] Daily reminders disabled")
325331
}
332+
333+
// Save settings to disk
334+
app.saveSettings()
326335
})
327336

328337
// Add login item option (macOS only)
329338
addLoginItemUI(ctx, app)
330339

340+
// Audio cues
341+
// Add 'Audio cues' option
342+
audioItem := systray.AddMenuItem("Audio cues", "Play sounds for notifications")
343+
app.mu.RLock()
344+
if app.enableAudioCues {
345+
audioItem.Check()
346+
}
347+
app.mu.RUnlock()
348+
audioItem.Click(func() {
349+
app.mu.Lock()
350+
app.enableAudioCues = !app.enableAudioCues
351+
enabled := app.enableAudioCues
352+
app.mu.Unlock()
353+
354+
if enabled {
355+
audioItem.Check()
356+
log.Println("[SETTINGS] Audio cues enabled")
357+
} else {
358+
audioItem.Uncheck()
359+
log.Println("[SETTINGS] Audio cues disabled")
360+
}
361+
362+
// Save settings to disk
363+
app.saveSettings()
364+
})
365+
331366
// Quit
332367
// Add 'Quit' option
333368
quitItem := systray.AddMenuItem("Quit", "")

0 commit comments

Comments
 (0)