fix: preserve plugin-set key images across profile re-renders#387
fix: preserve plugin-set key images across profile re-renders#387atomskz wants to merge 1 commit into
Conversation
|
This is a fix already discovered by @justmangoou, but I'm wary of accepting it because there must have been some reason for separation of Anyway, if it turns out that And finally, the ultimate fix is of course to actually discover why other keys are being re-rendered when they're not supposed to. It causes unnecessary churn in the entire frontend and of course causes device updates. If we prevent the unnecessary re-renders of other keys when one key is added/deleted (which seems to be the main trigger of this issue), this won't be necessary at all. Lastly, I'd rather read issue comments from a human than an LLM, if that's possible. |
|
Hi @nekename, thanks for taking the time to review this! On your suspicion — you're right, and I checked the history to be sure. The Why the write-back is incorrect. The replacement. I've reworked the change to leave the one-way design untouched and instead make + let lastInslot: ActionInstance | null | undefined;
const update = (inslot: ActionInstance | null) => {
+ if (inslot === lastInslot) return;
if (inslot && context && inslot.context.split(".")[0] != context.device) return;
+ lastInslot = inslot;
slot = inslot;
};The mechanism: on Compared to the write-back: same bug fixed, but nothing flows upward, the InstanceEditor inconsistency isn't made worse, and the runtime-vs-configured divergence stays where the design puts it — in On the re-renders themselves — I dug into why other keys re-render at all, and there are two layers. The If you'd rather go the remove-
Understood, and fair enough. I use models to format and translate my comments into English, since it isn't my native language. |
Key.svelte kept a plugin-set image only in the component-local `slot`, while the bound `inslot` stayed on the profile's loaded instance. A grid re-render (`profile = profile` after create/move/paste in DeviceView) re-runs `$: update(inslot)` for every key -- safe_not_equal treats an identical object reference as changed -- and the unconditional `slot = inslot` reset the key back to the loaded image. Guard `update()` so it only resets `slot` when the bound reference actually changed, keeping the one-way `inslot`/`slot` design intact: an untouched key early-returns and keeps its `slot`, while a genuine change (a fresh instance in the profile, or the update_state listener) still applies.
93e70f6 to
2c8fb68
Compare
|
Excellent work, thank you. That sounds like an acceptable fix that doesn't require changes in DeviceView. I'm away for a few more days this month but I'd be happy to test and merge this when I get back. As for LLM usage for translation, that's perfectly OK but you should just mention that you're using it for translation so that it doesn't come across the wrong way. |
Preflight checklist
If you remove this checklist, this pull request will be closed without explanation.
Fixes #386.
Problem
When a plugin updates a key's image via
setImage, the update is discarded on thenext profile grid re-render (e.g. after adding or moving any action), and the key
reverts to the image the profile was loaded with. No reconnect is involved.
Cause
slotis a Key's local working copy;inslotis the deliberate one-way downwardchannel from
profile.keys[](a plugin's per-sessionsetImagewrites onlyslot,never
profile). Onprofile = profile, Svelte'ssafe_not_equaltreats anidentical object reference as changed, so the reactive
$: update(inslot)re-runs forevery key even when its
profile.keys[i]didn't change;update()thenunconditionally does
slot = inslot, resetting the key to the loaded instance anddiscarding the plugin's image.
Fix
Make
update()idempotent: remember the last bound reference and skip the reset wheninslothasn't actually changed. The one-wayinslot/slotsplit stays intact —nothing propagates upward into
profile— while a genuine change (a fresh instancefrom the backend, or the
update_statelistener) still applies.The latch sits after the device filter, so a filtered entry is re-evaluated on the
next pass exactly as before, and
clear()'s upwardnullstill round-trips.Testing
setImage: set an image, restarted sothe profile loads it, set a different image this session, then added/moved another
action — the update now persists (previously the key reverted to the loaded image).
deno task checkand prettier are clean.