mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-28 04:16:46 -06:00
Keep consecutive spaces in recent file accessible names
Fixes #436 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
8482c3e85b
commit
72a3c8522f
@@ -813,6 +813,11 @@ pub fn button(resp: &Response, tip: &str) {
|
||||
});
|
||||
}
|
||||
|
||||
/// A button named by `label` as it is: no key is split off (a file name may hold two spaces).
|
||||
pub fn named_button(resp: &Response, label: &str) {
|
||||
node(resp, label, |n| n.set_role(Role::Button));
|
||||
}
|
||||
|
||||
/// A link, named by its text.
|
||||
pub fn link(resp: &Response, label: &str) {
|
||||
node(resp, label, |n| n.set_role(Role::Link));
|
||||
|
||||
@@ -738,7 +738,7 @@ fn grid(ui: &mut Ui, t: &Tokens, recents: &mut Recents, files: &[Shown], now: u6
|
||||
for (i, file) in row.iter().enumerate() {
|
||||
let rect = Rect::from_min_size(pos2(r.min.x + i as f32 * (card_w + GAP), r.min.y), vec2(card_w, card_h));
|
||||
let resp = ui.interact(rect, card_id(&file.path), Sense::click());
|
||||
a11y::button(&resp, &spoken(file, now));
|
||||
a11y::named_button(&resp, &spoken(file, now));
|
||||
let resp = resp.on_hover_text(&file.path);
|
||||
let visible = ui.is_rect_visible(rect);
|
||||
let picture = recents.picture(&file.path, visible, time);
|
||||
@@ -878,7 +878,7 @@ fn list(ui: &mut Ui, t: &Tokens, recents: &mut Recents, files: &[Shown], now: u6
|
||||
for file in files {
|
||||
let (r, _) = ui.allocate_exact_size(vec2(width, ROW_H), Sense::hover());
|
||||
let resp = ui.interact(r, card_id(&file.path), Sense::click());
|
||||
a11y::button(&resp, &spoken(file, now));
|
||||
a11y::named_button(&resp, &spoken(file, now));
|
||||
let resp = resp.on_hover_text(&file.path);
|
||||
if let Some(a) = interact(ui, &resp, recents, file) {
|
||||
action = Some(a);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
//! Recent file rows keep their full accessible name.
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
||||
|
||||
use egui::{Context, Id, Pos2, RawInput, Rect, accesskit::Role, vec2};
|
||||
use figcraft_engine::Session;
|
||||
use figcraft_ui_egui::{FigApp, NoServices};
|
||||
|
||||
/// Render the home screen in `view` with `path` (and a single-space control) as recents and return
|
||||
/// the row's (label, shortcut, focused name).
|
||||
fn row(view: &str, path: &str, prefix: &str, exclude: &str) -> (String, Option<String>, String) {
|
||||
let mut session = Session::empty();
|
||||
session.prefs.recent_files = vec![path.into(), "Q3 report.figcraft".into()];
|
||||
session.prefs.getting_started_dismissed = true;
|
||||
session.prefs.home_views.insert("recents".into(), view.into());
|
||||
let mut app = FigApp::new(session, Box::new(NoServices));
|
||||
app.ui.home = true;
|
||||
let ctx = Context::default();
|
||||
ctx.enable_accesskit();
|
||||
let mut found = None;
|
||||
for frame in 0..4 {
|
||||
if frame >= 2 {
|
||||
ctx.memory_mut(|m| m.request_focus(Id::new(("home_recent_file", path))));
|
||||
}
|
||||
let mut out = ctx.run_ui(
|
||||
RawInput {
|
||||
screen_rect: Some(Rect::from_min_size(Pos2::ZERO, vec2(1440.0, 900.0))),
|
||||
time: Some(frame as f64 / 60.0),
|
||||
..Default::default()
|
||||
},
|
||||
|ui| app.ui(ui),
|
||||
);
|
||||
out.textures_delta.clear();
|
||||
if frame == 3 {
|
||||
let nodes = out.platform_output.accesskit_update.unwrap().nodes;
|
||||
let mut matches = nodes.iter().map(|(_, n)| n).filter(|n| {
|
||||
n.role() == Role::Button && n.label().is_some_and(|s| s.starts_with(prefix) && (exclude.is_empty() || !s.starts_with(exclude)))
|
||||
});
|
||||
let n = matches.next().expect("file row");
|
||||
assert!(matches.next().is_none(), "{view}: more than one row matches {prefix:?}");
|
||||
found = Some((
|
||||
n.label().unwrap_or_default().to_string(),
|
||||
n.keyboard_shortcut().map(str::to_string),
|
||||
figcraft_ui_egui::a11y::focused_name(&ctx),
|
||||
));
|
||||
}
|
||||
}
|
||||
found.expect("rendered")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recent_file_names_preserve_spaces() {
|
||||
for view in ["grid", "list"] {
|
||||
for (path, prefix, full) in [("Q3 report.figcraft", "Q3", "Q3 report"), ("Notes A.figcraft", "Notes", "Notes A")] {
|
||||
// The single-space control "Q3 report" also starts with "Q3"; it is not the row under test.
|
||||
let (label, shortcut, focused) = row(view, path, prefix, "Q3 report");
|
||||
assert!(label.starts_with(full), "{view}: label {label:?}");
|
||||
assert_eq!(shortcut, None, "{view}: {path}");
|
||||
assert!(focused.starts_with(full), "{view}: focused {focused:?}");
|
||||
}
|
||||
let (label, shortcut, _) = row(view, "Q3 report.figcraft", "Q3 report", "");
|
||||
assert!(label.starts_with("Q3 report"), "{view}: control {label:?}");
|
||||
assert_eq!(shortcut, None);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user