Rolls: opt-in per-roll edit fork for a shared photo - #1126
Draft
PabloRuizCuevas wants to merge 3 commits into
Draft
PabloRuizCuevas wants to merge 3 commits into
PabloRuizCuevas wants to merge 3 commits into
Conversation
… workflow Rolls (negpy/services/assets/rolls.py) replace folders as the library's primary listing: importing a folder recognizes it as a roll; Save as Roll… turns any loaded batch into a reopenable virtual roll, not necessarily from one folder. The Library tree lists every roll flat, color-coded (folder amber, virtual coral, no left-side twisty gutter), with Rename…, bulk Delete…, and an opt-in "rename the folder on disk" checkbox that rehomes every loaded path when the renamed roll is the active one. Roll Settings dialog tags gear, capture, place, process and scanning metadata for the current frame, a selection, or the whole roll in one dialog, with a Load-preset flow to fill and tick fields. New Roll moves off the toolbar onto the Film Strip section's own header menu (CollapsibleSection.set_actions_menu), next to Reset Roll to Defaults — a roll-wide reset (reused _asset_defaults, one frame's worth of logic applied to every visible one) with its own confirm dialog. The top-level toolbar is gone: actions live in the row of the section they act on, Library's own corner row or the Film Strip row next to the loaded frames. restore_session now recognizes the active roll on restart too, the same "only when unambiguous" rule an already-open multi-folder session uses. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A photo can already belong to more than one roll, and its edit is shared wherever it's opened from -- by design. This adds an explicit, reversible way to break that sharing for one frame under one roll: "Edit Independently in This Roll" (right-click a frame that belongs to 2+ rolls) seeds an independent copy of the whole edit; "Use the Shared Edit Again" deletes it and reverts. Identity reuses the half-frame hash-suffix convention (`#roll:<id>` instead of `#<half>`), so every existing hash-keyed store -- edits, undo history, thumbnails, render cache -- picks up the fork for free with no schema change. Triage marks and legacy-hash migration read through the suffix (`unforked_hash`), since a keep/reject judgement belongs to the physical scan, not to one roll's fork of it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
fork_edit's config parameter is typed WorkspaceConfig; a plain object() sentinel fails ty's strict argument check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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
A photo can already belong to more than one roll, and its edit is shared wherever it's opened from -- by design. This adds an explicit, reversible way to break that sharing for one frame under one roll.
#roll:<id>instead of#<half>), so every existing hash-keyed store -- edits, undo history, thumbnails, render cache -- picks up the fork for free with no schema change.AppController._apply_roll_forks()rewrites a discovered asset's hash to its fork on open;load_or_promote()'s newforkedflag keeps a fork from ever falling back to the shared edit's path-based recovery or sidecar (which would otherwise steal or delete the shared row).unforked_hash), since a keep/reject judgement belongs to the scan itself, not to one roll's fork of it.Depends on #1109 for the Roll concept (
negpy/services/assets/rolls.py, the rolls store) this fork mechanism is layered on top of.Note: this PR is based on
mainbut its branch includes #1109's commits (the Roll concept the fork mechanism depends on) -- please review/merge #1109 first. Once it lands, this diff will automatically shrink to just the roll-fork changes.Testing
make all(ruff check/format, full pytest) passes with only one known unrelated failure (test_load_tooltip_follows_a_rebinding, a macOS key-symbol rendering difference, pre-existing onmain). Fork-specific coverage:tests/test_rolls.py(roll_edit_hash,unforked_hash,fork_edit,is_forked,unfork_edit),tests/test_roll_edit_fork.py(AppController._apply_roll_forks,request_fork_edit_for_roll,request_unfork_edit_for_roll),tests/test_sidecar.py(load_or_promote'sforkedflag skips path/sidecar fallback), andtests/test_file_browser_widget.py(the context-menu entries).🤖 Generated with Claude Code