Fix scoped gRPC persistence and autosave behavior
This commit is contained in:
@@ -380,6 +380,7 @@ type ui struct {
|
||||
settingsHistory widget.Bool
|
||||
settingsDenseLayout widget.Bool
|
||||
settingsDebugHeaderBounds widget.Bool
|
||||
settingsAutoSaveRemote widget.Bool
|
||||
entryClicks []widget.Clickable
|
||||
apiTokenClicks []widget.Clickable
|
||||
apiPolicyEdits []widget.Clickable
|
||||
@@ -475,6 +476,7 @@ type ui struct {
|
||||
editingEntry bool
|
||||
syncDefaultSourceMode syncSourceMode
|
||||
syncDefaultDirection syncDirection
|
||||
autoSaveRemote bool
|
||||
groupControlsHidden bool
|
||||
lifecycleAdvancedHidden bool
|
||||
historyHidden bool
|
||||
@@ -665,6 +667,7 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
|
||||
syncDirection: syncDirectionPull,
|
||||
syncDefaultSourceMode: syncSourceLocal,
|
||||
syncDefaultDirection: syncDirectionPull,
|
||||
autoSaveRemote: false,
|
||||
apiPolicyGroupScope: true,
|
||||
autofillNoticePreference: autofillNoticeAll,
|
||||
vaultSharer: platform.NewVaultSharer(runtime.GOOS),
|
||||
@@ -678,6 +681,7 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
|
||||
u.apiPolicyAllow.Value = true
|
||||
u.apiPolicyGroupScopeW.Value = true
|
||||
u.state.Session = sess
|
||||
u.state.AutoSaveRemote = u.autoSaveRemote
|
||||
u.phoneSplit.Value = 0.46
|
||||
u.eyeIcon, _ = widget.NewIcon(icons.ActionVisibility)
|
||||
u.eyeOffIcon, _ = widget.NewIcon(icons.ActionVisibilityOff)
|
||||
@@ -1211,6 +1215,17 @@ func (u *ui) securityDialogContent(gtx layout.Context) layout.Dimensions {
|
||||
return syncDialogSummaryCard(gtx, u.theme, syncDialogPurposeAdvanced, u.settingsDraft.Sync.SourceDefault, u.settingsDraft.Sync.DirectionDefault)
|
||||
},
|
||||
layout.Spacer{Height: unit.Dp(8)}.Layout,
|
||||
func(gtx layout.Context) layout.Dimensions {
|
||||
check := material.CheckBox(u.theme, &u.settingsAutoSaveRemote, "Auto-save remote vault edits")
|
||||
return check.Layout(gtx)
|
||||
},
|
||||
layout.Spacer{Height: unit.Dp(4)}.Layout,
|
||||
func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "When enabled, edits to an already-open remote vault save immediately instead of waiting for an explicit remote save.")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
},
|
||||
layout.Spacer{Height: unit.Dp(8)}.Layout,
|
||||
func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "Conflict handling stays retry-safe: merged entry changes keep history, while remote save conflicts still require reopening the vault and retrying the save.")
|
||||
lbl.Color = mutedColor
|
||||
|
||||
@@ -5618,6 +5618,33 @@ func TestUISyncDefaultsPersistInSettings(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUIRemoteAutosavePersistsInSettings(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
configPath := filepath.Join(t.TempDir(), "settings.json")
|
||||
|
||||
first := newUIWithSession("desktop", &session.Manager{}, statePaths{
|
||||
SettingsPath: configPath,
|
||||
})
|
||||
first.autoSaveRemote = true
|
||||
first.state.AutoSaveRemote = true
|
||||
first.saveSettings()
|
||||
|
||||
second := newUIWithSession("desktop", &session.Manager{}, statePaths{
|
||||
SettingsPath: configPath,
|
||||
})
|
||||
second.autoSaveRemote = false
|
||||
second.state.AutoSaveRemote = false
|
||||
second.loadSettings()
|
||||
|
||||
if !second.autoSaveRemote {
|
||||
t.Fatal("autoSaveRemote = false, want true after reload")
|
||||
}
|
||||
if !second.state.AutoSaveRemote {
|
||||
t.Fatal("state.AutoSaveRemote = false, want true after reload")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUIDebugHeaderBoundsPersistInSettings(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -5714,6 +5741,7 @@ func TestUISaveSecuritySettingsPersistsSyncDefaults(t *testing.T) {
|
||||
u.loadSettingsDraft()
|
||||
u.settingsDraft.Sync.SourceDefault = syncSourceRemote
|
||||
u.settingsDraft.Sync.DirectionDefault = syncDirectionPush
|
||||
u.settingsAutoSaveRemote.Value = true
|
||||
|
||||
if err := u.saveSecuritySettingsAction(); err != nil {
|
||||
t.Fatalf("saveSecuritySettingsAction() error = %v", err)
|
||||
@@ -5730,6 +5758,12 @@ func TestUISaveSecuritySettingsPersistsSyncDefaults(t *testing.T) {
|
||||
if got := reloaded.syncDefaultDirection; got != syncDirectionPush {
|
||||
t.Fatalf("reloaded syncDefaultDirection = %q, want push", got)
|
||||
}
|
||||
if !reloaded.autoSaveRemote {
|
||||
t.Fatal("reloaded autoSaveRemote = false, want true")
|
||||
}
|
||||
if !reloaded.state.AutoSaveRemote {
|
||||
t.Fatal("reloaded state.AutoSaveRemote = false, want true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUISaveSecuritySettingsPersistsDebugHeaderBounds(t *testing.T) {
|
||||
|
||||
@@ -44,6 +44,7 @@ type settingsFile struct {
|
||||
type syncSettings struct {
|
||||
SourceDefault string `json:"sourceDefault,omitempty"`
|
||||
DirectionDefault string `json:"directionDefault,omitempty"`
|
||||
AutoSaveRemote bool `json:"autoSaveRemote,omitempty"`
|
||||
}
|
||||
|
||||
type debugSettings struct {
|
||||
@@ -53,6 +54,7 @@ type debugSettings struct {
|
||||
type syncSettingsDraft struct {
|
||||
SourceDefault syncSourceMode
|
||||
DirectionDefault syncDirection
|
||||
AutoSaveRemote bool
|
||||
}
|
||||
|
||||
type settingsDraft struct {
|
||||
@@ -198,12 +200,14 @@ func (u *ui) loadSettingsDraft() {
|
||||
Sync: syncSettingsDraft{
|
||||
SourceDefault: u.syncDefaultSourceMode,
|
||||
DirectionDefault: u.syncDefaultDirection,
|
||||
AutoSaveRemote: u.autoSaveRemote,
|
||||
},
|
||||
Debug: debugSettings{
|
||||
LogHeaderBounds: u.debugLogHeaderBounds,
|
||||
},
|
||||
}
|
||||
u.settingsDebugHeaderBounds.Value = u.settingsDraft.Debug.LogHeaderBounds
|
||||
u.settingsAutoSaveRemote.Value = u.settingsDraft.Sync.AutoSaveRemote
|
||||
}
|
||||
|
||||
func (u *ui) saveSecuritySettingsAction() error {
|
||||
@@ -226,9 +230,12 @@ func (u *ui) applySecuritySettingsLive() error {
|
||||
u.settingsDraft.Accessibility.DisplayDensity = displayDensityForDenseLayout(u.settingsDenseLayout.Value)
|
||||
}
|
||||
u.settingsDraft.Debug.LogHeaderBounds = u.settingsDebugHeaderBounds.Value
|
||||
u.settingsDraft.Sync.AutoSaveRemote = u.settingsAutoSaveRemote.Value
|
||||
u.settingsDenseLayout.Value = u.settingsDraft.Accessibility.DisplayDensity == displayDensityDense
|
||||
u.syncDefaultSourceMode = sanitizeSyncSourceMode(u.settingsDraft.Sync.SourceDefault)
|
||||
u.syncDefaultDirection = sanitizeSyncDirection(u.settingsDraft.Sync.DirectionDefault)
|
||||
u.autoSaveRemote = u.settingsDraft.Sync.AutoSaveRemote
|
||||
u.state.AutoSaveRemote = u.autoSaveRemote
|
||||
u.debugLogHeaderBounds = u.settingsDraft.Debug.LogHeaderBounds
|
||||
if !u.debugLogHeaderBounds {
|
||||
u.lastHeaderBoundsLog = ""
|
||||
@@ -243,6 +250,7 @@ func (u *ui) applySecuritySettingsLive() error {
|
||||
func (u *ui) loadSettings() {
|
||||
u.syncDefaultSourceMode = syncSourceLocal
|
||||
u.syncDefaultDirection = syncDirectionPull
|
||||
u.autoSaveRemote = false
|
||||
|
||||
if strings.TrimSpace(u.settingsPath) != "" {
|
||||
content, err := os.ReadFile(u.settingsPath)
|
||||
@@ -251,6 +259,8 @@ func (u *ui) loadSettings() {
|
||||
if json.Unmarshal(content, &settings) == nil {
|
||||
u.syncDefaultSourceMode = sanitizeSyncSourceMode(syncSourceMode(settings.Sync.SourceDefault))
|
||||
u.syncDefaultDirection = sanitizeSyncDirection(syncDirection(settings.Sync.DirectionDefault))
|
||||
u.autoSaveRemote = settings.Sync.AutoSaveRemote
|
||||
u.state.AutoSaveRemote = u.autoSaveRemote
|
||||
u.debugLogHeaderBounds = settings.Debug.LogHeaderBounds
|
||||
return
|
||||
}
|
||||
@@ -258,6 +268,7 @@ func (u *ui) loadSettings() {
|
||||
}
|
||||
|
||||
u.loadLegacySyncDefaultsFromUIPreferences()
|
||||
u.state.AutoSaveRemote = u.autoSaveRemote
|
||||
}
|
||||
|
||||
func (u *ui) loadLegacySyncDefaultsFromUIPreferences() {
|
||||
@@ -287,6 +298,7 @@ func (u *ui) saveSettings() {
|
||||
Sync: syncSettings{
|
||||
SourceDefault: string(u.syncDefaultSourceMode),
|
||||
DirectionDefault: string(u.syncDefaultDirection),
|
||||
AutoSaveRemote: u.autoSaveRemote,
|
||||
},
|
||||
Debug: debugSettings{
|
||||
LogHeaderBounds: u.debugLogHeaderBounds,
|
||||
|
||||
Reference in New Issue
Block a user