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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions