Registry View: inline edit, rename, delete with success/error feedback#818
Open
kanhaiyaXITE wants to merge 1 commit into
Open
Registry View: inline edit, rename, delete with success/error feedback#818kanhaiyaXITE wants to merge 1 commit into
kanhaiyaXITE wants to merge 1 commit into
Conversation
Builds on PR rokucommunity#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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes the Roku Registry side panel actually editable end-to-end:
The initial registry read is now also wrapped in
try/finallyso the loader can no longer get stuck spinning ifreadRegistryrejects — that case now resolves to a toast + empty state.Motivation
The rewritten Registry View from #784 + the Svelte 5 compat fix from #808 give us a working panel, but it's been read-only in practice:
Edit/Copy/Trashicons didn't visibly do much for users who weren't expecting hover-only controls.section → key → string), but applications routinely store JSON-encoded objects as the string at level 2 — so the data users actually see and care about can be N levels deep.formatValues()parses those strings back into a tree for display. The old code wrote the leaf's local key at the top of the section instead of mutating the enclosing JSON blob, so editing e.g.com.xite.Xite.staging.screen_show_counts.get_startedfrom2to0added a newget_started: 0sibling next toscreen_show_countsinstead of updating the nested value. The same bug affected nested delete.What changed
Webview (
webviews/src/views/RokuRegistryView/)RegistryNode.svelte— replaced the per-row Edit/Copy buttons with a dblclick gesture on key + value spans; bound the cells to a context-driven ack store for the success/error flash; trash icon stays as the one always-visible action.RegistryTree.svelte— handler set is nowvalueChanged,keyRenamed,deleteItem,deleteSection. AddscloneTopLevel/navigateToParenthelpers that share the nested-write plumbing across the three mutating handlers.coerceNestedValuepreserves number / boolean / null primitives through the JSON round-trip so re-stringification doesn't change types. All write paths use a single error-toast helper.RokuRegistryView.svelte—loadRegistry()wrapper aroundreadRegistry()withtry/finally; the spinner can no longer hang.N-level write support
RegistryNodeexposes two extra props through the recursivesvelte:self:topLevelKey— the depth-1 registry key whose JSON-encoded string value owns this subtree.pathInTopLevel: string[]— the path inside the parsed object, inclusive of the current leaf. No length cap — works at any depth.RegistryTreebranches onpathInTopLevel.length:writeRegistryas before ({ key: null, newKey: value }etc.).pathInTopLevelto the leaf's parent, apply the mutation, re-stringify, and write the whole blob back under the original top-level key.The only hard requirement is the one Roku itself imposes: at the wire, the level-2 value must be a string, so any nested mutation is followed by
JSON.stringifyof the whole subtree.Extension host
src/viewProviders/ViewProviderCommand.ts— one new enum entry,showErrorMessage.src/viewProviders/BaseWebviewViewProvider.ts— one new else-if in the central message router, alongsidesetVscodeContext/getVscodeContext/sendMessageToWebviews. Callsvscode.window.showErrorMessage(message.context.message).webviews/src/ExtensionIntermediary.ts— one newshowErrorMessage(message)helper that posts the command.No changes to the RTA / ODC pipeline — every mutation goes through the existing
writeRegistry/deleteRegistrySectionscalls.Test plan
Manual verification via the Extension Development Host against a real Roku device with the on-device component active:
access_token) → edit, Enter → device updates, cell flashes green.screen_show_counts.get_started,2 → 0) → updates the nested entry only; no new top-level sibling appears.a.b.c.d.…) work the same way —pathInTopLevelcarries the full chain.nullvalues inside nested objects round-trip through edit + re-stringify with their original primitive type.Out of scope
Export/Import/Clearregistry commands inRokuRegistryViewProvider.ts.Repro of the nested-write bug on
masterIf you want to confirm the bug exists today (before this PR):
screen_show_counts.get_started: 2.2to0→ confirm.get_started: 0at the top level of the section, with the original nested value untouched.This PR fixes that path.