Merge pull request #334 from bnema/fix/favorites-shortcuts-noop
fix(favorites): migrate sidebar shortcuts
14 files · +322 -39
M docs/reference/keybindings.md +1 -1
| @@ -168,7 +168,7 @@ keys = ["alt+f"] | |||
| 168 | 168 | [workspace.shortcuts.actions.toggle-history-systemview] | |
| 169 | 169 | keys = ["ctrl+h"] | |
| 170 | 170 | ||
| 171 | - | [workspace.shortcuts.actions.toggle-favorites-systemview] | |
| 171 | + | [workspace.shortcuts.actions.toggle-favorites-sidebar] | |
| 172 | 172 | keys = ["ctrl+b"] | |
| 173 | 173 | ||
| 174 | 174 | [workspace.shortcuts.actions.toggle-current-page-favorite] | |
| @@ -168,7 +168,7 @@ keys = ["alt+f"] | |||||
| 168 | [workspace.shortcuts.actions.toggle-history-systemview] | 168 | [workspace.shortcuts.actions.toggle-history-systemview] | ||
| 169 | keys = ["ctrl+h"] | 169 | keys = ["ctrl+h"] | ||
| 170 | 170 | ||||
| 171 | - | [workspace.shortcuts.actions.toggle-favorites-systemview] | 171 | + | [workspace.shortcuts.actions.toggle-favorites-sidebar] |
| 172 | keys = ["ctrl+b"] | 172 | keys = ["ctrl+b"] | ||
| 173 | 173 | ||||
| 174 | [workspace.shortcuts.actions.toggle-current-page-favorite] | 174 | [workspace.shortcuts.actions.toggle-current-page-favorite] | ||
M internal/infrastructure/config/defaults.go +1 -1
| @@ -340,7 +340,7 @@ func DefaultConfig() *Config { | |||
| 340 | 340 | Actions: map[string]ActionBinding{ | |
| 341 | 341 | "toggle-floating-pane": {Keys: []string{"alt+f"}, Desc: "Toggle floating pane"}, | |
| 342 | 342 | "toggle-history-systemview": {Keys: []string{"ctrl+h"}, Desc: "Toggle History in right split"}, | |
| 343 | - | "toggle-favorites-systemview": {Keys: []string{"ctrl+b"}, Desc: "Toggle Favorites sidebar"}, | |
| 343 | + | "toggle-favorites-sidebar": {Keys: []string{"ctrl+b"}, Desc: "Toggle Favorites sidebar"}, | |
| 344 | 344 | "toggle-current-page-favorite": {Keys: []string{"ctrl+d"}, Desc: "Add/remove current page favorite"}, | |
| 345 | 345 | "toggle-config-systemview": {Keys: []string{}, Desc: "Toggle Config in right split"}, | |
| 346 | 346 | "close-pane": {Keys: []string{"ctrl+w"}, Desc: "Close active pane"}, | |
| @@ -340,7 +340,7 @@ func DefaultConfig() *Config { | |||||
| 340 | Actions: map[string]ActionBinding{ | 340 | Actions: map[string]ActionBinding{ | ||
| 341 | "toggle-floating-pane": {Keys: []string{"alt+f"}, Desc: "Toggle floating pane"}, | 341 | "toggle-floating-pane": {Keys: []string{"alt+f"}, Desc: "Toggle floating pane"}, | ||
| 342 | "toggle-history-systemview": {Keys: []string{"ctrl+h"}, Desc: "Toggle History in right split"}, | 342 | "toggle-history-systemview": {Keys: []string{"ctrl+h"}, Desc: "Toggle History in right split"}, | ||
| 343 | - | "toggle-favorites-systemview": {Keys: []string{"ctrl+b"}, Desc: "Toggle Favorites sidebar"}, | 343 | + | "toggle-favorites-sidebar": {Keys: []string{"ctrl+b"}, Desc: "Toggle Favorites sidebar"}, |
| 344 | "toggle-current-page-favorite": {Keys: []string{"ctrl+d"}, Desc: "Add/remove current page favorite"}, | 344 | "toggle-current-page-favorite": {Keys: []string{"ctrl+d"}, Desc: "Add/remove current page favorite"}, | ||
| 345 | "toggle-config-systemview": {Keys: []string{}, Desc: "Toggle Config in right split"}, | 345 | "toggle-config-systemview": {Keys: []string{}, Desc: "Toggle Config in right split"}, | ||
| 346 | "close-pane": {Keys: []string{"ctrl+w"}, Desc: "Close active pane"}, | 346 | "close-pane": {Keys: []string{"ctrl+w"}, Desc: "Close active pane"}, | ||
M internal/infrastructure/config/defaults_test.go +1 -1
| @@ -41,7 +41,7 @@ func TestDefaultConfig_CoreDefaults(t *testing.T) { | |||
| 41 | 41 | ||
| 42 | 42 | // System view shortcuts are first-class global actions. | |
| 43 | 43 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-history-systemview", []string{"ctrl+h"}) | |
| 44 | - | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-favorites-systemview", []string{"ctrl+b"}) | |
| 44 | + | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-favorites-sidebar", []string{"ctrl+b"}) | |
| 45 | 45 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-current-page-favorite", []string{"ctrl+d"}) | |
| 46 | 46 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-config-systemview", []string{}) | |
| 47 | 47 | ||
| @@ -41,7 +41,7 @@ func TestDefaultConfig_CoreDefaults(t *testing.T) { | |||||
| 41 | 41 | ||||
| 42 | // System view shortcuts are first-class global actions. | 42 | // System view shortcuts are first-class global actions. | ||
| 43 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-history-systemview", []string{"ctrl+h"}) | 43 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-history-systemview", []string{"ctrl+h"}) | ||
| 44 | - | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-favorites-systemview", []string{"ctrl+b"}) | 44 | + | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-favorites-sidebar", []string{"ctrl+b"}) |
| 45 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-current-page-favorite", []string{"ctrl+d"}) | 45 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-current-page-favorite", []string{"ctrl+d"}) | ||
| 46 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-config-systemview", []string{}) | 46 | requireActionBinding(t, cfg.Workspace.Shortcuts.Actions, "toggle-config-systemview", []string{}) | ||
| 47 | 47 | ||||
M internal/infrastructure/config/loader.go +0 -4
| @@ -175,10 +175,6 @@ func (m *Manager) transformLegacyConfig() { | |||
| 175 | 175 | transformer.TransformLegacyPopupsToBrowsingContexts(rawConfig) | |
| 176 | 176 | } | |
| 177 | 177 | ||
| 178 | - | // Merge newly added default actions into in-memory config so existing persisted | |
| 179 | - | // action maps keep working before the user writes a migrated config to disk. | |
| 180 | - | configMigrator.mergeMissingDefaultActions(rawConfig) | |
| 181 | - | ||
| 182 | 178 | // Apply transformed config back to viper | |
| 183 | 179 | for key, value := range rawConfig { | |
| 184 | 180 | m.viper.Set(key, value) | |
| @@ -175,10 +175,6 @@ func (m *Manager) transformLegacyConfig() { | |||||
| 175 | transformer.TransformLegacyPopupsToBrowsingContexts(rawConfig) | 175 | transformer.TransformLegacyPopupsToBrowsingContexts(rawConfig) | ||
| 176 | } | 176 | } | ||
| 177 | 177 | ||||
| 178 | - | // Merge newly added default actions into in-memory config so existing persisted | |||
| 179 | - | // action maps keep working before the user writes a migrated config to disk. | |||
| 180 | - | configMigrator.mergeMissingDefaultActions(rawConfig) | |||
| 181 | - | ||||
| 182 | // Apply transformed config back to viper | 178 | // Apply transformed config back to viper | ||
| 183 | for key, value := range rawConfig { | 179 | for key, value := range rawConfig { | ||
| 184 | m.viper.Set(key, value) | 180 | m.viper.Set(key, value) | ||
M internal/infrastructure/config/loader_actions_test.go +59 -4
| @@ -36,7 +36,7 @@ touchpad_navigation_max_vertical_ratio = 2.0 | |||
| 36 | 36 | assert.InDelta(t, 2.0, cfg.Engine.CEF.Input.TouchpadNavigationMaxVerticalRatio, 0.001) | |
| 37 | 37 | } | |
| 38 | 38 | ||
| 39 | - | func TestManagerLoad_MergesMissingPaneModeActionsInMemory(t *testing.T) { | |
| 39 | + | func TestManagerLoad_DoesNotMergeMissingPaneModeActionsInMemory(t *testing.T) { | |
| 40 | 40 | home := t.TempDir() | |
| 41 | 41 | t.Setenv("HOME", home) | |
| 42 | 42 | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |
| @@ -64,10 +64,65 @@ desc = "Custom stack pane" | |||
| 64 | 64 | cfg := mgr.Get() | |
| 65 | 65 | require.NotNil(t, cfg) | |
| 66 | 66 | ||
| 67 | - | eject, ok := cfg.Workspace.PaneMode.Actions["eject-pane-to-window"] | |
| 68 | - | require.True(t, ok) | |
| 69 | - | assert.Equal(t, []string{"w"}, eject.Keys) | |
| 67 | + | _, ok := cfg.Workspace.PaneMode.Actions["eject-pane-to-window"] | |
| 68 | + | assert.False(t, ok) | |
| 70 | 69 | ||
| 71 | 70 | stack := cfg.Workspace.PaneMode.Actions["stack-pane"] | |
| 72 | 71 | assert.Equal(t, "Custom stack pane", stack.Desc) | |
| 73 | 72 | } | |
| 73 | + | ||
| 74 | + | func TestManagerLoad_DoesNotMigrateLegacyFavoritesShortcut(t *testing.T) { | |
| 75 | + | home := t.TempDir() | |
| 76 | + | t.Setenv("HOME", home) | |
| 77 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |
| 78 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |
| 79 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |
| 80 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |
| 81 | + | ||
| 82 | + | configFile, err := GetConfigFile() | |
| 83 | + | require.NoError(t, err) | |
| 84 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |
| 85 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |
| 86 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |
| 87 | + | keys = [] | |
| 88 | + | desc = "Custom favorites shortcut" | |
| 89 | + | `), 0o644)) | |
| 90 | + | ||
| 91 | + | mgr, err := NewManager() | |
| 92 | + | require.NoError(t, err) | |
| 93 | + | require.NoError(t, mgr.Load()) | |
| 94 | + | ||
| 95 | + | favorites := mgr.Get().Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |
| 96 | + | assert.Empty(t, favorites.Keys) | |
| 97 | + | assert.Equal(t, "Custom favorites shortcut", favorites.Desc) | |
| 98 | + | } | |
| 99 | + | ||
| 100 | + | func TestManagerLoad_DoesNotMigrateLegacyFavoritesShortcutDefault(t *testing.T) { | |
| 101 | + | home := t.TempDir() | |
| 102 | + | t.Setenv("HOME", home) | |
| 103 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |
| 104 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |
| 105 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |
| 106 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |
| 107 | + | ||
| 108 | + | configFile, err := GetConfigFile() | |
| 109 | + | require.NoError(t, err) | |
| 110 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |
| 111 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |
| 112 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |
| 113 | + | keys = [] | |
| 114 | + | desc = "Toggle Favorites in right split" | |
| 115 | + | `), 0o644)) | |
| 116 | + | ||
| 117 | + | mgr, err := NewManager() | |
| 118 | + | require.NoError(t, err) | |
| 119 | + | require.NoError(t, mgr.Load()) | |
| 120 | + | ||
| 121 | + | cfg := mgr.Get() | |
| 122 | + | require.NotNil(t, cfg) | |
| 123 | + | favorites := cfg.Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |
| 124 | + | assert.Empty(t, favorites.Keys) | |
| 125 | + | assert.Equal(t, "Toggle Favorites in right split", favorites.Desc) | |
| 126 | + | _, ok := cfg.Workspace.Shortcuts.Actions["toggle-favorites-sidebar"] | |
| 127 | + | assert.False(t, ok) | |
| 128 | + | } | |
| @@ -36,7 +36,7 @@ touchpad_navigation_max_vertical_ratio = 2.0 | |||||
| 36 | assert.InDelta(t, 2.0, cfg.Engine.CEF.Input.TouchpadNavigationMaxVerticalRatio, 0.001) | 36 | assert.InDelta(t, 2.0, cfg.Engine.CEF.Input.TouchpadNavigationMaxVerticalRatio, 0.001) | ||
| 37 | } | 37 | } | ||
| 38 | 38 | ||||
| 39 | - | func TestManagerLoad_MergesMissingPaneModeActionsInMemory(t *testing.T) { | 39 | + | func TestManagerLoad_DoesNotMergeMissingPaneModeActionsInMemory(t *testing.T) { |
| 40 | home := t.TempDir() | 40 | home := t.TempDir() | ||
| 41 | t.Setenv("HOME", home) | 41 | t.Setenv("HOME", home) | ||
| 42 | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | 42 | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | ||
| @@ -64,10 +64,65 @@ desc = "Custom stack pane" | |||||
| 64 | cfg := mgr.Get() | 64 | cfg := mgr.Get() | ||
| 65 | require.NotNil(t, cfg) | 65 | require.NotNil(t, cfg) | ||
| 66 | 66 | ||||
| 67 | - | eject, ok := cfg.Workspace.PaneMode.Actions["eject-pane-to-window"] | 67 | + | _, ok := cfg.Workspace.PaneMode.Actions["eject-pane-to-window"] |
| 68 | - | require.True(t, ok) | 68 | + | assert.False(t, ok) |
| 69 | - | assert.Equal(t, []string{"w"}, eject.Keys) | |||
| 70 | 69 | ||||
| 71 | stack := cfg.Workspace.PaneMode.Actions["stack-pane"] | 70 | stack := cfg.Workspace.PaneMode.Actions["stack-pane"] | ||
| 72 | assert.Equal(t, "Custom stack pane", stack.Desc) | 71 | assert.Equal(t, "Custom stack pane", stack.Desc) | ||
| 73 | } | 72 | } | ||
| 73 | + | ||||
| 74 | + | func TestManagerLoad_DoesNotMigrateLegacyFavoritesShortcut(t *testing.T) { | |||
| 75 | + | home := t.TempDir() | |||
| 76 | + | t.Setenv("HOME", home) | |||
| 77 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |||
| 78 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |||
| 79 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |||
| 80 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |||
| 81 | + | ||||
| 82 | + | configFile, err := GetConfigFile() | |||
| 83 | + | require.NoError(t, err) | |||
| 84 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |||
| 85 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |||
| 86 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |||
| 87 | + | keys = [] | |||
| 88 | + | desc = "Custom favorites shortcut" | |||
| 89 | + | `), 0o644)) | |||
| 90 | + | ||||
| 91 | + | mgr, err := NewManager() | |||
| 92 | + | require.NoError(t, err) | |||
| 93 | + | require.NoError(t, mgr.Load()) | |||
| 94 | + | ||||
| 95 | + | favorites := mgr.Get().Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |||
| 96 | + | assert.Empty(t, favorites.Keys) | |||
| 97 | + | assert.Equal(t, "Custom favorites shortcut", favorites.Desc) | |||
| 98 | + | } | |||
| 99 | + | ||||
| 100 | + | func TestManagerLoad_DoesNotMigrateLegacyFavoritesShortcutDefault(t *testing.T) { | |||
| 101 | + | home := t.TempDir() | |||
| 102 | + | t.Setenv("HOME", home) | |||
| 103 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |||
| 104 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |||
| 105 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |||
| 106 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |||
| 107 | + | ||||
| 108 | + | configFile, err := GetConfigFile() | |||
| 109 | + | require.NoError(t, err) | |||
| 110 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |||
| 111 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |||
| 112 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |||
| 113 | + | keys = [] | |||
| 114 | + | desc = "Toggle Favorites in right split" | |||
| 115 | + | `), 0o644)) | |||
| 116 | + | ||||
| 117 | + | mgr, err := NewManager() | |||
| 118 | + | require.NoError(t, err) | |||
| 119 | + | require.NoError(t, mgr.Load()) | |||
| 120 | + | ||||
| 121 | + | cfg := mgr.Get() | |||
| 122 | + | require.NotNil(t, cfg) | |||
| 123 | + | favorites := cfg.Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |||
| 124 | + | assert.Empty(t, favorites.Keys) | |||
| 125 | + | assert.Equal(t, "Toggle Favorites in right split", favorites.Desc) | |||
| 126 | + | _, ok := cfg.Workspace.Shortcuts.Actions["toggle-favorites-sidebar"] | |||
| 127 | + | assert.False(t, ok) | |||
| 128 | + | } | |||
M internal/infrastructure/config/migrate.go +127 -13
| @@ -25,11 +25,6 @@ type Migrator struct { | |||
| 25 | 25 | defaultConfig *Config | |
| 26 | 26 | } | |
| 27 | 27 | ||
| 28 | - | // configMigrator reuses the default-action metadata needed during config load. | |
| 29 | - | // It is immutable after initialization; per-command migration still constructs | |
| 30 | - | // explicit Migrator instances when callers need independent state. | |
| 31 | - | var configMigrator = NewMigrator() | |
| 32 | - | ||
| 33 | 28 | // NewMigrator creates a new Migrator instance. | |
| 34 | 29 | func NewMigrator() *Migrator { | |
| 35 | 30 | v := viper.New() | |
| @@ -58,17 +53,22 @@ func (m *Migrator) CheckMigration() (*port.MigrationResult, error) { | |||
| 58 | 53 | return nil, nil | |
| 59 | 54 | } | |
| 60 | 55 | ||
| 61 | - | // Get user-defined keys from the TOML file | |
| 62 | - | userKeys, err := m.getUserConfigKeys(configFile) | |
| 56 | + | userKeysWithValues, err := m.getUserConfigKeysWithValues(configFile) | |
| 63 | 57 | if err != nil { | |
| 64 | 58 | return nil, fmt.Errorf("failed to parse user config: %w", err) | |
| 65 | 59 | } | |
| 66 | 60 | ||
| 61 | + | userKeys := make(map[string]bool, len(userKeysWithValues)) | |
| 62 | + | for key := range userKeysWithValues { | |
| 63 | + | userKeys[key] = true | |
| 64 | + | } | |
| 65 | + | ||
| 67 | 66 | // Get all default keys | |
| 68 | 67 | defaultKeys := m.getAllDefaultKeys() | |
| 69 | 68 | ||
| 70 | 69 | // Find missing keys (in defaults but not in user config) | |
| 71 | 70 | missingKeys := m.findMissingKeys(defaultKeys, userKeys) | |
| 71 | + | missingKeys = appendUniqueKeys(missingKeys, m.detectMissingDefaultActions(userKeysWithValues)) | |
| 72 | 72 | ||
| 73 | 73 | if len(missingKeys) == 0 { | |
| 74 | 74 | return nil, nil | |
| @@ -119,13 +119,16 @@ func (m *Migrator) DetectChanges() ([]port.KeyChange, error) { | |||
| 119 | 119 | userKeySet[k] = true | |
| 120 | 120 | } | |
| 121 | 121 | ||
| 122 | - | legacyBrowsingContextRenames := m.detectLegacyBrowsingContextRenames(rawUserKeysWithValues) | |
| 122 | + | legacyRenames := append( | |
| 123 | + | m.detectLegacyBrowsingContextRenames(rawUserKeysWithValues), | |
| 124 | + | m.detectLegacyFavoritesSidebarRename(userKeysWithValues)..., | |
| 125 | + | ) | |
| 123 | 126 | var changes []port.KeyChange | |
| 124 | - | changes = append(changes, legacyBrowsingContextRenames...) | |
| 127 | + | changes = append(changes, legacyRenames...) | |
| 125 | 128 | ||
| 126 | - | handledLegacyDeprecatedKeys := make(map[string]bool, len(legacyBrowsingContextRenames)) | |
| 127 | - | handledLegacyMissingKeys := make(map[string]bool, len(legacyBrowsingContextRenames)) | |
| 128 | - | for _, change := range legacyBrowsingContextRenames { | |
| 129 | + | handledLegacyDeprecatedKeys := make(map[string]bool, len(legacyRenames)) | |
| 130 | + | handledLegacyMissingKeys := make(map[string]bool, len(legacyRenames)) | |
| 131 | + | for _, change := range legacyRenames { | |
| 129 | 132 | handledLegacyDeprecatedKeys[change.OldKey] = true | |
| 130 | 133 | handledLegacyMissingKeys[change.NewKey] = true | |
| 131 | 134 | } | |
| @@ -444,10 +447,11 @@ func (m *Migrator) Migrate() ([]string, error) { | |||
| 444 | 447 | } | |
| 445 | 448 | } | |
| 446 | 449 | ||
| 447 | - | // Remove deprecated and renamed keys from the raw config | |
| 450 | + | // Remove deprecated and renamed keys from the raw config. | |
| 448 | 451 | for key := range keysToRemove { | |
| 449 | 452 | m.deleteNestedKey(rawConfig, key) | |
| 450 | 453 | } | |
| 454 | + | m.upgradeLegacyFavoritesSidebarDefault(rawConfig) | |
| 451 | 455 | m.mergeMissingDefaultActions(rawConfig) | |
| 452 | 456 | ||
| 453 | 457 | // Create a new Viper instance with defaults for added keys | |
| @@ -723,6 +727,31 @@ func (m *Migrator) getRawUserConfigKeysWithValues(configFile string) (map[string | |||
| 723 | 727 | return result, nil | |
| 724 | 728 | } | |
| 725 | 729 | ||
| 730 | + | func (m *Migrator) detectLegacyFavoritesSidebarRename(userKeys map[string]any) []port.KeyChange { | |
| 731 | + | const ( | |
| 732 | + | actionsKey = "workspace.shortcuts.actions" | |
| 733 | + | legacyName = "toggle-favorites-systemview" | |
| 734 | + | newName = "toggle-favorites-sidebar" | |
| 735 | + | ) | |
| 736 | + | ||
| 737 | + | actionsValue, ok := userKeys[actionsKey] | |
| 738 | + | if !ok { | |
| 739 | + | return nil | |
| 740 | + | } | |
| 741 | + | actions, ok := m.toStringAnyMap(actionsValue) | |
| 742 | + | if !ok || actions[legacyName] == nil || actions[newName] != nil { | |
| 743 | + | return nil | |
| 744 | + | } | |
| 745 | + | ||
| 746 | + | return []port.KeyChange{{ | |
| 747 | + | Type: port.KeyChangeRenamed, | |
| 748 | + | OldKey: actionsKey + "." + legacyName, | |
| 749 | + | NewKey: actionsKey + "." + newName, | |
| 750 | + | OldValue: m.formatValue(actions[legacyName]), | |
| 751 | + | NewValue: m.formatValue(m.defaultConfig.Workspace.Shortcuts.Actions[newName]), | |
| 752 | + | }} | |
| 753 | + | } | |
| 754 | + | ||
| 726 | 755 | func (m *Migrator) detectLegacyBrowsingContextRenames(rawUserKeys map[string]any) []port.KeyChange { | |
| 727 | 756 | type renamePair struct { | |
| 728 | 757 | oldKey string | |
| @@ -895,6 +924,91 @@ func (m *Migrator) mergeMissingDefaultActions(rawConfig map[string]any) { | |||
| 895 | 924 | } | |
| 896 | 925 | } | |
| 897 | 926 | ||
| 927 | + | func (m *Migrator) upgradeLegacyFavoritesSidebarDefault(rawConfig map[string]any) { | |
| 928 | + | const ( | |
| 929 | + | actionsKey = "workspace.shortcuts.actions" | |
| 930 | + | actionName = "toggle-favorites-sidebar" | |
| 931 | + | ) | |
| 932 | + | ||
| 933 | + | actionsValue := m.getNestedValue(rawConfig, actionsKey) | |
| 934 | + | actions, ok := m.toStringAnyMap(actionsValue) | |
| 935 | + | if !ok { | |
| 936 | + | return | |
| 937 | + | } | |
| 938 | + | binding, ok := m.actionBindingFromAny(actions[actionName]) | |
| 939 | + | if !ok || !reflect.DeepEqual(binding, entity.ActionBinding{Keys: []string{}, Desc: "Toggle Favorites in right split"}) { | |
| 940 | + | return | |
| 941 | + | } | |
| 942 | + | actions[actionName] = m.defaultConfig.Workspace.Shortcuts.Actions[actionName] | |
| 943 | + | m.setNestedValue(rawConfig, actionsKey, actions) | |
| 944 | + | } | |
| 945 | + | ||
| 946 | + | func (m *Migrator) actionBindingFromAny(value any) (entity.ActionBinding, bool) { | |
| 947 | + | switch v := value.(type) { | |
| 948 | + | case entity.ActionBinding: | |
| 949 | + | return v, true | |
| 950 | + | case map[string]any: | |
| 951 | + | return actionBindingFromMap(v) | |
| 952 | + | default: | |
| 953 | + | mapping, ok := m.toStringAnyMap(value) | |
| 954 | + | if !ok { | |
| 955 | + | return entity.ActionBinding{}, false | |
| 956 | + | } | |
| 957 | + | return actionBindingFromMap(mapping) | |
| 958 | + | } | |
| 959 | + | } | |
| 960 | + | ||
| 961 | + | func actionBindingFromMap(m map[string]any) (entity.ActionBinding, bool) { | |
| 962 | + | var binding entity.ActionBinding | |
| 963 | + | if keysValue, exists := m["keys"]; exists { | |
| 964 | + | keys, ok := stringSliceFromAny(keysValue) | |
| 965 | + | if !ok { | |
| 966 | + | return entity.ActionBinding{}, false | |
| 967 | + | } | |
| 968 | + | binding.Keys = keys | |
| 969 | + | } | |
| 970 | + | if descValue, exists := m["desc"]; exists { | |
| 971 | + | desc, ok := descValue.(string) | |
| 972 | + | if !ok { | |
| 973 | + | return entity.ActionBinding{}, false | |
| 974 | + | } | |
| 975 | + | binding.Desc = desc | |
| 976 | + | } | |
| 977 | + | return binding, true | |
| 978 | + | } | |
| 979 | + | ||
| 980 | + | func stringSliceFromAny(value any) ([]string, bool) { | |
| 981 | + | switch v := value.(type) { | |
| 982 | + | case []string: | |
| 983 | + | return append([]string(nil), v...), true | |
| 984 | + | case []any: | |
| 985 | + | out := make([]string, 0, len(v)) | |
| 986 | + | for _, item := range v { | |
| 987 | + | s, ok := item.(string) | |
| 988 | + | if !ok { | |
| 989 | + | return nil, false | |
| 990 | + | } | |
| 991 | + | out = append(out, s) | |
| 992 | + | } | |
| 993 | + | return out, true | |
| 994 | + | default: | |
| 995 | + | rv := reflect.ValueOf(value) | |
| 996 | + | if rv.Kind() != reflect.Slice { | |
| 997 | + | return nil, false | |
| 998 | + | } | |
| 999 | + | out := make([]string, 0, rv.Len()) | |
| 1000 | + | for i := 0; i < rv.Len(); i++ { | |
| 1001 | + | item := rv.Index(i).Interface() | |
| 1002 | + | s, ok := item.(string) | |
| 1003 | + | if !ok { | |
| 1004 | + | return nil, false | |
| 1005 | + | } | |
| 1006 | + | out = append(out, s) | |
| 1007 | + | } | |
| 1008 | + | return out, true | |
| 1009 | + | } | |
| 1010 | + | } | |
| 1011 | + | ||
| 898 | 1012 | func appendUniqueKeys(base, extra []string) []string { | |
| 899 | 1013 | if len(extra) == 0 { | |
| 900 | 1014 | return base | |
| @@ -25,11 +25,6 @@ type Migrator struct { | |||||
| 25 | defaultConfig *Config | 25 | defaultConfig *Config | ||
| 26 | } | 26 | } | ||
| 27 | 27 | ||||
| 28 | - | // configMigrator reuses the default-action metadata needed during config load. | |||
| 29 | - | // It is immutable after initialization; per-command migration still constructs | |||
| 30 | - | // explicit Migrator instances when callers need independent state. | |||
| 31 | - | var configMigrator = NewMigrator() | |||
| 32 | - | ||||
| 33 | // NewMigrator creates a new Migrator instance. | 28 | // NewMigrator creates a new Migrator instance. | ||
| 34 | func NewMigrator() *Migrator { | 29 | func NewMigrator() *Migrator { | ||
| 35 | v := viper.New() | 30 | v := viper.New() | ||
| @@ -58,17 +53,22 @@ func (m *Migrator) CheckMigration() (*port.MigrationResult, error) { | |||||
| 58 | return nil, nil | 53 | return nil, nil | ||
| 59 | } | 54 | } | ||
| 60 | 55 | ||||
| 61 | - | // Get user-defined keys from the TOML file | 56 | + | userKeysWithValues, err := m.getUserConfigKeysWithValues(configFile) |
| 62 | - | userKeys, err := m.getUserConfigKeys(configFile) | |||
| 63 | if err != nil { | 57 | if err != nil { | ||
| 64 | return nil, fmt.Errorf("failed to parse user config: %w", err) | 58 | return nil, fmt.Errorf("failed to parse user config: %w", err) | ||
| 65 | } | 59 | } | ||
| 66 | 60 | ||||
| 61 | + | userKeys := make(map[string]bool, len(userKeysWithValues)) | |||
| 62 | + | for key := range userKeysWithValues { | |||
| 63 | + | userKeys[key] = true | |||
| 64 | + | } | |||
| 65 | + | ||||
| 67 | // Get all default keys | 66 | // Get all default keys | ||
| 68 | defaultKeys := m.getAllDefaultKeys() | 67 | defaultKeys := m.getAllDefaultKeys() | ||
| 69 | 68 | ||||
| 70 | // Find missing keys (in defaults but not in user config) | 69 | // Find missing keys (in defaults but not in user config) | ||
| 71 | missingKeys := m.findMissingKeys(defaultKeys, userKeys) | 70 | missingKeys := m.findMissingKeys(defaultKeys, userKeys) | ||
| 71 | + | missingKeys = appendUniqueKeys(missingKeys, m.detectMissingDefaultActions(userKeysWithValues)) | |||
| 72 | 72 | ||||
| 73 | if len(missingKeys) == 0 { | 73 | if len(missingKeys) == 0 { | ||
| 74 | return nil, nil | 74 | return nil, nil | ||
| @@ -119,13 +119,16 @@ func (m *Migrator) DetectChanges() ([]port.KeyChange, error) { | |||||
| 119 | userKeySet[k] = true | 119 | userKeySet[k] = true | ||
| 120 | } | 120 | } | ||
| 121 | 121 | ||||
| 122 | - | legacyBrowsingContextRenames := m.detectLegacyBrowsingContextRenames(rawUserKeysWithValues) | 122 | + | legacyRenames := append( |
| 123 | + | m.detectLegacyBrowsingContextRenames(rawUserKeysWithValues), | |||
| 124 | + | m.detectLegacyFavoritesSidebarRename(userKeysWithValues)..., | |||
| 125 | + | ) | |||
| 123 | var changes []port.KeyChange | 126 | var changes []port.KeyChange | ||
| 124 | - | changes = append(changes, legacyBrowsingContextRenames...) | 127 | + | changes = append(changes, legacyRenames...) |
| 125 | 128 | ||||
| 126 | - | handledLegacyDeprecatedKeys := make(map[string]bool, len(legacyBrowsingContextRenames)) | 129 | + | handledLegacyDeprecatedKeys := make(map[string]bool, len(legacyRenames)) |
| 127 | - | handledLegacyMissingKeys := make(map[string]bool, len(legacyBrowsingContextRenames)) | 130 | + | handledLegacyMissingKeys := make(map[string]bool, len(legacyRenames)) |
| 128 | - | for _, change := range legacyBrowsingContextRenames { | 131 | + | for _, change := range legacyRenames { |
| 129 | handledLegacyDeprecatedKeys[change.OldKey] = true | 132 | handledLegacyDeprecatedKeys[change.OldKey] = true | ||
| 130 | handledLegacyMissingKeys[change.NewKey] = true | 133 | handledLegacyMissingKeys[change.NewKey] = true | ||
| 131 | } | 134 | } | ||
| @@ -444,10 +447,11 @@ func (m *Migrator) Migrate() ([]string, error) { | |||||
| 444 | } | 447 | } | ||
| 445 | } | 448 | } | ||
| 446 | 449 | ||||
| 447 | - | // Remove deprecated and renamed keys from the raw config | 450 | + | // Remove deprecated and renamed keys from the raw config. |
| 448 | for key := range keysToRemove { | 451 | for key := range keysToRemove { | ||
| 449 | m.deleteNestedKey(rawConfig, key) | 452 | m.deleteNestedKey(rawConfig, key) | ||
| 450 | } | 453 | } | ||
| 454 | + | m.upgradeLegacyFavoritesSidebarDefault(rawConfig) | |||
| 451 | m.mergeMissingDefaultActions(rawConfig) | 455 | m.mergeMissingDefaultActions(rawConfig) | ||
| 452 | 456 | ||||
| 453 | // Create a new Viper instance with defaults for added keys | 457 | // Create a new Viper instance with defaults for added keys | ||
| @@ -723,6 +727,31 @@ func (m *Migrator) getRawUserConfigKeysWithValues(configFile string) (map[string | |||||
| 723 | return result, nil | 727 | return result, nil | ||
| 724 | } | 728 | } | ||
| 725 | 729 | ||||
| 730 | + | func (m *Migrator) detectLegacyFavoritesSidebarRename(userKeys map[string]any) []port.KeyChange { | |||
| 731 | + | const ( | |||
| 732 | + | actionsKey = "workspace.shortcuts.actions" | |||
| 733 | + | legacyName = "toggle-favorites-systemview" | |||
| 734 | + | newName = "toggle-favorites-sidebar" | |||
| 735 | + | ) | |||
| 736 | + | ||||
| 737 | + | actionsValue, ok := userKeys[actionsKey] | |||
| 738 | + | if !ok { | |||
| 739 | + | return nil | |||
| 740 | + | } | |||
| 741 | + | actions, ok := m.toStringAnyMap(actionsValue) | |||
| 742 | + | if !ok || actions[legacyName] == nil || actions[newName] != nil { | |||
| 743 | + | return nil | |||
| 744 | + | } | |||
| 745 | + | ||||
| 746 | + | return []port.KeyChange{{ | |||
| 747 | + | Type: port.KeyChangeRenamed, | |||
| 748 | + | OldKey: actionsKey + "." + legacyName, | |||
| 749 | + | NewKey: actionsKey + "." + newName, | |||
| 750 | + | OldValue: m.formatValue(actions[legacyName]), | |||
| 751 | + | NewValue: m.formatValue(m.defaultConfig.Workspace.Shortcuts.Actions[newName]), | |||
| 752 | + | }} | |||
| 753 | + | } | |||
| 754 | + | ||||
| 726 | func (m *Migrator) detectLegacyBrowsingContextRenames(rawUserKeys map[string]any) []port.KeyChange { | 755 | func (m *Migrator) detectLegacyBrowsingContextRenames(rawUserKeys map[string]any) []port.KeyChange { | ||
| 727 | type renamePair struct { | 756 | type renamePair struct { | ||
| 728 | oldKey string | 757 | oldKey string | ||
| @@ -895,6 +924,91 @@ func (m *Migrator) mergeMissingDefaultActions(rawConfig map[string]any) { | |||||
| 895 | } | 924 | } | ||
| 896 | } | 925 | } | ||
| 897 | 926 | ||||
| 927 | + | func (m *Migrator) upgradeLegacyFavoritesSidebarDefault(rawConfig map[string]any) { | |||
| 928 | + | const ( | |||
| 929 | + | actionsKey = "workspace.shortcuts.actions" | |||
| 930 | + | actionName = "toggle-favorites-sidebar" | |||
| 931 | + | ) | |||
| 932 | + | ||||
| 933 | + | actionsValue := m.getNestedValue(rawConfig, actionsKey) | |||
| 934 | + | actions, ok := m.toStringAnyMap(actionsValue) | |||
| 935 | + | if !ok { | |||
| 936 | + | return | |||
| 937 | + | } | |||
| 938 | + | binding, ok := m.actionBindingFromAny(actions[actionName]) | |||
| 939 | + | if !ok || !reflect.DeepEqual(binding, entity.ActionBinding{Keys: []string{}, Desc: "Toggle Favorites in right split"}) { | |||
| 940 | + | return | |||
| 941 | + | } | |||
| 942 | + | actions[actionName] = m.defaultConfig.Workspace.Shortcuts.Actions[actionName] | |||
| 943 | + | m.setNestedValue(rawConfig, actionsKey, actions) | |||
| 944 | + | } | |||
| 945 | + | ||||
| 946 | + | func (m *Migrator) actionBindingFromAny(value any) (entity.ActionBinding, bool) { | |||
| 947 | + | switch v := value.(type) { | |||
| 948 | + | case entity.ActionBinding: | |||
| 949 | + | return v, true | |||
| 950 | + | case map[string]any: | |||
| 951 | + | return actionBindingFromMap(v) | |||
| 952 | + | default: | |||
| 953 | + | mapping, ok := m.toStringAnyMap(value) | |||
| 954 | + | if !ok { | |||
| 955 | + | return entity.ActionBinding{}, false | |||
| 956 | + | } | |||
| 957 | + | return actionBindingFromMap(mapping) | |||
| 958 | + | } | |||
| 959 | + | } | |||
| 960 | + | ||||
| 961 | + | func actionBindingFromMap(m map[string]any) (entity.ActionBinding, bool) { | |||
| 962 | + | var binding entity.ActionBinding | |||
| 963 | + | if keysValue, exists := m["keys"]; exists { | |||
| 964 | + | keys, ok := stringSliceFromAny(keysValue) | |||
| 965 | + | if !ok { | |||
| 966 | + | return entity.ActionBinding{}, false | |||
| 967 | + | } | |||
| 968 | + | binding.Keys = keys | |||
| 969 | + | } | |||
| 970 | + | if descValue, exists := m["desc"]; exists { | |||
| 971 | + | desc, ok := descValue.(string) | |||
| 972 | + | if !ok { | |||
| 973 | + | return entity.ActionBinding{}, false | |||
| 974 | + | } | |||
| 975 | + | binding.Desc = desc | |||
| 976 | + | } | |||
| 977 | + | return binding, true | |||
| 978 | + | } | |||
| 979 | + | ||||
| 980 | + | func stringSliceFromAny(value any) ([]string, bool) { | |||
| 981 | + | switch v := value.(type) { | |||
| 982 | + | case []string: | |||
| 983 | + | return append([]string(nil), v...), true | |||
| 984 | + | case []any: | |||
| 985 | + | out := make([]string, 0, len(v)) | |||
| 986 | + | for _, item := range v { | |||
| 987 | + | s, ok := item.(string) | |||
| 988 | + | if !ok { | |||
| 989 | + | return nil, false | |||
| 990 | + | } | |||
| 991 | + | out = append(out, s) | |||
| 992 | + | } | |||
| 993 | + | return out, true | |||
| 994 | + | default: | |||
| 995 | + | rv := reflect.ValueOf(value) | |||
| 996 | + | if rv.Kind() != reflect.Slice { | |||
| 997 | + | return nil, false | |||
| 998 | + | } | |||
| 999 | + | out := make([]string, 0, rv.Len()) | |||
| 1000 | + | for i := 0; i < rv.Len(); i++ { | |||
| 1001 | + | item := rv.Index(i).Interface() | |||
| 1002 | + | s, ok := item.(string) | |||
| 1003 | + | if !ok { | |||
| 1004 | + | return nil, false | |||
| 1005 | + | } | |||
| 1006 | + | out = append(out, s) | |||
| 1007 | + | } | |||
| 1008 | + | return out, true | |||
| 1009 | + | } | |||
| 1010 | + | } | |||
| 1011 | + | ||||
| 898 | func appendUniqueKeys(base, extra []string) []string { | 1012 | func appendUniqueKeys(base, extra []string) []string { | ||
| 899 | if len(extra) == 0 { | 1013 | if len(extra) == 0 { | ||
| 900 | return base | 1014 | return base | ||
M internal/infrastructure/config/migrate_test.go +111 -0
| @@ -1282,3 +1282,114 @@ section: | |||
| 1282 | 1282 | assert.InDelta(t, 42.0, section["number"].(float64), 0.001) | |
| 1283 | 1283 | }) | |
| 1284 | 1284 | } | |
| 1285 | + | ||
| 1286 | + | func TestMigrator_Migrate_RenamesCustomFavoritesSidebarShortcut(t *testing.T) { | |
| 1287 | + | home := t.TempDir() | |
| 1288 | + | t.Setenv("HOME", home) | |
| 1289 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |
| 1290 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |
| 1291 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |
| 1292 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |
| 1293 | + | ||
| 1294 | + | configFile, err := GetConfigFile() | |
| 1295 | + | require.NoError(t, err) | |
| 1296 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |
| 1297 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |
| 1298 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |
| 1299 | + | keys = [] | |
| 1300 | + | desc = "Custom favorites shortcut" | |
| 1301 | + | `), 0o644)) | |
| 1302 | + | ||
| 1303 | + | migrator := NewMigrator() | |
| 1304 | + | result, err := migrator.CheckMigration() | |
| 1305 | + | require.NoError(t, err) | |
| 1306 | + | require.NotNil(t, result) | |
| 1307 | + | assert.Contains(t, result.MissingKeys, "workspace.shortcuts.actions.toggle-favorites-sidebar") | |
| 1308 | + | ||
| 1309 | + | changes, err := migrator.DetectChanges() | |
| 1310 | + | require.NoError(t, err) | |
| 1311 | + | assertContainsChange(t, changes, port.KeyChangeRenamed, | |
| 1312 | + | "workspace.shortcuts.actions.toggle-favorites-systemview", | |
| 1313 | + | "workspace.shortcuts.actions.toggle-favorites-sidebar") | |
| 1314 | + | ||
| 1315 | + | applied, err := migrator.Migrate() | |
| 1316 | + | require.NoError(t, err) | |
| 1317 | + | assert.Contains(t, applied, "workspace.shortcuts.actions.toggle-favorites-systemview -> workspace.shortcuts.actions.toggle-favorites-sidebar") | |
| 1318 | + | ||
| 1319 | + | mgr, err := NewManager() | |
| 1320 | + | require.NoError(t, err) | |
| 1321 | + | require.NoError(t, mgr.Load()) | |
| 1322 | + | _, ok := mgr.Get().Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |
| 1323 | + | assert.False(t, ok) | |
| 1324 | + | favorites := mgr.Get().Workspace.Shortcuts.Actions["toggle-favorites-sidebar"] | |
| 1325 | + | assert.Empty(t, favorites.Keys) | |
| 1326 | + | assert.Equal(t, "Custom favorites shortcut", favorites.Desc) | |
| 1327 | + | } | |
| 1328 | + | ||
| 1329 | + | func TestMigrator_Migrate_UpgradesLegacyFavoritesSidebarDefault(t *testing.T) { | |
| 1330 | + | home := t.TempDir() | |
| 1331 | + | t.Setenv("HOME", home) | |
| 1332 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |
| 1333 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |
| 1334 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |
| 1335 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |
| 1336 | + | ||
| 1337 | + | configFile, err := GetConfigFile() | |
| 1338 | + | require.NoError(t, err) | |
| 1339 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |
| 1340 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |
| 1341 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |
| 1342 | + | keys = [] | |
| 1343 | + | desc = "Toggle Favorites in right split" | |
| 1344 | + | `), 0o644)) | |
| 1345 | + | ||
| 1346 | + | migrator := NewMigrator() | |
| 1347 | + | result, err := migrator.CheckMigration() | |
| 1348 | + | require.NoError(t, err) | |
| 1349 | + | require.NotNil(t, result) | |
| 1350 | + | assert.Contains(t, result.MissingKeys, "workspace.shortcuts.actions.toggle-favorites-sidebar") | |
| 1351 | + | assert.Contains(t, result.MissingKeys, "workspace.shortcuts.actions.toggle-current-page-favorite") | |
| 1352 | + | ||
| 1353 | + | changes, err := migrator.DetectChanges() | |
| 1354 | + | require.NoError(t, err) | |
| 1355 | + | assertContainsChange(t, changes, port.KeyChangeRenamed, | |
| 1356 | + | "workspace.shortcuts.actions.toggle-favorites-systemview", | |
| 1357 | + | "workspace.shortcuts.actions.toggle-favorites-sidebar") | |
| 1358 | + | assertContainsChange(t, changes, port.KeyChangeAdded, "", "workspace.shortcuts.actions.toggle-current-page-favorite") | |
| 1359 | + | ||
| 1360 | + | applied, err := migrator.Migrate() | |
| 1361 | + | require.NoError(t, err) | |
| 1362 | + | assert.Contains(t, applied, "workspace.shortcuts.actions.toggle-favorites-systemview -> workspace.shortcuts.actions.toggle-favorites-sidebar") | |
| 1363 | + | assert.Contains(t, applied, "workspace.shortcuts.actions.toggle-current-page-favorite") | |
| 1364 | + | ||
| 1365 | + | raw, err := migrator.readRawConfig(configFile) | |
| 1366 | + | require.NoError(t, err) | |
| 1367 | + | workspace, ok := raw["workspace"].(map[string]any) | |
| 1368 | + | require.True(t, ok) | |
| 1369 | + | shortcuts, ok := workspace["shortcuts"].(map[string]any) | |
| 1370 | + | require.True(t, ok) | |
| 1371 | + | actions, ok := shortcuts["actions"].(map[string]any) | |
| 1372 | + | require.True(t, ok) | |
| 1373 | + | ||
| 1374 | + | expectedActions := DefaultConfig().Workspace.Shortcuts.Actions | |
| 1375 | + | _, ok = actions["toggle-favorites-systemview"] | |
| 1376 | + | assert.False(t, ok) | |
| 1377 | + | favorites, ok := actions["toggle-favorites-sidebar"].(map[string]any) | |
| 1378 | + | require.True(t, ok) | |
| 1379 | + | assert.Equal(t, []any{"ctrl+b"}, favorites["keys"]) | |
| 1380 | + | assert.Equal(t, expectedActions["toggle-favorites-sidebar"].Desc, favorites["desc"]) | |
| 1381 | + | currentPage, ok := actions["toggle-current-page-favorite"].(map[string]any) | |
| 1382 | + | require.True(t, ok) | |
| 1383 | + | assert.Equal(t, []any{"ctrl+d"}, currentPage["keys"]) | |
| 1384 | + | assert.Equal(t, expectedActions["toggle-current-page-favorite"].Desc, currentPage["desc"]) | |
| 1385 | + | ||
| 1386 | + | mgr, err := NewManager() | |
| 1387 | + | require.NoError(t, err) | |
| 1388 | + | require.NoError(t, mgr.Load()) | |
| 1389 | + | cfg := mgr.Get() | |
| 1390 | + | require.NotNil(t, cfg) | |
| 1391 | + | _, ok = cfg.Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |
| 1392 | + | assert.False(t, ok) | |
| 1393 | + | assert.Equal(t, []string{"ctrl+b"}, cfg.Workspace.Shortcuts.Actions["toggle-favorites-sidebar"].Keys) | |
| 1394 | + | assert.Equal(t, []string{"ctrl+d"}, cfg.Workspace.Shortcuts.Actions["toggle-current-page-favorite"].Keys) | |
| 1395 | + | } | |
| @@ -1282,3 +1282,114 @@ section: | |||||
| 1282 | assert.InDelta(t, 42.0, section["number"].(float64), 0.001) | 1282 | assert.InDelta(t, 42.0, section["number"].(float64), 0.001) | ||
| 1283 | }) | 1283 | }) | ||
| 1284 | } | 1284 | } | ||
| 1285 | + | ||||
| 1286 | + | func TestMigrator_Migrate_RenamesCustomFavoritesSidebarShortcut(t *testing.T) { | |||
| 1287 | + | home := t.TempDir() | |||
| 1288 | + | t.Setenv("HOME", home) | |||
| 1289 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |||
| 1290 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |||
| 1291 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |||
| 1292 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |||
| 1293 | + | ||||
| 1294 | + | configFile, err := GetConfigFile() | |||
| 1295 | + | require.NoError(t, err) | |||
| 1296 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |||
| 1297 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |||
| 1298 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |||
| 1299 | + | keys = [] | |||
| 1300 | + | desc = "Custom favorites shortcut" | |||
| 1301 | + | `), 0o644)) | |||
| 1302 | + | ||||
| 1303 | + | migrator := NewMigrator() | |||
| 1304 | + | result, err := migrator.CheckMigration() | |||
| 1305 | + | require.NoError(t, err) | |||
| 1306 | + | require.NotNil(t, result) | |||
| 1307 | + | assert.Contains(t, result.MissingKeys, "workspace.shortcuts.actions.toggle-favorites-sidebar") | |||
| 1308 | + | ||||
| 1309 | + | changes, err := migrator.DetectChanges() | |||
| 1310 | + | require.NoError(t, err) | |||
| 1311 | + | assertContainsChange(t, changes, port.KeyChangeRenamed, | |||
| 1312 | + | "workspace.shortcuts.actions.toggle-favorites-systemview", | |||
| 1313 | + | "workspace.shortcuts.actions.toggle-favorites-sidebar") | |||
| 1314 | + | ||||
| 1315 | + | applied, err := migrator.Migrate() | |||
| 1316 | + | require.NoError(t, err) | |||
| 1317 | + | assert.Contains(t, applied, "workspace.shortcuts.actions.toggle-favorites-systemview -> workspace.shortcuts.actions.toggle-favorites-sidebar") | |||
| 1318 | + | ||||
| 1319 | + | mgr, err := NewManager() | |||
| 1320 | + | require.NoError(t, err) | |||
| 1321 | + | require.NoError(t, mgr.Load()) | |||
| 1322 | + | _, ok := mgr.Get().Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |||
| 1323 | + | assert.False(t, ok) | |||
| 1324 | + | favorites := mgr.Get().Workspace.Shortcuts.Actions["toggle-favorites-sidebar"] | |||
| 1325 | + | assert.Empty(t, favorites.Keys) | |||
| 1326 | + | assert.Equal(t, "Custom favorites shortcut", favorites.Desc) | |||
| 1327 | + | } | |||
| 1328 | + | ||||
| 1329 | + | func TestMigrator_Migrate_UpgradesLegacyFavoritesSidebarDefault(t *testing.T) { | |||
| 1330 | + | home := t.TempDir() | |||
| 1331 | + | t.Setenv("HOME", home) | |||
| 1332 | + | t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config")) | |||
| 1333 | + | t.Setenv("XDG_DATA_HOME", filepath.Join(home, ".local", "share")) | |||
| 1334 | + | t.Setenv("XDG_STATE_HOME", filepath.Join(home, ".local", "state")) | |||
| 1335 | + | t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache")) | |||
| 1336 | + | ||||
| 1337 | + | configFile, err := GetConfigFile() | |||
| 1338 | + | require.NoError(t, err) | |||
| 1339 | + | require.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755)) | |||
| 1340 | + | require.NoError(t, os.WriteFile(configFile, []byte(` | |||
| 1341 | + | [workspace.shortcuts.actions.toggle-favorites-systemview] | |||
| 1342 | + | keys = [] | |||
| 1343 | + | desc = "Toggle Favorites in right split" | |||
| 1344 | + | `), 0o644)) | |||
| 1345 | + | ||||
| 1346 | + | migrator := NewMigrator() | |||
| 1347 | + | result, err := migrator.CheckMigration() | |||
| 1348 | + | require.NoError(t, err) | |||
| 1349 | + | require.NotNil(t, result) | |||
| 1350 | + | assert.Contains(t, result.MissingKeys, "workspace.shortcuts.actions.toggle-favorites-sidebar") | |||
| 1351 | + | assert.Contains(t, result.MissingKeys, "workspace.shortcuts.actions.toggle-current-page-favorite") | |||
| 1352 | + | ||||
| 1353 | + | changes, err := migrator.DetectChanges() | |||
| 1354 | + | require.NoError(t, err) | |||
| 1355 | + | assertContainsChange(t, changes, port.KeyChangeRenamed, | |||
| 1356 | + | "workspace.shortcuts.actions.toggle-favorites-systemview", | |||
| 1357 | + | "workspace.shortcuts.actions.toggle-favorites-sidebar") | |||
| 1358 | + | assertContainsChange(t, changes, port.KeyChangeAdded, "", "workspace.shortcuts.actions.toggle-current-page-favorite") | |||
| 1359 | + | ||||
| 1360 | + | applied, err := migrator.Migrate() | |||
| 1361 | + | require.NoError(t, err) | |||
| 1362 | + | assert.Contains(t, applied, "workspace.shortcuts.actions.toggle-favorites-systemview -> workspace.shortcuts.actions.toggle-favorites-sidebar") | |||
| 1363 | + | assert.Contains(t, applied, "workspace.shortcuts.actions.toggle-current-page-favorite") | |||
| 1364 | + | ||||
| 1365 | + | raw, err := migrator.readRawConfig(configFile) | |||
| 1366 | + | require.NoError(t, err) | |||
| 1367 | + | workspace, ok := raw["workspace"].(map[string]any) | |||
| 1368 | + | require.True(t, ok) | |||
| 1369 | + | shortcuts, ok := workspace["shortcuts"].(map[string]any) | |||
| 1370 | + | require.True(t, ok) | |||
| 1371 | + | actions, ok := shortcuts["actions"].(map[string]any) | |||
| 1372 | + | require.True(t, ok) | |||
| 1373 | + | ||||
| 1374 | + | expectedActions := DefaultConfig().Workspace.Shortcuts.Actions | |||
| 1375 | + | _, ok = actions["toggle-favorites-systemview"] | |||
| 1376 | + | assert.False(t, ok) | |||
| 1377 | + | favorites, ok := actions["toggle-favorites-sidebar"].(map[string]any) | |||
| 1378 | + | require.True(t, ok) | |||
| 1379 | + | assert.Equal(t, []any{"ctrl+b"}, favorites["keys"]) | |||
| 1380 | + | assert.Equal(t, expectedActions["toggle-favorites-sidebar"].Desc, favorites["desc"]) | |||
| 1381 | + | currentPage, ok := actions["toggle-current-page-favorite"].(map[string]any) | |||
| 1382 | + | require.True(t, ok) | |||
| 1383 | + | assert.Equal(t, []any{"ctrl+d"}, currentPage["keys"]) | |||
| 1384 | + | assert.Equal(t, expectedActions["toggle-current-page-favorite"].Desc, currentPage["desc"]) | |||
| 1385 | + | ||||
| 1386 | + | mgr, err := NewManager() | |||
| 1387 | + | require.NoError(t, err) | |||
| 1388 | + | require.NoError(t, mgr.Load()) | |||
| 1389 | + | cfg := mgr.Get() | |||
| 1390 | + | require.NotNil(t, cfg) | |||
| 1391 | + | _, ok = cfg.Workspace.Shortcuts.Actions["toggle-favorites-systemview"] | |||
| 1392 | + | assert.False(t, ok) | |||
| 1393 | + | assert.Equal(t, []string{"ctrl+b"}, cfg.Workspace.Shortcuts.Actions["toggle-favorites-sidebar"].Keys) | |||
| 1394 | + | assert.Equal(t, []string{"ctrl+d"}, cfg.Workspace.Shortcuts.Actions["toggle-current-page-favorite"].Keys) | |||
| 1395 | + | } | |||
M internal/ui/browser_window_favorites_sidebar.go +9 -2
| @@ -119,7 +119,8 @@ func (a *App) toggleCurrentPageFavoriteAction(ctx context.Context) error { | |||
| 119 | 119 | if a == nil || a.deps == nil || a.deps.FavoritesUC == nil { | |
| 120 | 120 | return fmt.Errorf("favorites unavailable: usecase not configured") | |
| 121 | 121 | } | |
| 122 | - | _, wv := a.activeWebViewForBrowserWindow(a.lastFocusedBrowserWindow()) | |
| 122 | + | bw := a.lastFocusedBrowserWindow() | |
| 123 | + | _, wv := a.activeWebViewForBrowserWindow(bw) | |
| 123 | 124 | if wv == nil { | |
| 124 | 125 | return fmt.Errorf("favorites unavailable: no active webview") | |
| 125 | 126 | } | |
| @@ -127,10 +128,16 @@ func (a *App) toggleCurrentPageFavoriteAction(ctx context.Context) error { | |||
| 127 | 128 | if uri == "" { | |
| 128 | 129 | return fmt.Errorf("favorites unavailable: active page has no URI") | |
| 129 | 130 | } | |
| 130 | - | _, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title()) | |
| 131 | + | result, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title()) | |
| 131 | 132 | if err != nil { | |
| 132 | 133 | return err | |
| 133 | 134 | } | |
| 135 | + | if result != nil && strings.TrimSpace(result.Message) != "" { | |
| 136 | + | a.showToastOnBrowserWindow(ctx, bw, result.Message, component.ToastSuccess, | |
| 137 | + | component.WithDuration(component.ToastBriefDurationMs), | |
| 138 | + | component.WithPosition(component.ToastPositionBottomRight), | |
| 139 | + | ) | |
| 140 | + | } | |
| 134 | 141 | a.reloadVisibleFavoritesSidebars("current-page-favorite-toggle") | |
| 135 | 142 | return nil | |
| 136 | 143 | } | |
| @@ -119,7 +119,8 @@ func (a *App) toggleCurrentPageFavoriteAction(ctx context.Context) error { | |||||
| 119 | if a == nil || a.deps == nil || a.deps.FavoritesUC == nil { | 119 | if a == nil || a.deps == nil || a.deps.FavoritesUC == nil { | ||
| 120 | return fmt.Errorf("favorites unavailable: usecase not configured") | 120 | return fmt.Errorf("favorites unavailable: usecase not configured") | ||
| 121 | } | 121 | } | ||
| 122 | - | _, wv := a.activeWebViewForBrowserWindow(a.lastFocusedBrowserWindow()) | 122 | + | bw := a.lastFocusedBrowserWindow() |
| 123 | + | _, wv := a.activeWebViewForBrowserWindow(bw) | |||
| 123 | if wv == nil { | 124 | if wv == nil { | ||
| 124 | return fmt.Errorf("favorites unavailable: no active webview") | 125 | return fmt.Errorf("favorites unavailable: no active webview") | ||
| 125 | } | 126 | } | ||
| @@ -127,10 +128,16 @@ func (a *App) toggleCurrentPageFavoriteAction(ctx context.Context) error { | |||||
| 127 | if uri == "" { | 128 | if uri == "" { | ||
| 128 | return fmt.Errorf("favorites unavailable: active page has no URI") | 129 | return fmt.Errorf("favorites unavailable: active page has no URI") | ||
| 129 | } | 130 | } | ||
| 130 | - | _, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title()) | 131 | + | result, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title()) |
| 131 | if err != nil { | 132 | if err != nil { | ||
| 132 | return err | 133 | return err | ||
| 133 | } | 134 | } | ||
| 135 | + | if result != nil && strings.TrimSpace(result.Message) != "" { | |||
| 136 | + | a.showToastOnBrowserWindow(ctx, bw, result.Message, component.ToastSuccess, | |||
| 137 | + | component.WithDuration(component.ToastBriefDurationMs), | |||
| 138 | + | component.WithPosition(component.ToastPositionBottomRight), | |||
| 139 | + | ) | |||
| 140 | + | } | |||
| 134 | a.reloadVisibleFavoritesSidebars("current-page-favorite-toggle") | 141 | a.reloadVisibleFavoritesSidebars("current-page-favorite-toggle") | ||
| 135 | return nil | 142 | return nil | ||
| 136 | } | 143 | } | ||
M internal/ui/dispatcher/keyboard.go +1 -1
| @@ -295,7 +295,7 @@ func (d *KeyboardDispatcher) initActionHandlers() { | |||
| 295 | 295 | } | |
| 296 | 296 | return d.onToggleHistorySidebar(ctx) | |
| 297 | 297 | }, | |
| 298 | - | input.ActionToggleFavoritesSystemView: func(ctx context.Context) error { | |
| 298 | + | input.ActionToggleFavoritesSidebar: func(ctx context.Context) error { | |
| 299 | 299 | if d.onToggleFavoritesSidebar == nil { | |
| 300 | 300 | return fmt.Errorf("favorites sidebar unavailable: toggle handler not wired") | |
| 301 | 301 | } | |
| @@ -295,7 +295,7 @@ func (d *KeyboardDispatcher) initActionHandlers() { | |||||
| 295 | } | 295 | } | ||
| 296 | return d.onToggleHistorySidebar(ctx) | 296 | return d.onToggleHistorySidebar(ctx) | ||
| 297 | }, | 297 | }, | ||
| 298 | - | input.ActionToggleFavoritesSystemView: func(ctx context.Context) error { | 298 | + | input.ActionToggleFavoritesSidebar: func(ctx context.Context) error { |
| 299 | if d.onToggleFavoritesSidebar == nil { | 299 | if d.onToggleFavoritesSidebar == nil { | ||
| 300 | return fmt.Errorf("favorites sidebar unavailable: toggle handler not wired") | 300 | return fmt.Errorf("favorites sidebar unavailable: toggle handler not wired") | ||
| 301 | } | 301 | } | ||
M internal/ui/dispatcher/keyboard_test.go +3 -3
| @@ -122,19 +122,19 @@ func TestKeyboardDispatcher_ToggleFavoritesSidebarCallsCallbackAndPropagatesErro | |||
| 122 | 122 | ctx := context.Background() | |
| 123 | 123 | d := NewKeyboardDispatcher(ctx, &coordinator.WorkspaceCoordinator{}, &coordinator.NavigationCoordinator{}, nil, nil, KeyboardActions{}, func(context.Context) entity.PaneID { return "" }) | |
| 124 | 124 | ||
| 125 | - | missingErr := d.Dispatch(ctx, input.ActionToggleFavoritesSystemView) | |
| 125 | + | missingErr := d.Dispatch(ctx, input.ActionToggleFavoritesSidebar) | |
| 126 | 126 | require.Error(t, missingErr) | |
| 127 | 127 | require.ErrorContains(t, missingErr, "favorites sidebar unavailable") | |
| 128 | 128 | ||
| 129 | 129 | wantErr := fmt.Errorf("favorites failed") | |
| 130 | 130 | d.SetOnToggleFavoritesSidebar(func(context.Context) error { return wantErr }) | |
| 131 | - | err := d.Dispatch(ctx, input.ActionToggleFavoritesSystemView) | |
| 131 | + | err := d.Dispatch(ctx, input.ActionToggleFavoritesSidebar) | |
| 132 | 132 | require.Error(t, err) | |
| 133 | 133 | require.ErrorIs(t, err, wantErr) | |
| 134 | 134 | ||
| 135 | 135 | var called bool | |
| 136 | 136 | d.SetOnToggleFavoritesSidebar(func(context.Context) error { called = true; return nil }) | |
| 137 | - | require.NoError(t, d.Dispatch(ctx, input.ActionToggleFavoritesSystemView)) | |
| 137 | + | require.NoError(t, d.Dispatch(ctx, input.ActionToggleFavoritesSidebar)) | |
| 138 | 138 | assert.True(t, called) | |
| 139 | 139 | } | |
| 140 | 140 | ||
| @@ -122,19 +122,19 @@ func TestKeyboardDispatcher_ToggleFavoritesSidebarCallsCallbackAndPropagatesErro | |||||
| 122 | ctx := context.Background() | 122 | ctx := context.Background() | ||
| 123 | d := NewKeyboardDispatcher(ctx, &coordinator.WorkspaceCoordinator{}, &coordinator.NavigationCoordinator{}, nil, nil, KeyboardActions{}, func(context.Context) entity.PaneID { return "" }) | 123 | d := NewKeyboardDispatcher(ctx, &coordinator.WorkspaceCoordinator{}, &coordinator.NavigationCoordinator{}, nil, nil, KeyboardActions{}, func(context.Context) entity.PaneID { return "" }) | ||
| 124 | 124 | ||||
| 125 | - | missingErr := d.Dispatch(ctx, input.ActionToggleFavoritesSystemView) | 125 | + | missingErr := d.Dispatch(ctx, input.ActionToggleFavoritesSidebar) |
| 126 | require.Error(t, missingErr) | 126 | require.Error(t, missingErr) | ||
| 127 | require.ErrorContains(t, missingErr, "favorites sidebar unavailable") | 127 | require.ErrorContains(t, missingErr, "favorites sidebar unavailable") | ||
| 128 | 128 | ||||
| 129 | wantErr := fmt.Errorf("favorites failed") | 129 | wantErr := fmt.Errorf("favorites failed") | ||
| 130 | d.SetOnToggleFavoritesSidebar(func(context.Context) error { return wantErr }) | 130 | d.SetOnToggleFavoritesSidebar(func(context.Context) error { return wantErr }) | ||
| 131 | - | err := d.Dispatch(ctx, input.ActionToggleFavoritesSystemView) | 131 | + | err := d.Dispatch(ctx, input.ActionToggleFavoritesSidebar) |
| 132 | require.Error(t, err) | 132 | require.Error(t, err) | ||
| 133 | require.ErrorIs(t, err, wantErr) | 133 | require.ErrorIs(t, err, wantErr) | ||
| 134 | 134 | ||||
| 135 | var called bool | 135 | var called bool | ||
| 136 | d.SetOnToggleFavoritesSidebar(func(context.Context) error { called = true; return nil }) | 136 | d.SetOnToggleFavoritesSidebar(func(context.Context) error { called = true; return nil }) | ||
| 137 | - | require.NoError(t, d.Dispatch(ctx, input.ActionToggleFavoritesSystemView)) | 137 | + | require.NoError(t, d.Dispatch(ctx, input.ActionToggleFavoritesSidebar)) |
| 138 | assert.True(t, called) | 138 | assert.True(t, called) | ||
| 139 | } | 139 | } | ||
| 140 | 140 | ||||
M internal/ui/input/global_shortcuts.go +3 -3
| @@ -516,8 +516,8 @@ func globalShortcutActionMap() map[string]Action { | |||
| 516 | 516 | "consume-or-expel-down": ActionConsumeOrExpelDown, | |
| 517 | 517 | "toggle_history_systemview": ActionToggleHistorySystemView, | |
| 518 | 518 | "toggle-history-systemview": ActionToggleHistorySystemView, | |
| 519 | - | "toggle_favorites_systemview": ActionToggleFavoritesSystemView, | |
| 520 | - | "toggle-favorites-systemview": ActionToggleFavoritesSystemView, | |
| 519 | + | "toggle_favorites_sidebar": ActionToggleFavoritesSidebar, | |
| 520 | + | "toggle-favorites-sidebar": ActionToggleFavoritesSidebar, | |
| 521 | 521 | "toggle_current_page_favorite": ActionToggleCurrentPageFavorite, | |
| 522 | 522 | "toggle-current-page-favorite": ActionToggleCurrentPageFavorite, | |
| 523 | 523 | "toggle_config_systemview": ActionToggleConfigSystemView, | |
| @@ -733,7 +733,7 @@ func isRepeatedGlobalShortcutSuppressed(action Action) bool { | |||
| 733 | 733 | ActionToggleFullscreen, | |
| 734 | 734 | ActionToggleFloatingPane, | |
| 735 | 735 | ActionToggleHistorySystemView, | |
| 736 | - | ActionToggleFavoritesSystemView, | |
| 736 | + | ActionToggleFavoritesSidebar, | |
| 737 | 737 | ActionToggleCurrentPageFavorite, | |
| 738 | 738 | ActionToggleConfigSystemView, | |
| 739 | 739 | ActionCopyURL, | |
| @@ -516,8 +516,8 @@ func globalShortcutActionMap() map[string]Action { | |||||
| 516 | "consume-or-expel-down": ActionConsumeOrExpelDown, | 516 | "consume-or-expel-down": ActionConsumeOrExpelDown, | ||
| 517 | "toggle_history_systemview": ActionToggleHistorySystemView, | 517 | "toggle_history_systemview": ActionToggleHistorySystemView, | ||
| 518 | "toggle-history-systemview": ActionToggleHistorySystemView, | 518 | "toggle-history-systemview": ActionToggleHistorySystemView, | ||
| 519 | - | "toggle_favorites_systemview": ActionToggleFavoritesSystemView, | 519 | + | "toggle_favorites_sidebar": ActionToggleFavoritesSidebar, |
| 520 | - | "toggle-favorites-systemview": ActionToggleFavoritesSystemView, | 520 | + | "toggle-favorites-sidebar": ActionToggleFavoritesSidebar, |
| 521 | "toggle_current_page_favorite": ActionToggleCurrentPageFavorite, | 521 | "toggle_current_page_favorite": ActionToggleCurrentPageFavorite, | ||
| 522 | "toggle-current-page-favorite": ActionToggleCurrentPageFavorite, | 522 | "toggle-current-page-favorite": ActionToggleCurrentPageFavorite, | ||
| 523 | "toggle_config_systemview": ActionToggleConfigSystemView, | 523 | "toggle_config_systemview": ActionToggleConfigSystemView, | ||
| @@ -733,7 +733,7 @@ func isRepeatedGlobalShortcutSuppressed(action Action) bool { | |||||
| 733 | ActionToggleFullscreen, | 733 | ActionToggleFullscreen, | ||
| 734 | ActionToggleFloatingPane, | 734 | ActionToggleFloatingPane, | ||
| 735 | ActionToggleHistorySystemView, | 735 | ActionToggleHistorySystemView, | ||
| 736 | - | ActionToggleFavoritesSystemView, | 736 | + | ActionToggleFavoritesSidebar, |
| 737 | ActionToggleCurrentPageFavorite, | 737 | ActionToggleCurrentPageFavorite, | ||
| 738 | ActionToggleConfigSystemView, | 738 | ActionToggleConfigSystemView, | ||
| 739 | ActionCopyURL, | 739 | ActionCopyURL, | ||
M internal/ui/input/global_shortcuts_test.go +1 -1
| @@ -251,7 +251,7 @@ func TestGlobalShortcutHandlerSuppressesRepeatedAdditionalOneShotUIActions(t *te | |||
| 251 | 251 | ActionFindPrev, | |
| 252 | 252 | ActionOpenDevTools, | |
| 253 | 253 | ActionToggleFloatingPane, | |
| 254 | - | ActionToggleFavoritesSystemView, | |
| 254 | + | ActionToggleFavoritesSidebar, | |
| 255 | 255 | ActionToggleCurrentPageFavorite, | |
| 256 | 256 | ActionToggleConfigSystemView, | |
| 257 | 257 | ActionCopyURL, | |
| @@ -251,7 +251,7 @@ func TestGlobalShortcutHandlerSuppressesRepeatedAdditionalOneShotUIActions(t *te | |||||
| 251 | ActionFindPrev, | 251 | ActionFindPrev, | ||
| 252 | ActionOpenDevTools, | 252 | ActionOpenDevTools, | ||
| 253 | ActionToggleFloatingPane, | 253 | ActionToggleFloatingPane, | ||
| 254 | - | ActionToggleFavoritesSystemView, | 254 | + | ActionToggleFavoritesSidebar, |
| 255 | ActionToggleCurrentPageFavorite, | 255 | ActionToggleCurrentPageFavorite, | ||
| 256 | ActionToggleConfigSystemView, | 256 | ActionToggleConfigSystemView, | ||
| 257 | ActionCopyURL, | 257 | ActionCopyURL, | ||
M internal/ui/input/shortcuts.go +3 -3
| @@ -190,7 +190,7 @@ const ( | |||
| 190 | 190 | ActionToggleFullscreen Action = "toggle_fullscreen" | |
| 191 | 191 | ActionToggleFloatingPane Action = "toggle_floating_pane" | |
| 192 | 192 | ActionToggleHistorySystemView Action = "toggle_history_systemview" | |
| 193 | - | ActionToggleFavoritesSystemView Action = "toggle_favorites_systemview" | |
| 193 | + | ActionToggleFavoritesSidebar Action = "toggle_favorites_sidebar" | |
| 194 | 194 | ActionToggleCurrentPageFavorite Action = "toggle_current_page_favorite" | |
| 195 | 195 | ActionToggleConfigSystemView Action = "toggle_config_systemview" | |
| 196 | 196 | ||
| @@ -608,8 +608,8 @@ var configActionToAction = map[string]Action{ | |||
| 608 | 608 | "toggle-floating-pane": ActionToggleFloatingPane, | |
| 609 | 609 | "toggle_history_systemview": ActionToggleHistorySystemView, | |
| 610 | 610 | "toggle-history-systemview": ActionToggleHistorySystemView, | |
| 611 | - | "toggle_favorites_systemview": ActionToggleFavoritesSystemView, | |
| 612 | - | "toggle-favorites-systemview": ActionToggleFavoritesSystemView, | |
| 611 | + | "toggle_favorites_sidebar": ActionToggleFavoritesSidebar, | |
| 612 | + | "toggle-favorites-sidebar": ActionToggleFavoritesSidebar, | |
| 613 | 613 | "toggle_current_page_favorite": ActionToggleCurrentPageFavorite, | |
| 614 | 614 | "toggle-current-page-favorite": ActionToggleCurrentPageFavorite, | |
| 615 | 615 | "toggle_config_systemview": ActionToggleConfigSystemView, | |
| @@ -190,7 +190,7 @@ const ( | |||||
| 190 | ActionToggleFullscreen Action = "toggle_fullscreen" | 190 | ActionToggleFullscreen Action = "toggle_fullscreen" | ||
| 191 | ActionToggleFloatingPane Action = "toggle_floating_pane" | 191 | ActionToggleFloatingPane Action = "toggle_floating_pane" | ||
| 192 | ActionToggleHistorySystemView Action = "toggle_history_systemview" | 192 | ActionToggleHistorySystemView Action = "toggle_history_systemview" | ||
| 193 | - | ActionToggleFavoritesSystemView Action = "toggle_favorites_systemview" | 193 | + | ActionToggleFavoritesSidebar Action = "toggle_favorites_sidebar" |
| 194 | ActionToggleCurrentPageFavorite Action = "toggle_current_page_favorite" | 194 | ActionToggleCurrentPageFavorite Action = "toggle_current_page_favorite" | ||
| 195 | ActionToggleConfigSystemView Action = "toggle_config_systemview" | 195 | ActionToggleConfigSystemView Action = "toggle_config_systemview" | ||
| 196 | 196 | ||||
| @@ -608,8 +608,8 @@ var configActionToAction = map[string]Action{ | |||||
| 608 | "toggle-floating-pane": ActionToggleFloatingPane, | 608 | "toggle-floating-pane": ActionToggleFloatingPane, | ||
| 609 | "toggle_history_systemview": ActionToggleHistorySystemView, | 609 | "toggle_history_systemview": ActionToggleHistorySystemView, | ||
| 610 | "toggle-history-systemview": ActionToggleHistorySystemView, | 610 | "toggle-history-systemview": ActionToggleHistorySystemView, | ||
| 611 | - | "toggle_favorites_systemview": ActionToggleFavoritesSystemView, | 611 | + | "toggle_favorites_sidebar": ActionToggleFavoritesSidebar, |
| 612 | - | "toggle-favorites-systemview": ActionToggleFavoritesSystemView, | 612 | + | "toggle-favorites-sidebar": ActionToggleFavoritesSidebar, |
| 613 | "toggle_current_page_favorite": ActionToggleCurrentPageFavorite, | 613 | "toggle_current_page_favorite": ActionToggleCurrentPageFavorite, | ||
| 614 | "toggle-current-page-favorite": ActionToggleCurrentPageFavorite, | 614 | "toggle-current-page-favorite": ActionToggleCurrentPageFavorite, | ||
| 615 | "toggle_config_systemview": ActionToggleConfigSystemView, | 615 | "toggle_config_systemview": ActionToggleConfigSystemView, | ||
M internal/ui/input/shortcuts_test.go +2 -2
| @@ -403,7 +403,7 @@ func TestMapConfigAction_ToggleSystemViews(t *testing.T) { | |||
| 403 | 403 | want Action | |
| 404 | 404 | }{ | |
| 405 | 405 | {name: "toggle_history_systemview", want: ActionToggleHistorySystemView}, | |
| 406 | - | {name: "toggle_favorites_systemview", want: ActionToggleFavoritesSystemView}, | |
| 406 | + | {name: "toggle_favorites_sidebar", want: ActionToggleFavoritesSidebar}, | |
| 407 | 407 | {name: "toggle_current_page_favorite", want: ActionToggleCurrentPageFavorite}, | |
| 408 | 408 | {name: "toggle_config_systemview", want: ActionToggleConfigSystemView}, | |
| 409 | 409 | } | |
| @@ -423,7 +423,7 @@ func TestMapConfigAction_ToggleSystemViewsHyphenAlias(t *testing.T) { | |||
| 423 | 423 | want Action | |
| 424 | 424 | }{ | |
| 425 | 425 | {name: "toggle-history-systemview", want: ActionToggleHistorySystemView}, | |
| 426 | - | {name: "toggle-favorites-systemview", want: ActionToggleFavoritesSystemView}, | |
| 426 | + | {name: "toggle-favorites-sidebar", want: ActionToggleFavoritesSidebar}, | |
| 427 | 427 | {name: "toggle-current-page-favorite", want: ActionToggleCurrentPageFavorite}, | |
| 428 | 428 | {name: "toggle-config-systemview", want: ActionToggleConfigSystemView}, | |
| 429 | 429 | } | |
| @@ -403,7 +403,7 @@ func TestMapConfigAction_ToggleSystemViews(t *testing.T) { | |||||
| 403 | want Action | 403 | want Action | ||
| 404 | }{ | 404 | }{ | ||
| 405 | {name: "toggle_history_systemview", want: ActionToggleHistorySystemView}, | 405 | {name: "toggle_history_systemview", want: ActionToggleHistorySystemView}, | ||
| 406 | - | {name: "toggle_favorites_systemview", want: ActionToggleFavoritesSystemView}, | 406 | + | {name: "toggle_favorites_sidebar", want: ActionToggleFavoritesSidebar}, |
| 407 | {name: "toggle_current_page_favorite", want: ActionToggleCurrentPageFavorite}, | 407 | {name: "toggle_current_page_favorite", want: ActionToggleCurrentPageFavorite}, | ||
| 408 | {name: "toggle_config_systemview", want: ActionToggleConfigSystemView}, | 408 | {name: "toggle_config_systemview", want: ActionToggleConfigSystemView}, | ||
| 409 | } | 409 | } | ||
| @@ -423,7 +423,7 @@ func TestMapConfigAction_ToggleSystemViewsHyphenAlias(t *testing.T) { | |||||
| 423 | want Action | 423 | want Action | ||
| 424 | }{ | 424 | }{ | ||
| 425 | {name: "toggle-history-systemview", want: ActionToggleHistorySystemView}, | 425 | {name: "toggle-history-systemview", want: ActionToggleHistorySystemView}, | ||
| 426 | - | {name: "toggle-favorites-systemview", want: ActionToggleFavoritesSystemView}, | 426 | + | {name: "toggle-favorites-sidebar", want: ActionToggleFavoritesSidebar}, |
| 427 | {name: "toggle-current-page-favorite", want: ActionToggleCurrentPageFavorite}, | 427 | {name: "toggle-current-page-favorite", want: ActionToggleCurrentPageFavorite}, | ||
| 428 | {name: "toggle-config-systemview", want: ActionToggleConfigSystemView}, | 428 | {name: "toggle-config-systemview", want: ActionToggleConfigSystemView}, | ||
| 429 | } | 429 | } | ||