mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
Merge pull request #7081 from Kilo-Org/mark/fix-settings-panel-reload
fix(vscode): restore settings view and active tab after webview reload
This commit is contained in:
@@ -18,6 +18,7 @@ type PanelView = "settings" | "profile"
|
||||
export class SettingsEditorProvider implements vscode.Disposable {
|
||||
private panels = new Map<PanelView, vscode.WebviewPanel>()
|
||||
private providers = new Map<PanelView, KiloProvider>()
|
||||
private tabs = new Map<PanelView, string>()
|
||||
|
||||
constructor(
|
||||
private readonly extensionUri: vscode.Uri,
|
||||
@@ -25,9 +26,15 @@ export class SettingsEditorProvider implements vscode.Disposable {
|
||||
private readonly context: vscode.ExtensionContext,
|
||||
) {}
|
||||
|
||||
openPanel(view: PanelView): void {
|
||||
openPanel(view: PanelView, tab?: string): void {
|
||||
if (tab) this.tabs.set(view, tab)
|
||||
|
||||
const existing = this.panels.get(view)
|
||||
if (existing) {
|
||||
if (tab) {
|
||||
const provider = this.providers.get(view)
|
||||
provider?.postMessage({ type: "navigate", view, tab })
|
||||
}
|
||||
existing.reveal(vscode.ViewColumn.One)
|
||||
return
|
||||
}
|
||||
@@ -57,14 +64,21 @@ export class SettingsEditorProvider implements vscode.Disposable {
|
||||
}
|
||||
})
|
||||
|
||||
// Once the webview signals ready, navigate to the target view.
|
||||
// Navigate to the target view on every webviewReady (including after
|
||||
// "Developer: Reload Webviews" which re-creates the JS context).
|
||||
const readyDisposable = panel.webview.onDidReceiveMessage((msg) => {
|
||||
if (msg.type === "webviewReady") {
|
||||
// Small delay to let KiloProvider's own webviewReady handler finish first
|
||||
setTimeout(() => {
|
||||
provider.postMessage({ type: "navigate", view })
|
||||
provider.postMessage({ type: "navigate", view, tab: this.tabs.get(view) })
|
||||
}, 50)
|
||||
readyDisposable.dispose()
|
||||
}
|
||||
})
|
||||
|
||||
// Remember the active settings tab so it survives webview reloads.
|
||||
const tabDisposable = panel.webview.onDidReceiveMessage((msg) => {
|
||||
if (msg.type === "settingsTabChanged" && typeof msg.tab === "string") {
|
||||
this.tabs.set(view, msg.tab)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -74,9 +88,12 @@ export class SettingsEditorProvider implements vscode.Disposable {
|
||||
panel.onDidDispose(() => {
|
||||
console.log(`[Kilo New] ${title} panel disposed`)
|
||||
closePanelDisposable.dispose()
|
||||
readyDisposable.dispose()
|
||||
tabDisposable.dispose()
|
||||
provider.dispose()
|
||||
this.panels.delete(view)
|
||||
this.providers.delete(view)
|
||||
this.tabs.delete(view)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -176,6 +176,7 @@ export const LanguageBridge: Component<{ children: any }> = (props) => {
|
||||
// Inner app component that uses the contexts
|
||||
const AppContent: Component = () => {
|
||||
const [currentView, setCurrentView] = createSignal<ViewType>("newTask")
|
||||
const [settingsTab, setSettingsTab] = createSignal<string | undefined>()
|
||||
const [migrationReturnView, setMigrationReturnView] = createSignal<ViewType>("newTask") // legacy-migration
|
||||
const session = useSession()
|
||||
const server = useServer()
|
||||
@@ -212,7 +213,8 @@ const AppContent: Component = () => {
|
||||
handleViewAction(message.action)
|
||||
}
|
||||
if (message?.type === "navigate" && message.view && VALID_VIEWS.has(message.view)) {
|
||||
console.log("[Kilo New] App: 🧭 navigate:", message.view)
|
||||
console.log("[Kilo New] App: 🧭 navigate:", message.view, message.tab ? `tab=${message.tab}` : "")
|
||||
if (message.tab) setSettingsTab(message.tab)
|
||||
setCurrentView(message.view as ViewType)
|
||||
}
|
||||
if (message?.type === "openCloudSession" && message.sessionId) {
|
||||
@@ -267,6 +269,8 @@ const AppContent: Component = () => {
|
||||
</Match>
|
||||
<Match when={currentView() === "settings"}>
|
||||
<Settings
|
||||
tab={settingsTab()}
|
||||
onTabChange={setSettingsTab}
|
||||
onMigrateClick={() => {
|
||||
setMigrationReturnView("settings")
|
||||
setCurrentView("migration")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component } from "solid-js"
|
||||
import { Component, createSignal, createEffect, on } from "solid-js"
|
||||
import { Icon } from "@kilocode/kilo-ui/icon"
|
||||
import { Tabs } from "@kilocode/kilo-ui/tabs"
|
||||
import { useVSCode } from "../../context/vscode"
|
||||
import { useLanguage } from "../../context/language"
|
||||
import ProvidersTab from "./ProvidersTab"
|
||||
import AgentBehaviourTab from "./AgentBehaviourTab"
|
||||
@@ -19,12 +20,32 @@ import AboutKiloCodeTab from "./AboutKiloCodeTab"
|
||||
import { useServer } from "../../context/server"
|
||||
|
||||
export interface SettingsProps {
|
||||
tab?: string
|
||||
onTabChange?: (tab: string) => void
|
||||
onMigrateClick?: () => void // legacy-migration
|
||||
}
|
||||
|
||||
const Settings: Component<SettingsProps> = (props) => {
|
||||
const server = useServer()
|
||||
const language = useLanguage()
|
||||
const vscode = useVSCode()
|
||||
const [active, setActive] = createSignal(props.tab ?? "providers")
|
||||
|
||||
// Sync when the parent changes the tab prop (e.g. via navigate message)
|
||||
createEffect(
|
||||
on(
|
||||
() => props.tab,
|
||||
(tab) => {
|
||||
if (tab) setActive(tab)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
const onTabChange = (tab: string) => {
|
||||
setActive(tab)
|
||||
props.onTabChange?.(tab)
|
||||
vscode.postMessage({ type: "settingsTabChanged", tab })
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", "flex-direction": "column", height: "100%" }}>
|
||||
@@ -42,7 +63,13 @@ const Settings: Component<SettingsProps> = (props) => {
|
||||
</div>
|
||||
|
||||
{/* Settings tabs */}
|
||||
<Tabs orientation="vertical" variant="settings" defaultValue="providers" style={{ flex: 1, overflow: "hidden" }}>
|
||||
<Tabs
|
||||
orientation="vertical"
|
||||
variant="settings"
|
||||
value={active()}
|
||||
onChange={onTabChange}
|
||||
style={{ flex: 1, overflow: "hidden" }}
|
||||
>
|
||||
<Tabs.List>
|
||||
<Tabs.Trigger value="providers">
|
||||
<Icon name="providers" />
|
||||
|
||||
@@ -557,6 +557,7 @@ export interface DeviceAuthCancelledMessage {
|
||||
export interface NavigateMessage {
|
||||
type: "navigate"
|
||||
view: "newTask" | "marketplace" | "history" | "cloudHistory" | "profile" | "settings" | "migration" | "subAgentViewer" // legacy-migration: "migration"
|
||||
tab?: string
|
||||
}
|
||||
|
||||
export interface ProvidersLoadedMessage {
|
||||
@@ -1327,6 +1328,11 @@ export interface ResetAllSettingsRequest {
|
||||
type: "resetAllSettings"
|
||||
}
|
||||
|
||||
export interface SettingsTabChangedMessage {
|
||||
type: "settingsTabChanged"
|
||||
tab: string
|
||||
}
|
||||
|
||||
export interface RequestNotificationsMessage {
|
||||
type: "requestNotifications"
|
||||
}
|
||||
@@ -1638,6 +1644,7 @@ export type WebviewMessage =
|
||||
| UpdateConfigMessage
|
||||
| RequestNotificationSettingsMessage
|
||||
| ResetAllSettingsRequest
|
||||
| SettingsTabChangedMessage
|
||||
| SyncSessionRequest
|
||||
| CreateWorktreeSessionRequest
|
||||
| RequestNotificationsMessage
|
||||
|
||||
Reference in New Issue
Block a user