Skip to content

[UX] Wire SettingsView Save button to syncViewStateToGlobal #918

Description

@easonLiangWorldedtech

[UX] Wire SettingsView Save button to syncViewStateToGlobal

Problem

ClineProvider.syncViewStateToGlobal() exists as a method that pushes view-local state to global state, but there's no corresponding UI trigger in SettingsView. Users have no way to explicitly "sync" their per-tab settings to the shared global persistence layer.

Evidence

Code locations:

  • ClineProvider.ts:521-537: syncViewStateToGlobal() method — syncs mode, currentApiConfigName, apiConfiguration from viewLocalState to ContextProxy global state
  • SettingsView.tsx:376-458: handleSubmit() sends updateSettings message but doesn't call syncViewStateToGlobal()
  • No webview message handler for a "syncViewState" action

Reproduction:

1. Tab A: User modifies mode/apiConfig in SettingsView → changes saved to view-local state
2. Changes persist via saveViewState() to __view_state_{id}_* keys (session-scoped)
3. User wants these changes to apply to ALL tabs (sync to global state)
4. No UI mechanism exists to trigger syncViewStateToGlobal() from SettingsView
5. User must manually switch mode/apiConfig in each tab, or reload extension and hope shared keys match

Root Cause

syncViewStateToGlobal() was added as a utility method but never wired to the webview message protocol:

  1. No vscode.postMessage({ type: "syncViewState" }) handler in webviewMessageHandler.ts
  2. SettingsView's Save button only sends updateSettings (global settings) and upsertApiConfiguration (profile data), but doesn't trigger the view-local → global sync

Proposed Fix

Step 1: Add webview message type for syncViewState

// In ExtensionStateContext.tsx or a new message handler file:
case "syncViewState": {
    await provider.syncViewStateToGlobal()
    await provider.postStateToWebview()
    break
}

Step 2: Add "Sync View State" button to SettingsView header

// In SettingsView.tsx, add to providers tab header or settings toolbar:
{hasUnsyncedChanges && (
    <Button 
        variant="secondary" 
        size="sm"
        onClick={() => vscode.postMessage({ type: "syncViewState" })}
    >
        Sync View State
    </Button>
)}

// Track unsynced changes:
const [hasUnsyncedChanges, setHasUnsyncedChanges] = useState(false)

useEffect(() => {
    // Check if viewLocalState differs from global state
    const isSynced = 
        cachedState.mode === extensionState.mode &&
        cachedState.currentApiConfigName === extensionState.currentApiConfigName
    setHasUnsyncedChanges(!isSynced)
}, [cachedState, extensionState])

Step 3: Add VSCode command for power users (optional)

// In extension.ts or commands registration:
vscode.commands.registerCommand('zoo-code.syncViewState', async () => {
    const provider = ClineProvider.getInstance()
    if (provider) {
        await provider.syncViewStateToGlobal()
        vscode.window.showInformationMessage('View state synced to global settings')
    }
})

Scope

  • Impact: Power users who want to explicitly sync per-tab settings to all tabs
  • Risk: Low — existing syncViewStateToGlobal() logic is already tested; just adding UI trigger
  • Priority: Low (nice-to-have for power users, not critical for basic usage)

Design Considerations

  1. Button placement: Add "Sync View State" button in SettingsView header (next to Save/Cancel buttons) or as a separate command in the VSCode command palette
  2. Visibility: Only show when hasUnsyncedChanges is true (i.e., viewLocalState differs from global state)
  3. Feedback: Show toast notification after sync completes: "View state synced — changes now apply to all tabs"
  4. Documentation: Add comment in SettingsView explaining the difference between:
    • Save → Updates global settings (applies to all tabs immediately)
    • Sync View State → Pushes current tab's view-local overrides to global state

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions