Reveal the comment's page when opening it via ui.set commentOpen

Fixes #435

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:
NetterSilver
2026-10-15 10:43:25 +00:00
co-authored by Claude Haiku 5.5
parent 8482c3e85b
commit 42e6f267b8
2 changed files with 49 additions and 1 deletions
+8 -1
View File
@@ -427,7 +427,14 @@ pub fn handle(app: &mut FigApp, ctx: &Context, method: &str, p: &Value) -> Resul
// Comment thread popover: an id opens it, null closes it.
if let Some(v) = p.get("commentOpen") {
match v.as_u64() {
Some(id) => app.ui.comments.show(id),
Some(id) => {
// Pins are drawn for the current page only: reveal the thread's page first.
let page = app.session.doc().ok().and_then(|d| d.comment(id)).map(|c| c.page);
if let Some(page) = page.filter(|p| app.session.page().is_ok_and(|cur| cur != *p)) {
app.session.execute("page.select", &json!({"id": page.0})).map_err(|e| e.to_string())?;
}
app.ui.comments.show(id);
}
None => app.ui.comments.close(),
}
}
@@ -0,0 +1,41 @@
use egui::{Pos2, RawInput, Rect, vec2};
use figcraft_engine::Session;
use figcraft_ui_egui::{FigApp, NoServices, control};
use serde_json::json;
fn frame(ctx: &egui::Context, app: &mut FigApp, time: f64) {
let mut out = ctx
.run_ui(RawInput { screen_rect: Some(Rect::from_min_size(Pos2::ZERO, vec2(1440.0, 900.0))), time: Some(time), ..Default::default() }, |ui| {
app.ui(ui)
});
out.textures_delta.clear();
}
#[test]
fn comment_open_other_page() {
let mut session = Session::new();
let first = session.page().unwrap();
let second = session.execute("page.add", &json!({})).unwrap()["id"].as_u64().unwrap();
session.execute("page.select", &json!({"id": second})).unwrap();
let comment = session.execute("comment.add", &json!({"x": 50, "y": 50, "text": "Review this"})).unwrap()["id"].as_u64().unwrap();
let ctx = egui::Context::default();
let mut app = FigApp::new(session, Box::new(NoServices));
for i in 1..=3 {
frame(&ctx, &mut app, i as f64 / 60.0);
}
// Same page: stays open.
control::handle(&mut app, &ctx, "ui.set", &json!({"commentOpen": comment})).unwrap();
frame(&ctx, &mut app, 4.0 / 60.0);
assert_eq!(app.inspect()["comments"]["open"], json!(comment));
// null closes it.
control::handle(&mut app, &ctx, "ui.set", &json!({"commentOpen": null})).unwrap();
frame(&ctx, &mut app, 5.0 / 60.0);
assert_eq!(app.inspect()["comments"]["open"], json!(null));
// Another page: the page is revealed and the thread stays open across a frame.
control::handle(&mut app, &ctx, "engine.execute", &json!({"command": "page.select", "params": {"id": first}})).unwrap();
let reply = control::handle(&mut app, &ctx, "ui.set", &json!({"commentOpen": comment})).unwrap();
assert_eq!(reply["comments"]["open"], json!(comment));
frame(&ctx, &mut app, 6.0 / 60.0);
assert_eq!(app.session.page().unwrap().0, second);
assert_eq!(app.inspect()["comments"]["open"], json!(comment), "ui.set should keep the requested popover open across a frame");
}