Repository navigation
Electron: sharper drag previews and a faster 1:1 view after an edit - #26
Merged
Merged
Conversation
The Electron client now uses the backend's editing-speed calls. - Drag frames render through PreviewDraft at the size the photo covers in the loupe at fit, in device pixels, between 1024 and 2560. They were a fixed 1024, too soft to judge an edit by on a large screen. - A hovered preset's sharp frame is a PreviewDraft at 2048, never a PreviewEdit settle. The backend reads every settle as "the editor is now on this state" and would move its kept decode to the hovered look. - The Develop panel holds its photo open with OpenInEditor after a 350 ms dwell, so skimming starts no hold per step. A hold that ends with an error is made again after 1 s, 5 s, 5 s, then every 30 s. - After an edit of the held photo, its 1:1 render starts at once instead of after the skimming dwell. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The 1:1 render after the user's own save now really starts without the skimming dwell. The edit session records the hash each save produced, and the loupe passes "immediate" to useTilesWarm whenever tiles come to be wanted for that state. tiles.ts no longer reads editor state, so the guest page does not pull it in. - Drag frames stop at 2048, the settle's size, so letting go of a slider never softens the photo. - A hovered preset's sharp frame is a PreviewExact: the same pixels the apply gives, without telling the backend the editor is on it. Its key carries a hover flag, so a second settle request during one hover is skipped and the apply after it still settles. - The photo is held open after a 1 s dwell, not 350 ms, so stepping through photos in Develop does not start a decode per step. - Develop holds the photo its loupe shows, however many are selected. - A hold lost with the connection is made again as soon as the client is connected. Backend errors are tried again after 5, 30 and 30 s, then given up with one warning. - Drag frames follow device pixel ratio changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SetEditParams now returns the save's hash and number together. The edit session takes the hash from it, as before, for the 1:1 render that starts without a pause after the user's own save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ives The signal for skipping the skimming dwell was the hash SetEditParams returned. It came too late: the patch with the new hash reaches the loupe before the answer. Saves with several photos selected never set it, and it outlived a switch to another photo. - Each save of the session's photo, at any selection size, now records the hash it was made over. Once the shown photo's hash moves past it, the 1:1 render skips the dwell. A photo switch, or warm tiles, forget it. The returned hash is no longer used. - useTilesWarm cuts a dwell already under way short when `immediate` turns true, instead of reading it only as the dwell starts. - Tests: a dwell cut short, a multi-photo save, forgetting on a photo switch and once warm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts tiles Round 3 of review found two gaps in the 1:1 render after the user's own save: - The loupe read the last state's tile warmth in the render the next hash arrived in, and so forgot the save before its tiles existed. The warmth useTilesWarm reports is now for the tile set it was found for, and the save is forgotten only when its own result's tiles are warm. - Holding undo or stepping the history started and aborted a full render per step. Saves of the photo are now numbered and counted while out. The dwell is skipped only once no save is out and the photo shows the newest save's result. That path still waits 120 ms, so a burst of saves makes one render. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server numbers edit saves in the order they are written, but aprot delivers each subscriber's patches on its own goroutine, so two saves of one photo can arrive in reverse. The grid kept whichever came last and could end on the overwritten edit. The photo list now remembers the highest save number applied per photo and skips the edit fields (hash, rotation, crop) of an older one. Rating, flag and the other fields of that patch still apply, and patches with no number apply as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Saves of the session's photo take numbers from one counter that never restarts. A save sent before a photo switch can no longer answer into the record of a save made after coming back. - The record keeps the hash the photo showed before its first save, so a save that changes nothing (crop entered and left) no longer hides the real edit before it. - The user's own Reset of the session's photo is counted like any save. Its hash is not returned, so whether the photo moved on decides. - Tile warmth is forgotten on leaving a state, and when a probe finds a once-warm tile set gone, so evicted tiles read cold again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The record keeps, for the newest save that changed something, the hash the loupe showed when it was sent and the hash it saved. A paste or a Reset, whose result is unknown, counts once the photo has moved past the hash it was sent from. So a paste answered before its patch no longer takes the overwritten earlier hash for its result, and a Reset back to the photo's original hash counts. - A save that changes nothing still leaves the real edit before it. - Tile warmth is kept when only `kick` changes (a guest pinching past 2x, cull fit to 1:1 on a HiDPI screen), so tiles on screen stay up. - photoPatchReducer is documented as reading and raising the edit-save numbers it has seen, and the tests reset them, so test order can't matter. A full reload of the list is taken as is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paste and reset now return what they saved, like a single save does, so the edit session no longer guesses a paste's or a reset's result from the hash it was sent from. - The record keeps the hash the newest save that changed something saved. A save that changes nothing, or fails, leaves the result before it, so a failed save no longer hides the edit still on screen. - Paste and reset take the session photo's entry from their answer. - The 1:1 render skips the long dwell when no save is out and the photo shows that hash. The unknown-result rule is gone. - useTilesWarm records what the render asked for in a layout effect, not during render, so a render React throws away can't reach its cleanup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 20, 2026
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.
The Electron app gets the editing-speed work: sharper drag previews, the photo held open in Develop, and the 1:1 render after your own edit starting almost at once. Stacked on server PR #24.
What changes
Edits.PreviewDraftat what the photo covers in the loupe at fit, in device pixels, from 1024 to 2048. They were a fixed 1024. The cap is 2048, so letting go never softens the frame. The size follows device pixel ratio changes (useDevicePixelRatio).Edits.PreviewExact. It is exact like the settle, but it doesn't tell the server the editor is on that state.Edits.OpenInEditor(client/src/lib/editorHold.ts).immediatetouseTilesWarmwhen no save is out and the photo shows that hash.DEVELOPER.mdand an UnreleasedCHANGELOG.mdsection describe the change.Tests
npm run typecheck,npm run lint(oxlint) andnpx vitest runpass: 164 tests.scripts/ui-verify.mjsstops attimeout: clipboardon this box, as it does on the base branch.7 review rounds; the last one found nothing new.
🤖 Generated with Claude Code