This commit is contained in:
Eva Ho 2025-12-17 17:13:03 -05:00
parent 5a5d3260f4
commit dc573715c4
2 changed files with 42 additions and 44 deletions

View File

@ -120,6 +120,7 @@ type UpdaterInterface interface {
DownloadUpdate(ctx context.Context, updateVersion string) error DownloadUpdate(ctx context.Context, updateVersion string) error
InstallAndRestart() error InstallAndRestart() error
CancelOngoingDownload() CancelOngoingDownload()
TriggerImmediateCheck()
} }
func (s *Server) log() *slog.Logger { func (s *Server) log() *slog.Logger {
@ -1465,43 +1466,25 @@ func (s *Server) settings(w http.ResponseWriter, r *http.Request) error {
return fmt.Errorf("failed to save settings: %w", err) return fmt.Errorf("failed to save settings: %w", err)
} }
// Update tray notification based on auto-update toggle // Handle auto-update toggle changes
if old.AutoUpdateEnabled && !settings.AutoUpdateEnabled { if old.AutoUpdateEnabled != settings.AutoUpdateEnabled {
// Auto-update disabled: cancel any ongoing download and clear tray notification if !settings.AutoUpdateEnabled {
if s.Updater != nil { // Auto-update disabled: cancel any ongoing download and clear tray notification
s.Updater.CancelOngoingDownload() if s.Updater != nil {
} s.Updater.CancelOngoingDownload()
if s.ClearUpdateAvailableFunc != nil { }
s.ClearUpdateAvailableFunc() if s.ClearUpdateAvailableFunc != nil {
} s.ClearUpdateAvailableFunc()
} else if !old.AutoUpdateEnabled && settings.AutoUpdateEnabled { }
// Auto-update enabled: check for updates and download if available } else {
go func() { // Auto-update re-enabled: show notification if update is already staged, or trigger immediate check
// First, show notification if update is already pending
if (updater.IsUpdatePending() || updater.UpdateDownloaded) && s.UpdateAvailableFunc != nil { if (updater.IsUpdatePending() || updater.UpdateDownloaded) && s.UpdateAvailableFunc != nil {
s.UpdateAvailableFunc() s.UpdateAvailableFunc()
} else if s.Updater != nil { } else if s.Updater != nil {
// Otherwise, immediately check for and download new updates // Trigger the background checker to run immediately
slog.Info("auto-update re-enabled, checking for updates") s.Updater.TriggerImmediateCheck()
available, updateVersion, err := s.Updater.CheckForUpdate(r.Context())
if err != nil {
slog.Error("failed to check for update after re-enabling auto-update", "error", err)
return
}
if available {
slog.Info("update available, starting download", "version", updateVersion)
err := s.Updater.DownloadUpdate(r.Context(), updateVersion)
if err != nil {
slog.Error("failed to download update", "error", err)
return
}
// Show tray notification after successful download
if s.UpdateAvailableFunc != nil {
s.UpdateAvailableFunc()
}
}
} }
}() }
} }
if old.ContextLength != settings.ContextLength || if old.ContextLength != settings.ContextLength ||

View File

@ -264,6 +264,7 @@ type Updater struct {
Store *store.Store Store *store.Store
cancelDownload context.CancelFunc cancelDownload context.CancelFunc
cancelDownloadLock sync.Mutex cancelDownloadLock sync.Mutex
checkNow chan struct{}
} }
// CancelOngoingDownload cancels any currently running download // CancelOngoingDownload cancels any currently running download
@ -277,24 +278,45 @@ func (u *Updater) CancelOngoingDownload() {
} }
} }
// TriggerImmediateCheck signals the background checker to check for updates immediately
func (u *Updater) TriggerImmediateCheck() {
if u.checkNow != nil {
u.checkNow <- struct{}{}
}
}
func (u *Updater) StartBackgroundUpdaterChecker(ctx context.Context, cb func(string) error) { func (u *Updater) StartBackgroundUpdaterChecker(ctx context.Context, cb func(string) error) {
u.checkNow = make(chan struct{}, 1)
go func() { go func() {
// Don't blast an update message immediately after startup // Don't blast an update message immediately after startup
time.Sleep(UpdateCheckInitialDelay) time.Sleep(UpdateCheckInitialDelay)
slog.Info("beginning update checker", "interval", UpdateCheckInterval) slog.Info("beginning update checker", "interval", UpdateCheckInterval)
ticker := time.NewTicker(UpdateCheckInterval)
defer ticker.Stop()
for { for {
select {
case <-ctx.Done():
slog.Debug("stopping background update checker")
return
case <-u.checkNow:
// Immediate check triggered
case <-ticker.C:
// Regular interval check
}
// Check if auto-update is enabled // Check if auto-update is enabled
settings, err := u.Store.Settings() settings, err := u.Store.Settings()
if err != nil { if err != nil {
slog.Error("failed to load settings", "error", err) slog.Error("failed to load settings", "error", err)
time.Sleep(UpdateCheckInterval)
continue continue
} }
if !settings.AutoUpdateEnabled { if !settings.AutoUpdateEnabled {
// When auto-update is disabled, don't check or download anything // When auto-update is disabled, don't check or download anything
slog.Debug("auto-update disabled, skipping check") slog.Debug("auto-update disabled, skipping check")
time.Sleep(UpdateCheckInterval)
continue continue
} }
@ -303,21 +325,14 @@ func (u *Updater) StartBackgroundUpdaterChecker(ctx context.Context, cb func(str
if available { if available {
err := u.DownloadNewRelease(ctx, resp) err := u.DownloadNewRelease(ctx, resp)
if err != nil { if err != nil {
slog.Error(fmt.Sprintf("failed to download new release: %s", err)) slog.Error("failed to download new release", "error", err)
} else { } else {
err = cb(resp.UpdateVersion) err = cb(resp.UpdateVersion)
if err != nil { if err != nil {
slog.Warn(fmt.Sprintf("failed to register update available with tray: %s", err)) slog.Warn("failed to register update available with tray", "error", err)
} }
} }
} }
select {
case <-ctx.Done():
slog.Debug("stopping background update checker")
return
default:
time.Sleep(UpdateCheckInterval)
}
} }
}() }()
} }