feat(config): add notify_on_new_settings option to control migration toast
- commit
- 10db773cb4d22bcccda6c3592adbaa68620c85a5
- author
- bnema · · 2025-12-27 19:05 UTC
- parent
- 3fc796d
- signature
- GPG Unverified
2B82207D370127A0The key is unknown
7 files · +51 -8
M CHANGELOG.md +4 -0
| @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. | |||
| 5 | 5 | ## [Unreleased] | |
| 6 | 6 | ||
| 7 | 7 | ### Added | |
| 8 | + | - **Config migration system**: Detects missing config keys when new settings are added in updates and provides tools to add them. | |
| 9 | + | - `dumber config status`: Shows config file path and number of new settings available. | |
| 10 | + | - `dumber config migrate`: Lists missing keys with types/defaults and adds them to config file. | |
| 11 | + | - GUI toast notification on startup when new settings are available (configurable via `update.notify_on_new_settings`). | |
| 8 | 12 | - **CLI self-update command**: New `dumber update` command to check for and install updates from the command line. | |
| 9 | 13 | - Interactive spinner animation during check and download phases. | |
| 10 | 14 | - `--force` / `-f` flag to skip version check and reinstall the current version. | |
| @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. | |||||
| 5 | ## [Unreleased] | 5 | ## [Unreleased] | ||
| 6 | 6 | ||||
| 7 | ### Added | 7 | ### Added | ||
| 8 | + | - **Config migration system**: Detects missing config keys when new settings are added in updates and provides tools to add them. | |||
| 9 | + | - `dumber config status`: Shows config file path and number of new settings available. | |||
| 10 | + | - `dumber config migrate`: Lists missing keys with types/defaults and adds them to config file. | |||
| 11 | + | - GUI toast notification on startup when new settings are available (configurable via `update.notify_on_new_settings`). | |||
| 8 | - **CLI self-update command**: New `dumber update` command to check for and install updates from the command line. | 12 | - **CLI self-update command**: New `dumber update` command to check for and install updates from the command line. | ||
| 9 | - Interactive spinner animation during check and download phases. | 13 | - Interactive spinner animation during check and download phases. | ||
| 10 | - `--force` / `-f` flag to skip version check and reinstall the current version. | 14 | - `--force` / `-f` flag to skip version check and reinstall the current version. | ||
M README.md +4 -0
| @@ -261,6 +261,10 @@ sudo apt install va-driver-all | |||
| 261 | 261 | - Clean up data: | |
| 262 | 262 | - `dumber purge` # interactive selection (TUI) | |
| 263 | 263 | - `dumber purge --force` # remove everything (no prompts) | |
| 264 | + | - Manage configuration: | |
| 265 | + | - `dumber config status` # show config path and migration availability | |
| 266 | + | - `dumber config migrate` # add missing default settings to config | |
| 267 | + | - `dumber config migrate --yes` # skip confirmation prompt | |
| 264 | 268 | - Manage sessions: | |
| 265 | 269 | - `dumber sessions` # interactive session browser (TUI) | |
| 266 | 270 | - `dumber sessions list` # list saved sessions | |
| @@ -261,6 +261,10 @@ sudo apt install va-driver-all | |||||
| 261 | - Clean up data: | 261 | - Clean up data: | ||
| 262 | - `dumber purge` # interactive selection (TUI) | 262 | - `dumber purge` # interactive selection (TUI) | ||
| 263 | - `dumber purge --force` # remove everything (no prompts) | 263 | - `dumber purge --force` # remove everything (no prompts) | ||
| 264 | + | - Manage configuration: | |||
| 265 | + | - `dumber config status` # show config path and migration availability | |||
| 266 | + | - `dumber config migrate` # add missing default settings to config | |||
| 267 | + | - `dumber config migrate --yes` # skip confirmation prompt | |||
| 264 | - Manage sessions: | 268 | - Manage sessions: | ||
| 265 | - `dumber sessions` # interactive session browser (TUI) | 269 | - `dumber sessions` # interactive session browser (TUI) | ||
| 266 | - `dumber sessions list` # list saved sessions | 270 | - `dumber sessions list` # list saved sessions | ||
M docs/CONFIG.md +28 -0
| @@ -451,6 +451,34 @@ Notes: | |||
| 451 | 451 | - Filter data is downloaded from `bnema/ublock-webkit-filters` GitHub releases. | |
| 452 | 452 | - Domain whitelist is managed via the database (`content_whitelist` table), not the config file. | |
| 453 | 453 | ||
| 454 | + | ## Update | |
| 455 | + | ||
| 456 | + | | Key | Type | Default | Description | | |
| 457 | + | |-----|------|---------|-------------| | |
| 458 | + | | `update.enable_on_startup` | bool | `true` | Check for updates when browser starts | | |
| 459 | + | | `update.auto_download` | bool | `false` | Automatically download updates in background | | |
| 460 | + | | `update.notify_on_new_settings` | bool | `true` | Show toast notification when new config settings are available | | |
| 461 | + | ||
| 462 | + | **Example:** | |
| 463 | + | ```toml | |
| 464 | + | [update] | |
| 465 | + | enable_on_startup = true # Check for updates on startup | |
| 466 | + | auto_download = false # Don't auto-download (prompt instead) | |
| 467 | + | notify_on_new_settings = true # Show toast when config migration available | |
| 468 | + | ``` | |
| 469 | + | ||
| 470 | + | **CLI Commands:** | |
| 471 | + | ```bash | |
| 472 | + | # Check config status and available migrations | |
| 473 | + | dumber config status | |
| 474 | + | ||
| 475 | + | # Add missing settings with default values | |
| 476 | + | dumber config migrate | |
| 477 | + | ||
| 478 | + | # Skip confirmation prompt | |
| 479 | + | dumber config migrate --yes | |
| 480 | + | ``` | |
| 481 | + | ||
| 454 | 482 | ## Environment Variables | |
| 455 | 483 | ||
| 456 | 484 | All config values can be overridden via environment variables with the prefix `DUMBER_`: | |
| @@ -451,6 +451,34 @@ Notes: | |||||
| 451 | - Filter data is downloaded from `bnema/ublock-webkit-filters` GitHub releases. | 451 | - Filter data is downloaded from `bnema/ublock-webkit-filters` GitHub releases. | ||
| 452 | - Domain whitelist is managed via the database (`content_whitelist` table), not the config file. | 452 | - Domain whitelist is managed via the database (`content_whitelist` table), not the config file. | ||
| 453 | 453 | ||||
| 454 | + | ## Update | |||
| 455 | + | ||||
| 456 | + | | Key | Type | Default | Description | | |||
| 457 | + | |-----|------|---------|-------------| | |||
| 458 | + | | `update.enable_on_startup` | bool | `true` | Check for updates when browser starts | | |||
| 459 | + | | `update.auto_download` | bool | `false` | Automatically download updates in background | | |||
| 460 | + | | `update.notify_on_new_settings` | bool | `true` | Show toast notification when new config settings are available | | |||
| 461 | + | ||||
| 462 | + | **Example:** | |||
| 463 | + | ```toml | |||
| 464 | + | [update] | |||
| 465 | + | enable_on_startup = true # Check for updates on startup | |||
| 466 | + | auto_download = false # Don't auto-download (prompt instead) | |||
| 467 | + | notify_on_new_settings = true # Show toast when config migration available | |||
| 468 | + | ``` | |||
| 469 | + | ||||
| 470 | + | **CLI Commands:** | |||
| 471 | + | ```bash | |||
| 472 | + | # Check config status and available migrations | |||
| 473 | + | dumber config status | |||
| 474 | + | ||||
| 475 | + | # Add missing settings with default values | |||
| 476 | + | dumber config migrate | |||
| 477 | + | ||||
| 478 | + | # Skip confirmation prompt | |||
| 479 | + | dumber config migrate --yes | |||
| 480 | + | ``` | |||
| 481 | + | ||||
| 454 | ## Environment Variables | 482 | ## Environment Variables | ||
| 455 | 483 | ||||
| 456 | All config values can be overridden via environment variables with the prefix `DUMBER_`: | 484 | All config values can be overridden via environment variables with the prefix `DUMBER_`: | ||
M internal/infrastructure/config/defaults.go +3 -2
| @@ -292,8 +292,9 @@ func DefaultConfig() *Config { | |||
| 292 | 292 | WebViewPoolPrewarmCount: defaultWebViewPoolPrewarmCount, | |
| 293 | 293 | }, | |
| 294 | 294 | Update: UpdateConfig{ | |
| 295 | - | EnableOnStartup: true, // Check for updates on startup by default | |
| 296 | - | AutoDownload: false, // Conservative: don't auto-download by default | |
| 295 | + | EnableOnStartup: true, // Check for updates on startup by default | |
| 296 | + | AutoDownload: false, // Conservative: don't auto-download by default | |
| 297 | + | NotifyOnNewSettings: true, // Show toast when new config settings available | |
| 297 | 298 | }, | |
| 298 | 299 | } | |
| 299 | 300 | } | |
| @@ -292,8 +292,9 @@ func DefaultConfig() *Config { | |||||
| 292 | WebViewPoolPrewarmCount: defaultWebViewPoolPrewarmCount, | 292 | WebViewPoolPrewarmCount: defaultWebViewPoolPrewarmCount, | ||
| 293 | }, | 293 | }, | ||
| 294 | Update: UpdateConfig{ | 294 | Update: UpdateConfig{ | ||
| 295 | - | EnableOnStartup: true, // Check for updates on startup by default | 295 | + | EnableOnStartup: true, // Check for updates on startup by default |
| 296 | - | AutoDownload: false, // Conservative: don't auto-download by default | 296 | + | AutoDownload: false, // Conservative: don't auto-download by default |
| 297 | + | NotifyOnNewSettings: true, // Show toast when new config settings available | |||
| 297 | }, | 298 | }, | ||
| 298 | } | 299 | } | ||
| 299 | } | 300 | } | ||
M internal/infrastructure/config/loader.go +1 -0
| @@ -460,6 +460,7 @@ func (m *Manager) setSessionDefaults(defaults *Config) { | |||
| 460 | 460 | func (m *Manager) setUpdateDefaults(defaults *Config) { | |
| 461 | 461 | m.viper.SetDefault("update.enable_on_startup", defaults.Update.EnableOnStartup) | |
| 462 | 462 | m.viper.SetDefault("update.auto_download", defaults.Update.AutoDownload) | |
| 463 | + | m.viper.SetDefault("update.notify_on_new_settings", defaults.Update.NotifyOnNewSettings) | |
| 463 | 464 | } | |
| 464 | 465 | ||
| 465 | 466 | // New returns a new default configuration instance. | |
| @@ -460,6 +460,7 @@ func (m *Manager) setSessionDefaults(defaults *Config) { | |||||
| 460 | func (m *Manager) setUpdateDefaults(defaults *Config) { | 460 | func (m *Manager) setUpdateDefaults(defaults *Config) { | ||
| 461 | m.viper.SetDefault("update.enable_on_startup", defaults.Update.EnableOnStartup) | 461 | m.viper.SetDefault("update.enable_on_startup", defaults.Update.EnableOnStartup) | ||
| 462 | m.viper.SetDefault("update.auto_download", defaults.Update.AutoDownload) | 462 | m.viper.SetDefault("update.auto_download", defaults.Update.AutoDownload) | ||
| 463 | + | m.viper.SetDefault("update.notify_on_new_settings", defaults.Update.NotifyOnNewSettings) | |||
| 463 | } | 464 | } | ||
| 464 | 465 | ||||
| 465 | // New returns a new default configuration instance. | 466 | // New returns a new default configuration instance. | ||
M internal/infrastructure/config/schema.go +3 -0
| @@ -294,6 +294,9 @@ type UpdateConfig struct { | |||
| 294 | 294 | // When enabled, updates are applied on browser exit. | |
| 295 | 295 | // Default: false | |
| 296 | 296 | AutoDownload bool `mapstructure:"auto_download" yaml:"auto_download" toml:"auto_download"` | |
| 297 | + | // NotifyOnNewSettings shows a toast notification on startup when new config settings are available. | |
| 298 | + | // Default: true | |
| 299 | + | NotifyOnNewSettings bool `mapstructure:"notify_on_new_settings" yaml:"notify_on_new_settings" toml:"notify_on_new_settings"` | |
| 297 | 300 | } | |
| 298 | 301 | ||
| 299 | 302 | // WorkspaceConfig captures layout, pane, and tab behavior preferences. | |
| @@ -294,6 +294,9 @@ type UpdateConfig struct { | |||||
| 294 | // When enabled, updates are applied on browser exit. | 294 | // When enabled, updates are applied on browser exit. | ||
| 295 | // Default: false | 295 | // Default: false | ||
| 296 | AutoDownload bool `mapstructure:"auto_download" yaml:"auto_download" toml:"auto_download"` | 296 | AutoDownload bool `mapstructure:"auto_download" yaml:"auto_download" toml:"auto_download"` | ||
| 297 | + | // NotifyOnNewSettings shows a toast notification on startup when new config settings are available. | |||
| 298 | + | // Default: true | |||
| 299 | + | NotifyOnNewSettings bool `mapstructure:"notify_on_new_settings" yaml:"notify_on_new_settings" toml:"notify_on_new_settings"` | |||
| 297 | } | 300 | } | ||
| 298 | 301 | ||||
| 299 | // WorkspaceConfig captures layout, pane, and tab behavior preferences. | 302 | // WorkspaceConfig captures layout, pane, and tab behavior preferences. | ||
M internal/ui/config_migration.go +8 -6
| @@ -12,6 +12,7 @@ import ( | |||
| 12 | 12 | // checkConfigMigration checks if user config needs migration and shows a toast. | |
| 13 | 13 | func (a *App) checkConfigMigration(ctx context.Context) { | |
| 14 | 14 | log := logging.FromContext(ctx) | |
| 15 | + | cfg := config.Get() | |
| 15 | 16 | ||
| 16 | 17 | migrator := config.NewMigrator() | |
| 17 | 18 | result, err := migrator.CheckMigration() | |
| @@ -24,13 +25,14 @@ func (a *App) checkConfigMigration(ctx context.Context) { | |||
| 24 | 25 | return // No migration needed | |
| 25 | 26 | } | |
| 26 | 27 | ||
| 27 | - | // Show toast notification | |
| 28 | - | if a.appToaster != nil { | |
| 29 | - | msg := fmt.Sprintf("Config has %d new settings. Run 'dumber config migrate'", len(result.MissingKeys)) | |
| 30 | - | a.appToaster.Show(ctx, msg, component.ToastInfo) | |
| 31 | - | } | |
| 32 | - | ||
| 28 | + | // Log is always shown for debugging purposes | |
| 33 | 29 | log.Info(). | |
| 34 | 30 | Int("missing_keys", len(result.MissingKeys)). | |
| 35 | 31 | Msg("config migration available") | |
| 32 | + | ||
| 33 | + | // Show toast notification if enabled | |
| 34 | + | if cfg.Update.NotifyOnNewSettings && a.appToaster != nil { | |
| 35 | + | msg := fmt.Sprintf("Config has %d new settings. Run 'dumber config migrate'", len(result.MissingKeys)) | |
| 36 | + | a.appToaster.Show(ctx, msg, component.ToastInfo) | |
| 37 | + | } | |
| 36 | 38 | } | |
| @@ -12,6 +12,7 @@ import ( | |||||
| 12 | // checkConfigMigration checks if user config needs migration and shows a toast. | 12 | // checkConfigMigration checks if user config needs migration and shows a toast. | ||
| 13 | func (a *App) checkConfigMigration(ctx context.Context) { | 13 | func (a *App) checkConfigMigration(ctx context.Context) { | ||
| 14 | log := logging.FromContext(ctx) | 14 | log := logging.FromContext(ctx) | ||
| 15 | + | cfg := config.Get() | |||
| 15 | 16 | ||||
| 16 | migrator := config.NewMigrator() | 17 | migrator := config.NewMigrator() | ||
| 17 | result, err := migrator.CheckMigration() | 18 | result, err := migrator.CheckMigration() | ||
| @@ -24,13 +25,14 @@ func (a *App) checkConfigMigration(ctx context.Context) { | |||||
| 24 | return // No migration needed | 25 | return // No migration needed | ||
| 25 | } | 26 | } | ||
| 26 | 27 | ||||
| 27 | - | // Show toast notification | 28 | + | // Log is always shown for debugging purposes |
| 28 | - | if a.appToaster != nil { | |||
| 29 | - | msg := fmt.Sprintf("Config has %d new settings. Run 'dumber config migrate'", len(result.MissingKeys)) | |||
| 30 | - | a.appToaster.Show(ctx, msg, component.ToastInfo) | |||
| 31 | - | } | |||
| 32 | - | ||||
| 33 | log.Info(). | 29 | log.Info(). | ||
| 34 | Int("missing_keys", len(result.MissingKeys)). | 30 | Int("missing_keys", len(result.MissingKeys)). | ||
| 35 | Msg("config migration available") | 31 | Msg("config migration available") | ||
| 32 | + | ||||
| 33 | + | // Show toast notification if enabled | |||
| 34 | + | if cfg.Update.NotifyOnNewSettings && a.appToaster != nil { | |||
| 35 | + | msg := fmt.Sprintf("Config has %d new settings. Run 'dumber config migrate'", len(result.MissingKeys)) | |||
| 36 | + | a.appToaster.Show(ctx, msg, component.ToastInfo) | |||
| 37 | + | } | |||
| 36 | } | 38 | } | ||