Fix-up for #9979, #9182 and #10837: review findings on the batch

- #9979: ui.dialog.set can no longer rewrite an open field picker's __colorPicker
  marker (its OK went to the Crop shield instead of the field), and Preferences Apply
  waits for an open colour picker as OK does, so it never saves a previewed colour.
  Both have regression tests that fail without the fix.
- #9182: the stress test's PC_BUILD_ROUNDS / PC_BUILDS_PER_DEVICE fall back to the
  default for 0, which ran no builds and passed.
- #10837: the ROADMAP entry no longer says a Latin hint rules windows-1251 out; the
  hint settles a word-initial rare letter and breaks exact ties.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
David Mann
2026-11-04 13:22:51 +01:00
co-authored by Claude Opus 5.5
parent cbc674ea9a
commit f05bb0ea9b
6 changed files with 26 additions and 5 deletions
+1 -1
View File
@@ -122,7 +122,7 @@ Detail and the next releases: [docs/roadmap.md](docs/roadmap.md).
| Date | Entry |
|---|---|
| 2026-11-02 | Load Actions: Mac Roman step names with é ä ö ü Ä or ° read as Mac Roman instead of windows-1252 or Cyrillic (#10774): windows-1252's rare 0x80–0x9F letters and a lone Cyrillic letter in a Latin word no longer count as common text, the degree sign does, and a Latin hint rules windows-1251 out |
| 2026-11-02 | Load Actions: Mac Roman step names with é ä ö ü Ä or ° read as Mac Roman instead of windows-1252 or Cyrillic (#10774): windows-1252's rare 0x80–0x9F letters and a lone Cyrillic letter in a Latin word no longer count as common text, the degree sign does, and the file's own Unicode text settles a word-initial rare letter and breaks exact ties toward windows-1252 or Mac Roman |
| 2026-10-21 | Linux can use font-free Adwaita controls when System Title Bar is selected, while the integrated CSD title bar remains the default (as in #4439). Saved preferences are respected; startup and preference-dialog regressions cover both choices (#6266). |
| 2026-10-17 | Object Finder classifies background by boundary coverage, retaining large enclosed foregrounds and rejecting surrounding backdrop (#6548); learned segmentation remains open (#2788) |
| 2026-10-10 | Full re-measure against Photoshop 2026 27.11.0 (installed bundle inspected): breadth ~76%, ready ~45%, alpha. Progress docs reorganized (`parity.md` → `parity-checklist.md`, `parity-estimate.md` merged into `target-app-parity.md`). 0.6.0 released. |
+1 -1
View File
@@ -64,7 +64,7 @@ fn a_compositor_with_failed_pipelines_draws_without_panicking() {
#[ignore = "stress test: builds many compositors"]
fn parallel_compositor_builds_leave_the_shader_cache_intact() {
let _lock = GPU_LOCK.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
let var = |name: &str, default: u32| std::env::var(name).ok().and_then(|v| v.parse().ok()).unwrap_or(default);
let var = |name: &str, default: u32| std::env::var(name).ok().and_then(|v| v.parse::<u32>().ok()).filter(|&n| n > 0).unwrap_or(default);
let (rounds, builds) = (var("PC_BUILD_ROUNDS", 4), var("PC_BUILDS_PER_DEVICE", 8));
for round in 0..rounds {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle_from_env());
+3 -1
View File
@@ -1038,7 +1038,9 @@ fn dialog_set(app: &mut PhotocraftApp, p: &Value) -> Outcome {
Some(_) if field == crate::actions::RESUME => err("the paused action token is read-only"),
Some(_) if previewed => err("confirm or cancel the color picker first"),
// A Color Picker's target is fixed when it opens: OK must set the field it previewed in.
Some(d) if matches!(field, "__dialog" | "__field") && crate::color_picker_ui::owns(&d.fields) => err("a Color Picker's target is fixed when it opens"),
Some(d) if matches!(field, "__colorPicker" | "__dialog" | "__field") && crate::color_picker_ui::owns(&d.fields) => {
err("a Color Picker's target is fixed when it opens")
}
// A marker picks the handler OK runs: a dialog keeps the ones it was opened with.
Some(d) if !d.fields.contains_key(field) && crate::dialogs::is_route_marker(field) => err(format!("`{field}` is set only by the dialog it belongs to")),
Some(d) => {
+1 -1
View File
@@ -973,7 +973,7 @@ fn confirm_generic_command(app: &mut PhotocraftApp, d: Dialog) -> Result<Value,
/// The checks before a dialog is confirmed: no open child picker, the automation gate for a handler
/// that touches files itself, and a valid guide layout.
fn confirm_preflight(app: &mut PhotocraftApp, id: u64) -> Result<(), String> {
pub(crate) fn confirm_preflight(app: &mut PhotocraftApp, id: u64) -> Result<(), String> {
if crate::layer_style::color_picker::has_child(app, id) {
return Err("confirm or cancel the Layer Style color picker first".into());
}
@@ -3,7 +3,7 @@ use egui_kittest::Harness;
use serde_json::{Map, Value, json};
use super::*;
use crate::color_picker_ui::{open_for_field, open_requested, request};
use crate::color_picker_ui::{open_for_field, open_requested, request, request_field};
use crate::crop_shield::ShieldColor;
use crate::state::DialogKind;
@@ -315,6 +315,7 @@ fn a_pickers_target_stays_the_dialog_it_opened_on() {
};
assert_eq!(set(&mut app, "__dialog", json!(other)), Some(false));
assert_eq!(set(&mut app, "__field", json!("opacity")), Some(false));
assert_eq!(set(&mut app, "__colorPicker", json!("cropShield")), Some(false), "nor can its OK go to the Crop shield");
assert_eq!(set(&mut app, "color", json!("#336699")), Some(true), "the colour itself stays drivable");
assert_eq!(fields(&app, fill)["color"], json!("#336699"));
@@ -324,3 +325,19 @@ fn a_pickers_target_stays_the_dialog_it_opened_on() {
assert!(app.ui.dialogs.iter().any(|d| d.id == picker), "the picker stays with its own dialog");
assert_eq!(fields(&app, fill)["color"], json!("#336699"), "and keeps previewing there");
}
/// Preferences › Apply, like OK, waits for an open colour picker: it would otherwise save the
/// colour the picker previews and may still cancel.
#[test]
fn preferences_apply_waits_for_an_open_picker() {
let mut app = app();
let prefs = crate::prefs_ui::open_preferences(&mut app, "guidesGridAndSlices");
let before = app.session.prefs().guides_grid_and_slices.guide_color.clone();
let f = &mut app.ui.dialog_mut(prefs).unwrap().fields;
request_field(f, "/values/guidesGridAndSlices/guideColor", "Color Picker (Guide Color)");
open_requested(&mut app, prefs);
let picker = crate::color_picker_ui::top(&app).expect("the picker opens over Preferences");
pick(&mut app, picker, "#ff8000");
assert!(crate::prefs_ui::apply(&mut app, prefs).is_err(), "Apply refuses while the picker is open");
assert_eq!(app.session.prefs().guides_grid_and_slices.guide_color, before, "nothing is saved");
}
@@ -101,6 +101,8 @@ pub fn apply(app: &mut PhotocraftApp, id: u64) -> Result<Value, String> {
return Err("Apply is only available for Preferences".into());
}
let fields = d.fields.clone();
// As OK does: an open colour picker would leave a previewed colour in the applied values.
crate::dialogs::confirm_preflight(app, id)?;
let result = confirm(app, &fields)?;
let values = Value::Object(preference_values(app.session.prefs()));
if let Some(d) = app.ui.dialog_mut(id) {