mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-03 00:41:28 -06:00
Merge pull request #1694
Comments: the pane keeps its width and resizes again (fixes #1431)
This commit is contained in:
@@ -130,29 +130,34 @@ fn comment_card(app: &mut SlideApp, ui: &mut Ui, slide: usize, index: usize, c:
|
||||
for r in &c.replies {
|
||||
ui.label(egui::RichText::new(format!("↳ {}: {}", r.author, r.text)).color(t.text_dim));
|
||||
}
|
||||
// The buttons are laid out first, from the right, so the reply field takes exactly the
|
||||
// width they leave. A fixed allowance overflowed the card and widened the pane every
|
||||
// frame until it stuck at its widest (#1431).
|
||||
ui.horizontal(|ui| {
|
||||
let id = ui.scope_id().with(("reply", slide, index));
|
||||
let mut txt: String = ui.data_mut(|d| d.get_temp(id).unwrap_or_default());
|
||||
let r = ui.add(egui::TextEdit::singleline(&mut txt).hint_text("Reply…").desired_width(ui.available_width() - 70.0));
|
||||
if r.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) && !txt.trim().is_empty() {
|
||||
focus_comment(app, slide, index);
|
||||
run(app, "comment.reply", json!({"index": index, "text": txt}));
|
||||
txt.clear();
|
||||
}
|
||||
ui.data_mut(|d| d.insert_temp(id, txt));
|
||||
if ui.small_button(if c.resolved { "Reopen" } else { "Resolve" }).clicked() {
|
||||
focus_comment(app, slide, index);
|
||||
run(app, "comment.resolve", json!({"index": index, "resolved": !c.resolved}));
|
||||
}
|
||||
if ui.small_button("🗑").clicked() {
|
||||
let _ = app.run("slide.go", json!({"index": slide}));
|
||||
let _ = app.run("comment.delete", json!({"index": index}));
|
||||
match app.ui.comment_focus {
|
||||
Some((fs, fi)) if fs == slide && fi == index => app.ui.comment_focus = None,
|
||||
Some((fs, fi)) if fs == slide && fi > index => app.ui.comment_focus = Some((fs, fi - 1)),
|
||||
_ => {}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("🗑").clicked() {
|
||||
let _ = app.run("slide.go", json!({"index": slide}));
|
||||
let _ = app.run("comment.delete", json!({"index": index}));
|
||||
match app.ui.comment_focus {
|
||||
Some((fs, fi)) if fs == slide && fi == index => app.ui.comment_focus = None,
|
||||
Some((fs, fi)) if fs == slide && fi > index => app.ui.comment_focus = Some((fs, fi - 1)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ui.small_button(if c.resolved { "Reopen" } else { "Resolve" }).clicked() {
|
||||
focus_comment(app, slide, index);
|
||||
run(app, "comment.resolve", json!({"index": index, "resolved": !c.resolved}));
|
||||
}
|
||||
let id = ui.scope_id().with(("reply", slide, index));
|
||||
let mut txt: String = ui.data_mut(|d| d.get_temp(id).unwrap_or_default());
|
||||
let r = ui.add(egui::TextEdit::singleline(&mut txt).hint_text("Reply…").desired_width(ui.available_width()));
|
||||
if r.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) && !txt.trim().is_empty() {
|
||||
focus_comment(app, slide, index);
|
||||
run(app, "comment.reply", json!({"index": index, "text": txt}));
|
||||
txt.clear();
|
||||
}
|
||||
ui.data_mut(|d| d.insert_temp(id, txt));
|
||||
});
|
||||
});
|
||||
});
|
||||
if focused {
|
||||
|
||||
@@ -2361,3 +2361,47 @@ fn overdue_visible_logic_does_not_reanchor_a_later_hidden_show() {
|
||||
let _ = ctx.run_logic(&raw_at(12.0, true, false), |ctx| app.tick_hidden_show(ctx, visible_anchor + std::time::Duration::from_secs(3)));
|
||||
assert_eq!(app.show.as_ref().unwrap().state.slide, 1, "time from the full visible frame is preserved through the logic-only pass");
|
||||
}
|
||||
|
||||
/// #1431: a comment card's reply row was wider than the pane, so the Comments pane grew every
|
||||
/// frame until it stuck at its widest and dragging its edge did nothing.
|
||||
#[test]
|
||||
fn comments_pane_keeps_its_width_and_resizes() {
|
||||
let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state(
|
||||
|ui, app: &mut SlideApp| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
},
|
||||
SlideApp::new(Session::with_new(), Services::default()),
|
||||
);
|
||||
h.run_steps(3);
|
||||
h.state_mut().run("comment.add", json!({"text": "Check the figures on this slide"})).unwrap();
|
||||
h.state_mut().run("comment.add", json!({"text": "Resolved one"})).unwrap();
|
||||
h.state_mut().run("comment.resolve", json!({"index": 1, "resolved": true})).unwrap();
|
||||
h.state_mut().run("view.pane", json!({"pane": "comments"})).unwrap();
|
||||
h.run_steps(30);
|
||||
let width = h.state().ui.pane_width;
|
||||
assert!(width < 320.0, "the pane keeps its default width, not {width}");
|
||||
// The cards stay compact: the second one starts near the top, not below a stretched first.
|
||||
let second = h.get_by_label("Resolved one").rect();
|
||||
assert!(second.top() < 450.0, "the second comment sits near the top, at {second:?}");
|
||||
|
||||
// Drag the pane's left edge: right narrows it, left widens it.
|
||||
let drag = |h: &mut egui_kittest::Harness<'_, SlideApp>, dx: f32| {
|
||||
let start = egui::pos2(1200.0 - h.state().ui.pane_width - 1.0, 500.0);
|
||||
let end = start + egui::vec2(dx, 0.0);
|
||||
h.event(egui::Event::PointerMoved(start));
|
||||
h.run_steps(1);
|
||||
h.event(egui::Event::PointerButton { pos: start, button: egui::PointerButton::Primary, pressed: true, modifiers: egui::Modifiers::NONE });
|
||||
for i in 1..=6 {
|
||||
h.event(egui::Event::PointerMoved(start + (end - start) * (i as f32 / 6.0)));
|
||||
h.run_steps(1);
|
||||
}
|
||||
h.event(egui::Event::PointerButton { pos: end, button: egui::PointerButton::Primary, pressed: false, modifiers: egui::Modifiers::NONE });
|
||||
h.run_steps(10);
|
||||
h.state().ui.pane_width
|
||||
};
|
||||
let narrow = drag(&mut h, 50.0);
|
||||
assert!(narrow < width - 40.0, "dragging right narrows the pane: {width} -> {narrow}");
|
||||
let wide = drag(&mut h, -150.0);
|
||||
assert!(wide > narrow + 140.0, "dragging left widens the pane: {narrow} -> {wide}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user