Conflicts resolved by keeping both sides:
- ui-egui control.rs: UI_SET_FIELDS has main's updatesOpen and the
histogramPanel, histogramRange and histogramRefresh fields (42).
- automation server.rs: the ui_set description names all of them.
- docs/ui-parity.md: main's header, with the Histogram panel entry
added to its change list.
- docs/scorecard.md: regenerated with `cargo xtask scorecard`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Compact, Expanded and All Channels views; the channel is kept across views.
- Channels per colour mode, plus Luminosity and Colors (overlaid, mixed where
channels overlap); Show Channels in Color and Show Statistics in the panel menu.
- Statistics for the level under the pointer or a dragged range: Mean, Std Dev,
Median, Pixels, Level, Count, Percentile, Cache Level.
- Source (Entire Image, Selected Layer, Adjustment Composite) for multilayer
documents.
- Adjustment previews counted live, with the original outlined over them.
- Cached-data warning and Uncached Refresh; Preferences > Performance > Cache
Levels (1-8) caps the cache level.
- ui.set histogramPanel / histogramRange / histogramRefresh, ui.inspect histogram.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- control: tool, mode and stroke are parsed before anything changes, so a refused request leaves
the workspace as it was.
- A preview made from an older document revision is dropped (even mid-stroke), and a revision
change clears the shown texture and the pending result too.
- Show Edge applies the Refine Edge Brush only when the selection has content, as OK
(matting::refine_area) does.
- control-protocol.md documents `hideView`.
An agent's ui.menu.invoke reached the main window's menus while a full-window workspace was
open: window.document.N switched documents and the workspace closed, dropping its work.
Photoshop makes these dialogs modal.
menus::modal_allows now refuses other menu commands while one is open (distort_ui::
modal_workspace), so ui.menu.invoke and the macOS menu bar wait for OK or Cancel. The
control channel's Camera Raw continuation is generalised: the open workspace's own
{"ui": {...}} requests still pass, unless another dialog, a discard prompt or a crop is
pending. The menus' cache key includes the open workspace, so opening or cancelling one
without input rebuilds them. engine.execute (MCP run_command) is not a menu click and is
not gated.
Puppet Warp, Perspective Warp and Vanishing Point are on-canvas modes here, with the
in-window menus live, so they stay out.
Select > Select and Mask... opens a full-window workspace laid out as
Photoshop's, replacing the parameter dialog:
- options bar: tool, add/subtract, Size, Hardness (Brush), Sample All
Layers, Select Subject, Refine Hair (greyed: #2671)
- tools: Quick Selection W, Refine Edge Brush R, Brush B, Object
Selection W, Lasso and Polygonal Lasso L (one slot), Hand H, Zoom Z;
Shift+W / Shift+L cycle
- the document under its tab, shown in the chosen view
- Properties: Remember Settings, View Mode (view letters, Show Edge J,
Show Original P, Real-Time Refinement, High Quality Preview,
Transparency/Opacity, Overlay colour and Indicates), Refine Mode
(Object Aware greyed: #2788), Edge Detection, Global Refinements with
Clear Selection and Invert, Output Settings; Reset, OK, Cancel
The tools become select.refineEdge `edits` (the Refine Edge Brush its
`refineStrokes`): OK is one history step, Cancel drops everything,
Ctrl+Z undoes per edit. The preview runs in the background on a reduced
copy (full size with High Quality Preview), reusing the selection after
the edits it already applied; Real-Time Refinement previews the stroke
being drawn. A targeted layer mask is refined and output to the mask.
Closes#7069. Closes#8148.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bridge forwards Replace Contents to the app, which runs it on its
active document, so a given `index` was silently dropped and could replace
another document's contents. It is now refused before anything reaches the
app, as bridge previews and saves already do; documented in the schema and
control-protocol.md. A fake-app test checks the indexed call never arrives.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- crates/ui-egui/src/layer_style.rs: values_of keeps the PR's method/smoothness keys and source-stop ends, and main's (#7072) unconditional From/To and geometry fields.
- crates/compose/src/cmyk_tests.rs (no textual conflict): add the PR's new `interpolation: None` field to main's CMYK test GradientOverlay literal.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts:
- crates/ui-egui/src/i18n/{cs,de,el,es,fr,hu,id,it,ja,ko,nl,pl,pt-br,ru,sr,tr,uk,vi,zh-hans,zh-hant}.tsv: kept every key of both sides (main's block, then the PR's Color panel block); no duplicate keys.
- crates/ui-egui/src/panels.rs: took the PR's removal of color_picker/hsb_sliders/rgb_sliders (moved to color_panel_ui.rs); kept main's color_field_height doc comment; main's #5842 slider recolour tests ported to color_panel_tests.rs for the new HSB/RGB slider modes; main's black-HSB test dropped as the PR's hsb_sliders_take_values_on_black covers it.
- crates/ui-egui/src/color_panel_ui.rs (no textual conflict, adapted): set_color now goes through apply_color::foreground_changed with the gesture (was type_tool::foreground_changed), so every mode (sliders, ramp, alerts, wheel) recolours selected type/shapes tool-gated in one undo step per gesture; panel() calls apply_color::track_focus.
- crates/ui-egui/src/color_panel_tests.rs (adapted): new every_slider_mode_recolours_the_selected_shape test.
- docs/gaps.md, docs/ui-parity.md: union of both sides' status lines, rows and revision history; the PR's done row replaces the old "missing" Color panel row.
- docs/scorecard.md: generated, took b7-base's version.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts resolved:
- crates/ui-egui/src/i18n/hu.tsv: kept base's Bevel & Emboss keys, then the PR's update-check keys
- crates/ui-egui/src/i18n/ru.tsv: kept base's Bevel & Emboss keys, then the PR's update-check keys
- crates/ui-egui/src/i18n/sr.tsv: kept base's added sections, then the PR's update-check keys
- crates/ui-egui/src/i18n/tr.tsv: kept base's Bevel & Emboss keys, then the PR's update-check keys
- crates/ui-egui/src/menus.rs: kept base's saved-workspace entries, then the PR's Help › Check for Updates reordering
- docs/gaps.md: base status line with the PR's G17 clause prepended; PR revision row above base's rows
- docs/target-app-parity.md: base status line (updated 2026-10-22) with the PR's clause prepended; PR revision row above base's rows
- docs/scorecard.md: generated, took b7-base's version
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The rpc test only checked the returned layer id, so a no-op that echoed
{"layer": id} passed, its undo check passed on doc.place's own step, and
the bad-layer case asserted on an empty reason. It now checks the smart
object's file name and rendered centre pixel (42 -> 200 after the
replace, back to 42 on undo, 200 on redo), that every refusal changes
nothing, and that layer 999999 fails with "no such layer".
The bridge row in docs/control-protocol.md claimed doc_replace_smart_object
maps onto layer.smartObjects.replaceContents; the desktop refuses that
command (ambient path), like doc_place's file.placeEmbedded. The row now
says so and points to the headless / workspace server method.
Co-authored-by: VishnuByrraju <112673081+VishnuByrraju@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Main moved about 1,860 commits since the PR's last merge. i18n catalogs keep both
sides' rows; control.rs keeps updatesOpen next to main's strokeTrace (39 fields);
Services keeps check_updates next to main's place_inbox; Cargo.lock is main's,
re-resolved for ureq and semver; docs/gaps.md, docs/target-app-parity.md and
docs/scorecard.md are main's (the PR's entries come back in the next commit).
Co-authored-by: ZhuanTou33212 <285931757+ZhuanTou33212@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's Color panel HSB/RGB slider switch (#7172, #7317) is replaced by this
branch's panel-menu modes, which include RGB Sliders and HSB Sliders; its
control test now sets colorPanel.mode. The panel takes main's shared
photocraft_color HSB conversions and ui.set's f32-range checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep the brush Mode menu's early return in canvas_buttons ahead of main's
physical right-button handling, keep both sets of control tests, and keep
both notes in docs/brush-parity.md and docs/control-protocol.md.
crates/ui-egui/src/lib.rs: replay_save doc comment names both Export As and JPEG; replay_save uses the PR's FormatChoices::from_step, after main's export_dialog::replay branch.
docs/file-format-parity.md: header keeps main's text plus the JPEG Options item (last updated 2026-10-19); TIFF row is main's, JPEG row is the PR's; change-log rows once each, newest first.
docs/gaps.md: header keeps main's text plus the G10 item (last updated 2026-10-19).
crates/ui-egui/src/lib.rs: union in the PhotocraftApp fields, the initialiser and set_wgpu (main's window_device/window_lost/window_recovery_retry and set_available, the PR's gpu_render_state/gpu_fault).
docs/control-protocol.md: ui.gpu.simulateLoss line takes the PR's text and keeps main's destroy: true sentences.
crates/paint/src/brush_tests.rs: both sides added tests at the same spot; kept main's four smoothing tests and added the PR's three pose_axes tests after them.
docs/brush-parity.md: kept main's header and added the PR's change item.
docs/gaps.md: kept main's header, added the PR's change item; G4 progress notes and the change-log row kept from both sides.
docs/control-protocol.md: kept main's eyedropper line (with the document.sampleColor wording) and added the PR's Brush Pose line before it.
docs/control-protocol.md: kept main's table rows (document.inspect with snapshots, layer.list) and added the PR's four-floats wording to document.pixel.
openingRaw is {name, path, demosaic}; ui.demosaic is accepted only while a raw
opens; rawDefaults.demosaic is the method the app's raw opens develop with; Open
re-develops when the chosen method differs from the one the open used.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts only in the parity docs: status lines take main's text with the
JPEG Options entry (FILE-215-19) on top; scorecard takes main's rows with
FILE-215-19 done and File compatibility 10 / 12 / 5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
layer.smartObjects.replaceContents takes an ambient path and is refused in
serve/mcp. Add the capability-scoped sibling of doc.place: the file is read
beneath --automation-read-root and handed to the command's own core, as an
RPC method (doc.replaceSmartObject) and an MCP tool (doc_replace_smart_object).