mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-26 03:16:53 -06:00
View > Full screen (`view.fullscreen {on?}`, F11 on Windows and Linux,
Ctrl+Cmd+F on macOS) makes the window fill the screen, taskbar included,
and leaves it again. FigCraft's own menu item, translated in every catalog.
Tests: the key and the command toggle the window, junk parameters are
ignored; the shortcut table pins the new binding (49 pinned).
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: bflatastic <bombayapirat@gmail.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
bflatastic
parent
ce84d1f27f
commit
fb8ace5bf4
@@ -104,6 +104,8 @@ pub static MENU: &[MenuItem] = &[
|
||||
m!("View", "Soft-proof sRGB", "view.proofSrgb"),
|
||||
m!("View", SEP, ""),
|
||||
m!("View/Panels", "Show/Hide UI", "view.toggleUi"),
|
||||
// FigCraft's own: the window fills the screen (F11), for setups that hide the taskbar then.
|
||||
m!("View", "Full screen", "view.fullscreen"),
|
||||
m!("View/Panels", "Reset panel widths", "view.panelWidths"),
|
||||
m!("View/Panels", "Layers", "view.layers"),
|
||||
m!("View/Panels", "Assets", "view.assets"),
|
||||
|
||||
@@ -268,6 +268,10 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
spec!("view.snapObjects", "Snap to objects", "{on?}", false, |s, p| flag(s, p, |v| &mut v.snap_objects)),
|
||||
spec!("view.snapPixel", "Snap to pixel grid", "{on?}", false, |s, p| flag(s, p, |v| &mut v.snap_pixel)),
|
||||
spec!("view.toggleUi", "Show/Hide UI", "{on?}", false, |s, p| flag(s, p, |v| &mut v.ui_hidden)),
|
||||
spec!("view.fullscreen", "Full screen", "{on?} the window fills the screen (the desktop app; a no-op headless)", false, |s, p| {
|
||||
s.request_ui("window.fullscreen", json!({"on": boolean(p, "on")}));
|
||||
ok()
|
||||
}),
|
||||
spec!("view.layers", "Layers panel", "{}", false, |s, _| ui(s, "panel.layers")),
|
||||
spec!("view.assets", "Assets panel", "{}", false, |s, _| ui(s, "panel.assets")),
|
||||
spec!("view.design", "Design panel", "{}", false, |s, _| ui(s, "panel.design")),
|
||||
|
||||
@@ -162,6 +162,7 @@ pub static KEYS: &[Binding] = &[
|
||||
k(Essential, "app.actions", &["Cmd+K", "Cmd+/"]).label("Actions…"),
|
||||
k(Essential, "help.shortcuts", &["Ctrl+Shift+?"]).both(),
|
||||
k(Essential, "view.toggleUi", &["Cmd+\\"]),
|
||||
k(Essential, "view.fullscreen", &["Ctrl+Cmd+F"]).win(&["F11"]),
|
||||
k(Essential, "edit.pickColor", &["I", "Ctrl+C"]).win(&["I"]),
|
||||
k(Essential, "app.preferences", &["Cmd+,"]),
|
||||
k(Essential, "file.new", &["Cmd+N"]),
|
||||
|
||||
@@ -91,6 +91,7 @@ static ROWS: &[Row] = &[
|
||||
doc(Essential, "Save to version history", &["Alt+Cmd+S"], &["Ctrl+Alt+S"], Bound("file.saveVersion"), ""),
|
||||
doc(Essential, "Run the last plugin", &["Alt+Cmd+P"], &["Ctrl+Alt+P"], Moved("plugins.runLast", &["Alt+Cmd+P"], &["Ctrl+Alt+Shift+P"]),
|
||||
"conflict: the documentation also gives Ctrl+Alt+P to pixel preview on Windows; pixel preview keeps it, the plugin takes Ctrl+Alt+Shift+P"),
|
||||
pin(Essential, "view.fullscreen", &["Ctrl+Cmd+F"], &["F11"]),
|
||||
pin(Essential, "app.preferences", &["Cmd+,"], &[]),
|
||||
pin(Essential, "file.new", &["Cmd+N"], &[]).reserved(BROWSER_TAB),
|
||||
pin(Essential, "file.open", &["Cmd+O"], &[]),
|
||||
@@ -397,7 +398,7 @@ fn counts_match_the_docs() {
|
||||
let reserved = documented.iter().filter(|r| !r.reserved.is_empty()).count();
|
||||
let pinned = ROWS.len() - documented.len();
|
||||
// docs/ui-parity.md quotes these.
|
||||
assert_eq!((documented.len(), bound, moved, missing, reserved, pinned), (129, 128, 1, 0, 2, 48));
|
||||
assert_eq!((documented.len(), bound, moved, missing, reserved, pinned), (129, 128, 1, 0, 2, 49));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -2034,6 +2034,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "Vorherige Seite"
|
||||
"view.previousRegion" = "Vorherigen Bereich fokussieren"
|
||||
"view.proofSrgb" = "Softproof sRGB"
|
||||
"view.fullscreen" = "Vollbild"
|
||||
"view.prototype" = "Bereich Prototyp"
|
||||
"view.rulers" = "Lineale"
|
||||
"view.set" = "Ansicht festlegen"
|
||||
|
||||
@@ -2087,6 +2087,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "Página anterior"
|
||||
"view.previousRegion" = "Enfocar la región anterior"
|
||||
"view.proofSrgb" = "Prueba en pantalla sRGB"
|
||||
"view.fullscreen" = "Pantalla completa"
|
||||
"view.prototype" = "Panel de prototipo"
|
||||
"view.rulers" = "Reglas"
|
||||
"view.set" = "Establecer vista"
|
||||
|
||||
@@ -2034,6 +2034,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "Page précédente"
|
||||
"view.previousRegion" = "Activer la région précédente"
|
||||
"view.proofSrgb" = "Épreuve écran sRGB"
|
||||
"view.fullscreen" = "Plein écran"
|
||||
"view.prototype" = "Panneau Prototype"
|
||||
"view.rulers" = "Règles"
|
||||
"view.set" = "Définir l’affichage"
|
||||
|
||||
@@ -2036,6 +2036,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "前のページ"
|
||||
"view.previousRegion" = "前の領域にフォーカス"
|
||||
"view.proofSrgb" = "sRGB でソフトプルーフ"
|
||||
"view.fullscreen" = "全画面表示"
|
||||
"view.prototype" = "プロトタイプパネル"
|
||||
"view.rulers" = "定規"
|
||||
"view.set" = "ビューを設定"
|
||||
|
||||
@@ -2035,6 +2035,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "이전 페이지"
|
||||
"view.previousRegion" = "이전 영역에 포커스"
|
||||
"view.proofSrgb" = "sRGB 교정 미리 보기"
|
||||
"view.fullscreen" = "전체 화면"
|
||||
"view.prototype" = "프로토타입 패널"
|
||||
"view.rulers" = "눈금자"
|
||||
"view.set" = "보기 설정"
|
||||
|
||||
@@ -2033,6 +2033,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "Página anterior"
|
||||
"view.previousRegion" = "Focar a região anterior"
|
||||
"view.proofSrgb" = "Prova em tela sRGB"
|
||||
"view.fullscreen" = "Tela cheia"
|
||||
"view.prototype" = "Painel de protótipo"
|
||||
"view.rulers" = "Réguas"
|
||||
"view.set" = "Definir visualização"
|
||||
|
||||
@@ -2036,6 +2036,7 @@ status = "draft — needs native review"
|
||||
"view.prevPage" = "上一页"
|
||||
"view.previousRegion" = "聚焦上一个区域"
|
||||
"view.proofSrgb" = "sRGB 软打样"
|
||||
"view.fullscreen" = "全屏"
|
||||
"view.prototype" = "原型面板"
|
||||
"view.rulers" = "标尺"
|
||||
"view.set" = "设置视图"
|
||||
|
||||
@@ -735,7 +735,7 @@ impl FigApp {
|
||||
"dialog.unsaved" => self.toast(i18n::tr("This file has unsaved changes")),
|
||||
"dialog.plugins" => self.ui.plugins_window = true,
|
||||
"dialog.cursorChat" => live::open_chat(self),
|
||||
"window.new" | "window.focus" => self.window_requests.push(r),
|
||||
"window.new" | "window.focus" | "window.fullscreen" => self.window_requests.push(r),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,3 +189,25 @@ fn enter_with_a_shape_tool_places_one_in_the_middle_of_the_view() {
|
||||
press(&mut u, Key::Enter, Modifiers::NONE);
|
||||
assert!(u.app.session.ds().unwrap().vector_edit.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_screen_key_and_command_toggle_the_window() {
|
||||
let mut u = Ui::new(Session::new());
|
||||
let fullscreen = |out: &egui::FullOutput| -> Vec<ViewportCommand> {
|
||||
out.viewport_output.get(&ViewportId::ROOT).map(|v| v.commands.clone()).unwrap_or_default()
|
||||
};
|
||||
// F11 (Windows and Linux) or Ctrl+Cmd+F (macOS) asks the window to fill the screen.
|
||||
let out = if crate::shortcuts::platform() == Platform::Mac {
|
||||
press(&mut u, Key::F, Modifiers::MAC_CMD | Modifiers::COMMAND | Modifiers::CTRL)
|
||||
} else {
|
||||
press(&mut u, Key::F11, Modifiers::NONE)
|
||||
};
|
||||
assert!(fullscreen(&out).contains(&ViewportCommand::Fullscreen(true)), "full screen key, {:?}", fullscreen(&out));
|
||||
// `on: false` leaves it, whatever the window reports.
|
||||
u.app.run("view.fullscreen", json!({"on": false}));
|
||||
let out = u.frame_output(vec![]);
|
||||
assert!(fullscreen(&out).contains(&ViewportCommand::Fullscreen(false)), "{:?}", fullscreen(&out));
|
||||
// Junk parameters are ignored, not fatal.
|
||||
u.app.run("view.fullscreen", json!({"on": "yes"}));
|
||||
u.frame(vec![]);
|
||||
}
|
||||
|
||||
@@ -242,6 +242,12 @@ pub fn focus(app: &mut FigApp, ctx: &Context, id: u64) -> Result<Value, String>
|
||||
pub(crate) fn requests(app: &mut FigApp, ctx: &Context) {
|
||||
for r in std::mem::take(&mut app.window_requests) {
|
||||
let n = |k: &str| r.data.get(k).and_then(Value::as_u64);
|
||||
if r.kind == "window.fullscreen" {
|
||||
let full = ctx.input(|i| i.viewport().fullscreen.unwrap_or(false));
|
||||
let on = r.data.get("on").and_then(Value::as_bool).unwrap_or(!full);
|
||||
ctx.send_viewport_cmd(ViewportCommand::Fullscreen(on));
|
||||
continue;
|
||||
}
|
||||
let res = if r.kind == "window.new" {
|
||||
open(app, ctx, n("index").map(|i| i as usize), r.data.get("path").and_then(Value::as_str), None).map(|_| ())
|
||||
} else {
|
||||
|
||||
+2
-1
@@ -124,7 +124,7 @@ in the table. `crates/ui-egui/src/shortcut_keys_tests.rs` drives the keys a look
|
||||
| Bound on other keys (documented conflict) | 1 | Run last plugin: the documentation also gives Ctrl+Alt+P to pixel preview on Windows; the plugin takes Ctrl+Alt+Shift+P there |
|
||||
| Missing | 0 | moving the rotation origin (Alt+R, `transform.rotationOrigin`) and placing an object with Enter after choosing its tool (`tool.place`) were the last two |
|
||||
| Documented keys a platform keeps | 2 | Ctrl+Space (Windows/Linux keyboard box selection) switches some CJK input methods; F6 goes to a browser's address bar in the web build |
|
||||
| Undocumented bindings pinned | 48 | of which Cmd/Ctrl+W, Cmd/Ctrl+N and Ctrl+Tab are taken by browsers (web build) and Ctrl+Alt+T / Ctrl+Alt+L by some Linux desktops |
|
||||
| Undocumented bindings pinned | 49 | of which Cmd/Ctrl+W, Cmd/Ctrl+N and Ctrl+Tab are taken by browsers (web build) and Ctrl+Alt+T / Ctrl+Alt+L by some Linux desktops |
|
||||
|
||||
- **Newly bound:** A for the Frame tool, Shift+' for the pixel grid (Cmd+' kept: the articles
|
||||
disagree), Alt+Cmd+\ / Ctrl+Alt+\ for others' cursors (`view.multiplayerCursors`, new), Ctrl+F6
|
||||
@@ -165,6 +165,7 @@ in the table. `crates/ui-egui/src/shortcut_keys_tests.rs` drives the keys a look
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-13 | minor | Home screen: a Templates tab (eight starter templates as cards with thumbnails, search and a kind filter; click or Enter opens a new document) replaces the Community placeholder, the Drafts placeholder is removed, Recents offers four templates while there are no recent files and shows a Getting started card (closable; Help ▸ Getting started brings it back), File ▸ New from template…, and a first run opens on the home screen |
|
||||
| 2026-10-13 | minor | Full screen (#227): View ▸ Full screen (`view.fullscreen {on?}`, F11 on Windows and Linux, Ctrl+Cmd+F on macOS) makes the window fill the screen, taskbar and title bar included, and leaves it again; FigCraft's own item (not in the incumbent's menu). Percentages and hours unchanged |
|
||||
| 2026-10-12 | minor | Everyday editing partials: number fields (scrub a step a point, ×10 with Shift, ×0.1 with Alt, on past the screen edge where the platform reports it; arrow keys by the nudge preferences, opacity and rotation by 1 and 10; brackets and units in arithmetic; `50%` relative outside percentage fields; Tab commits and moves on; an untouched field commits nothing; relative edits and arrow keys on Mixed go to each layer in one undo step) done; outline mode's Include hidden layers and Include object bounds, drawn and clickable, done; Hide when publishing from the Assets panel done (the name's leading `.`); cursors per tool and modifier done (a table in the engine, drawn rotate, pen, eyedropper and comment cursors, not-allowed on refused edits; guides and handles keep their cursors); resizable panels done (limits, double-click reset, kept per window and in the preferences, the canvas keeps its room in a small window); a file or page made in the dark theme has a #1E1E1E page (the light theme and sessions without an interface: #F5F5F5) and text drawn on a dark page is white; Enter on a text selects all of it (test added). Menu items: View ▸ Outlines ▸ Include hidden layers / Include object bounds, View ▸ Panels ▸ Reset panel widths, Libraries ▸ Hide when publishing |
|
||||
| 2026-10-12 | minor | Drag threshold and double-clicks: the second press of a double-click began a move or resize that was never finished, so double-clicking text inside a group often didn't start editing (from the middle of the text) or dragged and resized it when the hand moved a pixel or two; a move or resize now starts only after 3 px of travel on screen and a double-click drops the press's gesture first |
|
||||
| 2026-10-12 | minor | Rotation origin and placing with Enter: Alt+R shows a rotation origin handle to drag (snapping to the box's corners, edge middles and centre; double-click resets; Escape hides; kept while the selection lasts, not saved), which the corner handles, the rotation field, Rotate 90°/180° and `transform.rotate` turn about (`transform.rotationOrigin`, `transform.setRotationOrigin`); Enter with a shape or frame tool chosen, on the canvas or the toolbar's tool, places a click-sized one in the middle of the view (`tool.place`). Documented shortcuts: 128 bound, 0 missing. The keyboard box selection's toast and screen-reader text name Cmd/Ctrl+arrows too; the shortcuts panel cuts a label that doesn't fit before its keycaps with "…" (measured in the font it's drawn in; long labels ran into the keycaps) and shows it in full on hover |
|
||||
|
||||
Reference in New Issue
Block a user