Detailed changes
@@ -25,6 +25,7 @@ type Service interface {
RefreshFolder(accountID, folder string) error
Subscribe(accountID, folder string) error
Unsubscribe(accountID, folder string) error
+ ReloadConfig() error
Events() <-chan *daemonrpc.Event
IsDaemon() bool
Close() error
@@ -187,6 +188,10 @@ func (s *daemonService) Unsubscribe(accountID, folder string) error {
}, nil)
}
+func (s *daemonService) ReloadConfig() error {
+ return s.client.Call(daemonrpc.MethodReloadConfig, nil, nil)
+}
+
func (s *daemonService) Events() <-chan *daemonrpc.Event {
return s.client.Events()
}
@@ -313,6 +318,16 @@ func (s *directService) Unsubscribe(_, _ string) error {
return nil
}
+func (s *directService) ReloadConfig() error {
+ cfg, err := config.LoadConfig()
+ if err != nil {
+ return err
+ }
+ s.cfg = cfg
+ s.initProviders()
+ return nil
+}
+
func (s *directService) Events() <-chan *daemonrpc.Event {
return s.events
}
@@ -982,6 +982,14 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
return m, m.current.Init()
+ case tui.ConfigSavedMsg:
+ if m.service != nil {
+ if err := m.service.ReloadConfig(); err != nil {
+ log.Printf("config reload: %v", err)
+ }
+ }
+ return m, nil
+
case tui.LanguageChangedMsg:
// Rebuild all models with new translations
// Keep current view type but recreate with fresh i18n
@@ -543,6 +543,10 @@ type SendRSVPMsg struct {
// RSVPResultMsg signals that RSVP was sent (or failed)
type LanguageChangedMsg struct{}
+// ConfigSavedMsg signals the config was written to disk and downstream
+// consumers (notably the daemon) should reload it.
+type ConfigSavedMsg struct{}
+
type RSVPResultMsg struct {
Err error
Response string // "ACCEPTED", "DECLINED", "TENTATIVE"
@@ -68,19 +68,24 @@ func (m *Settings) updateGeneral(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
return m, nil
}
+ saved := false
switch m.generalCursor {
case 0: // Image Display
m.cfg.DisableImages = !m.cfg.DisableImages
_ = config.SaveConfig(m.cfg)
+ saved = true
case 1: // Contextual Tips
m.cfg.HideTips = !m.cfg.HideTips
_ = config.SaveConfig(m.cfg)
+ saved = true
case 2: // Desktop Notifications
m.cfg.DisableNotifications = !m.cfg.DisableNotifications
_ = config.SaveConfig(m.cfg)
+ saved = true
case 3: // Split Pane View
m.cfg.EnableSplitPane = !m.cfg.EnableSplitPane
_ = config.SaveConfig(m.cfg)
+ saved = true
case 4: // Date Format
switch m.cfg.DateFormat {
case config.DateFormatEU:
@@ -91,6 +96,7 @@ func (m *Settings) updateGeneral(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
m.cfg.DateFormat = config.DateFormatEU
}
_ = config.SaveConfig(m.cfg)
+ saved = true
case 5: // Language
// Cycle through available languages
langs := i18n.LanguageCodes()
@@ -108,12 +114,18 @@ func (m *Settings) updateGeneral(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
// Apply language change immediately
i18n.GetManager().SetLanguage(m.cfg.Language)
// Trigger full UI rebuild
- return m, func() tea.Msg { return LanguageChangedMsg{} }
+ return m, tea.Batch(
+ func() tea.Msg { return ConfigSavedMsg{} },
+ func() tea.Msg { return LanguageChangedMsg{} },
+ )
case 6: // Edit Signature
if msg.String() == "enter" || msg.String() == "right" || msg.String() == "l" {
return m, func() tea.Msg { return GoToSignatureEditorMsg{} }
}
}
+ if saved {
+ return m, func() tea.Msg { return ConfigSavedMsg{} }
+ }
}
}
return m, nil