Dev Mode review fixes: slot imports keep the slot's depth base, Shift-click deselects, a comment link pastes, Enter on a drawing tool returns to the design, formal German

This commit is contained in:
bflatastic
2026-10-24 01:53:08 +07:00
parent 16a78cc11e
commit 334b388aa3
6 changed files with 44 additions and 8 deletions
+2 -1
View File
@@ -166,7 +166,8 @@ fn call_imports(doc: &Document, id: NodeId, lang: CodeLang, depth: usize, out: &
&& v.as_bool() == Some(true)
&& let Some((slot, _)) = slots.iter().find(|(_, name)| *name == p.prop)
{
tree(&Ctx::new(doc, *slot), *slot, lang, depth + 1, out);
// The same depth base as the slot's generated content, so its connected children count.
tree(&Ctx { doc, root: *slot, comp: None, base: depth }, *slot, lang, depth + 1, out);
}
}
}
+4 -1
View File
@@ -1228,8 +1228,11 @@ impl Session {
vec![target]
};
self.set_selection(new_sel.clone());
// Dev Mode only selects: nothing moves.
// Dev Mode only selects (Shift-click still deselects): nothing moves.
if !edits {
if deselect.is_some() {
self.set_selection(without_target());
}
return Ok(());
}
// Locked layers selected in the layers panel stay put.
+1 -1
View File
@@ -372,7 +372,7 @@ status = "draft — needs native review"
"Detach variable" = "Variable lösen"
"Details" = "Details"
"Dev Mode" = "Entwicklermodus"
"Dev Mode only inspects: switch to Design (Shift+D) to edit" = "Der Entwicklermodus prüft nur: wechsle zu Design (Shift+D), um zu bearbeiten"
"Dev Mode only inspects: switch to Design (Shift+D) to edit" = "Der Entwicklermodus prüft nur: Wechseln Sie zu Design (Shift+D), um zu bearbeiten"
"Dev resources" = "Entwicklerressourcen"
"Development" = "Entwicklung"
"Device" = "Gerät"
+23
View File
@@ -85,3 +85,26 @@ fn read_only_plugins_run_from_the_inspect_tab_show_their_panel() {
assert!(u.app.session.execute("plugin.event", &json!({"id": "org.test.inspect", "control": "go"})).is_err());
assert_eq!(layers(&u), before);
}
/// A clipboard holding only text.
struct TextClip(String);
impl crate::Services for TextClip {
fn clipboard_get_text(&mut self) -> Option<String> {
Some(self.0.clone())
}
}
#[test]
fn dev_mode_pastes_only_a_comments_link() {
let mut s = Session::new();
let c = s.execute("comment.add", &json!({"x": 10, "y": 10, "text": "Check the spacing"})).unwrap()["id"].as_u64().unwrap();
let layers = |app: &crate::FigApp| app.session.doc().unwrap().node(app.session.page().unwrap()).unwrap().children.len();
let mut app = crate::FigApp::new(s, Box::new(TextClip("Pasted words".into())));
app.ui.right_tab = crate::RightTab::Inspect;
crate::menus::paste(&mut app, None, None);
assert_eq!(layers(&app), 0, "text doesn't paste into the design in Dev Mode");
app.services = Box::new(TextClip(format!("figcraft://comment/{c}")));
crate::menus::paste(&mut app, None, None);
assert_eq!(app.ui.comments.open, Some(c), "the link opens its thread");
}
+12 -4
View File
@@ -35,12 +35,13 @@ pub const UI_COMMANDS: &[&str] = &[
/// `event_text` is the text the platform handed over with the paste event (the browser has no
/// other way to read it). `at`: the page point to paste at (Paste here); `None` pastes in the
/// middle of the view.
/// In Dev Mode only a comment's link pastes (it opens the thread); everything else would edit.
pub fn paste(app: &mut FigApp, event_text: Option<&str>, at: Option<(f64, f64)>) {
if dev_mode_refuses(app, "edit.paste") {
return;
}
// Only HTML that holds readable design data takes this path; other HTML pastes as before.
if let Some(html) = app.services.clipboard_get_html().filter(|h| figcraft_engine::cmd::edit::design_clipboard_buffer(h).is_some()) {
if dev_mode_refuses(app, "edit.paste") {
return;
}
let mut params = json!({"html": html});
if let Some((x, y)) = at {
params["x"] = json!(x);
@@ -61,6 +62,9 @@ pub fn paste(app: &mut FigApp, event_text: Option<&str>, at: Option<(f64, f64)>)
let (cx, cy) = at.or_else(|| app.session.ds().ok().map(|d| (d.view.cx, d.view.cy))).unwrap_or((0.0, 0.0));
if !ours {
if let Some((png, w, h)) = clipboard_png(app) {
if dev_mode_refuses(app, "edit.paste") {
return;
}
use base64::Engine as _;
let b64 = base64::engine::general_purpose::STANDARD.encode(png);
// Centred in the view; Paste here puts its top-left at the point, as it does layers.
@@ -73,6 +77,8 @@ pub fn paste(app: &mut FigApp, event_text: Option<&str>, at: Option<(f64, f64)>)
// A comment's link opens its thread.
if text.trim().starts_with("figcraft://comment/") {
app.run("comment.open", json!({"link": text.trim()}));
} else if dev_mode_refuses(app, "edit.paste") {
// Dev Mode: the note says why nothing was pasted.
} else if figcraft_engine::looks_like_svg(&text) {
use base64::Engine as _;
let b64 = base64::engine::general_purpose::STANDARD.encode(text.as_bytes());
@@ -83,7 +89,9 @@ pub fn paste(app: &mut FigApp, event_text: Option<&str>, at: Option<(f64, f64)>)
return;
}
}
app.run("edit.paste", at.map_or(json!({}), |(x, y)| json!({"x": x, "y": y})));
if !dev_mode_refuses(app, "edit.paste") {
app.run("edit.paste", at.map_or(json!({}), |(x, y)| json!({"x": x, "y": y})));
}
}
/// The system clipboard's image as PNG bytes, with its size.
+2 -1
View File
@@ -115,7 +115,8 @@ fn main_toolbar(app: &mut FigApp, ui: &mut Ui, canvas: Rect, t: &Tokens) {
if resp.clicked() {
// Enter (a keyboard click) on the shape or frame tool already chosen places one; the
// canvas takes the keyboard.
if in_group && shown.draws_shape() && ui.input(|i| i.key_pressed(egui::Key::Enter)) {
// In Dev Mode the tool goes through `choose`, which returns to the design first.
if in_group && shown.draws_shape() && app.ui.right_tab != crate::RightTab::Inspect && ui.input(|i| i.key_pressed(egui::Key::Enter)) {
app.run("tool.place", json!({}));
app.ui.nav.go(Region::Canvas);
} else {