From 4920c054e87f304876d0110a4dc067d1d12d2394 Mon Sep 17 00:00:00 2001 From: Kanhaiya Kumar <113596215+kanhaiyaXITE@users.noreply.github.com> Date: Fri, 29 May 2026 13:30:58 +0200 Subject: [PATCH] Registry View: inline edit, rename, delete with success/error feedback Builds on PR #808's Svelte 5 fix to make the Roku Registry side-panel actually editable end-to-end. UI: - Double-click a value cell to edit; Enter or click-away commits; Escape cancels. - Double-click a key name (depth >= 1) to rename. Section keys at depth 0 stay non-renamable since they're app namespaces. - Trash icon visible on hover for every row: deletes a leaf key, a nested entry, or a whole section. Correct nested writes: - The registry is a 2-level store (section -> key -> string) but formatValues() recursively JSON.parses string values into a tree that often goes 3+ levels deep. Writing a leaf's local key at the top of the section creates a sibling instead of mutating the enclosing JSON blob, which is what the rewritten Registry View was doing before this change (you can repro on master by editing e.g. com.xite.Xite.staging.screen_show_counts.get_started). - RegistryNode now threads `topLevelKey` + `pathInTopLevel` through the recursive svelte:self. RegistryTree branches on pathInTopLevel.length: depth-1 edits/renames/deletes use the existing merge-semantic writeRegistry; deeper edits deep-clone the parsed top-level object, apply the mutation, and write back the re-stringified blob under the original top-level key. - coerceNestedValue preserves number/boolean/null primitives through the round-trip so re-stringification doesn't silently change types. Feedback: - A new ViewProviderCommand.showErrorMessage, routed in BaseWebviewViewProvider alongside setVscodeContext/getVscodeContext, lets the webview ask the host to show a vscode error toast. Used for all write failures and for the initial registry read. - The two readRegistry callers in RokuRegistryView.svelte are wrapped in try/finally so the loader always clears -- previously a rejected read would leave the panel spinning forever. - A Svelte context store from RegistryTree -> RegistryNode pushes an ack signal after each write; the matching cell briefly flashes green on success or red on failure (~1.6s CSS animation). On delete success the row disappears so no flash is fired. No extension-host ODC pipeline changes. All edits go through the existing writeRegistry / deleteRegistrySections merge semantics. --- src/viewProviders/BaseWebviewViewProvider.ts | 2 + src/viewProviders/ViewProviderCommand.ts | 1 + webviews/src/ExtensionIntermediary.ts | 6 + .../RokuRegistryView/RegistryNode.svelte | 264 ++++++++++++++---- .../RokuRegistryView/RegistryTree.svelte | 200 ++++++++++++- .../RokuRegistryView/RokuRegistryView.svelte | 27 +- 6 files changed, 427 insertions(+), 73 deletions(-) diff --git a/src/viewProviders/BaseWebviewViewProvider.ts b/src/viewProviders/BaseWebviewViewProvider.ts index 024e2dac2..b0d55ab9e 100644 --- a/src/viewProviders/BaseWebviewViewProvider.ts +++ b/src/viewProviders/BaseWebviewViewProvider.ts @@ -135,6 +135,8 @@ export abstract class BaseWebviewViewProvider implements vscode.WebviewViewProvi } else if (command === ViewProviderCommand.sendMessageToWebviews) { const context = message.context; this.webviewViewProviderManager.sendMessageToWebviews(context.viewIds, context.message); + } else if (command === ViewProviderCommand.showErrorMessage) { + void vscode.window.showErrorMessage(message.context.message); } else if (command === ViewProviderCommand.updateWorkspaceState) { const context = message.context; await this.extensionContext.workspaceState.update(context.key, context.value); diff --git a/src/viewProviders/ViewProviderCommand.ts b/src/viewProviders/ViewProviderCommand.ts index a8e9aacfa..b512e1056 100644 --- a/src/viewProviders/ViewProviderCommand.ts +++ b/src/viewProviders/ViewProviderCommand.ts @@ -13,6 +13,7 @@ export enum ViewProviderCommand { sendReplRequest = 'sendReplRequest', setManualIpAddress = 'setManualIpAddress', setVscodeContext = 'setVscodeContext', + showErrorMessage = 'showErrorMessage', stopRokuAutomationConfig = 'stopRokuAutomationConfig', storeRokuAppOverlays = 'storeRokuAppOverlays', storeRokuAutomationConfigs = 'storeRokuAutomationConfigs', diff --git a/webviews/src/ExtensionIntermediary.ts b/webviews/src/ExtensionIntermediary.ts index 92475e9fc..611ef7e94 100644 --- a/webviews/src/ExtensionIntermediary.ts +++ b/webviews/src/ExtensionIntermediary.ts @@ -142,6 +142,12 @@ class ExtensionIntermediary { this.observedEvents.set(eventName, observedEvent); } + public showErrorMessage(message: string) { + this.postMessage(this.createCommandMessage(ViewProviderCommand.showErrorMessage, { + message: message + })); + } + public sendMessageToWebviews(viewIds: string | string[], message) { if (!viewIds || (Array.isArray(viewIds) && viewIds.length === 0)) { return; diff --git a/webviews/src/views/RokuRegistryView/RegistryNode.svelte b/webviews/src/views/RokuRegistryView/RegistryNode.svelte index c38e8c50f..718c190cc 100644 --- a/webviews/src/views/RokuRegistryView/RegistryNode.svelte +++ b/webviews/src/views/RokuRegistryView/RegistryNode.svelte @@ -1,19 +1,27 @@