Commit Graph
1160 Commits
Author SHA1 Message Date
a1a842af9a chore: resolve SonarCloud maintainability issues (#1241)
* chore: resolve SonarCloud maintainability issues

- Define SHA256_FMT constant in packaging script to remove duplicated string literal (shelldre:S1192)
- Remove redundant 'static lifetime annotations from const items (rust:S8863)
- Replace closures with method and function pointers (rust:S1612)
- Extract helper functions in synthetic document generation, bezier polyline flattening, and component restoration to reduce cognitive complexity (rust:S3776)

* fix(packaging): use verify_sha256 helper function to avoid shellcheck SC2059

* fix(engine): remove duplicate closing brace in large_document

* fix(engine): take &mut Document in restore_id_map; keep 'static on associated consts

restore_id_map allocates ids, so it needs a mutable document. Elided
lifetimes in associated consts trip elided_lifetimes_in_associated_constant,
so those annotations are restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assign positional parameters to locals in sha256 verification

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-23 23:28:13 -04:00
aiongg c668e21759 PDF: write with craft-libs' krilla, which bounds decoded PNGs (#1240)
* PDF: write with craft-libs' krilla, which bounds decoded PNGs

* PDF: pin craft-libs' krilla at 9f75d3dc
2026-10-23 22:46:21 -04:00
BFlat 8167f13a6a M12: Boards: a collaborative whiteboard file kind (#1229)
Board files (File > New board) with sticky notes, shapes with text, connectors that follow what they join (straight or elbow, arrowheads, labels), marker, highlighter and eraser, and stamps; a board toolbar and a contextual bar; the Design panel hidden on boards, Prototype and Dev Mode refused there. Boards are ordinary FigCraft files built from ordinary layers, so saving, undo, export, MCP and live sessions work unchanged. File tabs, recent files and Open files show a pen nib for design files and a note for boards (original icons drawn in code).
2026-10-24 04:18:55 +07:00
BFlat 17ed21d128 M6: Dev Mode tail: imports in layer trees, compare with versions, an inspect-only canvas (#538)
Import lines for connected components inside generated layer trees; Compare changes against any saved version; a Dev Mode behaviour suite with an inspect-only canvas (menus, shortcuts, paste and Revert to saved refuse design edits; a drag under way is dropped on entering), Changed in the ready list, statuses only on top-level frames and sections; read-only plugins' panels from the Inspect tab.
2026-10-24 02:56:55 +07:00
aiongg 70f702ca17 i18n: a missing translation fails no check; cargo xtask i18n-report lists them (#1228) 2026-10-23 15:43:21 -04:00
aiongg 6ba0223636 Tests: the paragraph indent test loads system fonts and skips only without glyphs (#1227) 2026-10-23 13:50:42 -04:00
aiongg fc7a744519 CI: one test binary per crate, nextest, line tables only (#1208)
* Dev profile: line tables for workspace crates, no debug info for dependencies

* Tests: one integration-test binary per crate with several test files

* xtask ci: nextest, doctests, tests without examples, --keep-going; add xtask test
2026-10-23 13:01:12 -04:00
Dylan M. Taylor 32735549c4 test: explain the discarded reads in the fake servers (SonarCloud)
read() returns Result<Message>, not a lock guard; these test loops
deliberately ignore what the client sent first.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-23 09:44:02 -04:00
Dylan M. Taylor e3169e5a61 collab/ui-egui: keep old UTC output past chrono's year range
`utc_date` (collab) and `date` (ui-egui) took `u64` seconds, which the old
hand-rolled civil-from-days code converted for the whole `u64` range. The
chrono rewrite used `from_timestamp(..).unwrap_or_default()`, so any instant
past chrono's own year limit (262143) silently became the epoch — changing
existing output. `u64::MAX` seconds, for example, used to read
`584554051223-11-09 07:00 UTC` / `Nov 9, 584554051223`, not 1970.

Fix: add a `utc_parts(days, sod, nanos)` helper per crate that moves the
instant into chrono's range by whole 400-year Gregorian cycles (146_097 days),
lets chrono do the month/day/time, and restores the real year afterwards.
chrono stays the only calendar logic; the cycle count just shifts the year, and
every `u64` day count fits in `i64` so the conversion is always exact (no epoch
fallback). Split seconds with `u64` arithmetic first to avoid the `i64` seconds
overflow near `u64::MAX`, matching the old code.

Tests now pin the old output instead of the epoch:
- collab utc_date(u64::MAX) == "584554051223-11-09 07:00 UTC"
  (and utc_date(253_402_300_800) == "10000-01-01 00:00 UTC", already pinned)
- ui-egui date(253_402_300_800) == "Jan 1, 10000"
  date(u64::MAX) == "Nov 9, 584554051223"
2026-10-22 07:12:29 -04:00
Dylan M. Taylor 630e0dd403 Keep 5-digit years unprefixed in utc_date
chrono's %Y writes a '+' before years past 9999, whereas the old hand-rolled
{y:04} did not. utc_date now writes the year with {:04} to keep the exact old
output. from_timestamp already reads a clock past chrono's range as the epoch
rather than panicking. Tests cover the 5-digit-year and out-of-range cases.
2026-10-22 07:12:29 -04:00
Dylan M. Taylor 0e3876e6d6 Use chrono for UTC/calendar conversion instead of hand-rolled copies
Replaces the two hand-rolled Howard Hinnant days-from-civil copies with chrono
as a workspace dependency:
- crates/collab/src/message.rs: utc_date (YYYY-MM-DD HH:MM UTC)
- crates/ui-egui/src/home_recents.rs: date (Mon D, YYYY, UTC; keeps the
  translated month names and trf formatting)
Output is unchanged. Neither function had a test, so each gains one pinning the
exact strings the old code produced (leap days included). chrono uses only std,
so wasm stays safe. AGENTS.md/CLAUDE.md now say time goes through chrono.

Follow-up to storytold/cadcraft#1785
2026-10-22 07:12:29 -04:00
BFlat 74c4a84da3 Merge pull request #907 from RiceDee/fix/idle-tests-font-scan
test(ui-egui): idle harness scans system fonts before its first frame
2026-10-21 16:32:52 +07:00
BFlat 123e46550f Merge pull request #909 from RiceDee/fix/component-set-name
#903 follow-up: name new component sets from the variant path, not the first property
2026-10-21 16:31:04 +07:00
BFlat 44e64d8d47 Merge pull request #933 from SiadeLucas/feat/pages-scroll-area
ui: keep the current page scrolled into view in the pages list (#930)
2026-10-21 16:21:38 +07:00
BFlat bb532a5790 Merge pull request #908 from RiceDee/feat/903-variants-discoverability
#903: Combine as variants in the context menu and Design panel; Add variant on a lone component
2026-10-21 16:01:25 +07:00
BFlat f6f44dcc53 Merge pull request #928 from AganzeFelicite/fix/web-drop-opens-documents-916
M7: a document dropped on the canvas opens as a new file (#916)
2026-10-21 15:50:24 +07:00
BFlat 96a82edecf Merge pull request #939 from YarilaFox/fix/comment-draft-on-tool-switch
M7: dismiss comment draft when switching tools
2026-10-21 15:48:42 +07:00
BFlat f143260c3a Merge pull request #935 from YarilaFox/fix/saved-document-title
M7: show the chosen filename for saved documents
2026-10-21 15:47:09 +07:00
BFlat bb93e5e433 Merge pull request #929 from Silvertree2010/fix/h881-local-from-link-accepts-a-sign-i
Reject non-hex characters in Local::from_link token
2026-10-21 15:44:45 +07:00
BFlat da96d54157 Merge pull request #961 from Silvertree2010/fix/h1145-reversesubpaths-reverse-subpaths
Keep open subpaths open in ReverseSubpaths::reverse_subpaths
2026-10-21 15:35:17 +07:00
BFlat a1758c163f Merge pull request #958 from Silvertree2010/fix/h1112-live-text-svg-export-capitalises
Fix Title Case restarting mid-word across styled runs in SVG export
2026-10-21 15:34:55 +07:00
BFlat b1d00f0802 Merge pull request #943 from Silvertree2010/fix/h932-trim-num-prints-any-whole-number
Fix trim_num saturating whole numbers beyond i64 range
2026-10-21 15:34:34 +07:00
BFlat efb95b29bf Merge pull request #938 from Silvertree2010/fix/h911-same-server-ignores-the-scheme-s
Strip default port in same_server when the address has a path
2026-10-21 15:34:08 +07:00
NetterSilverandClaude Haiku 5.5 2e12bdfd91 Keep open subpaths open in ReverseSubpaths::reverse_subpaths
Found while testing crates/geom/src/lib.rs:287

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 02:46:23 +02:00
Siade Lucas f53f37dfe0 ui: scope page tracker by document UID and update on render
Include document UID in pages_seen_page to correctly handle page selection and scroll tracking when switching between documents. Record page as seen only after the active row renders so that pages filtered out by search scroll into view when the filter is cleared.
2026-10-20 21:28:09 -03:00
NetterSilverandClaude Haiku 5.5 59f3b3b733 Fix Title Case restarting mid-word across styled runs in SVG export
Found while testing crates/svg/src/lib.rs:589 (also :604 and :611)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 00:31:03 +02:00
NetterSilverandClaude Haiku 5.5 77f4271061 Fix trim_num saturating whole numbers beyond i64 range
Found while testing crates/doc/src/text.rs:64

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 17:03:45 +00:00
YarilaFox 8f3afbf6a1 M7: clear comment drafts for control-channel tool changes 2026-10-20 21:04:04 +05:00
Siade Lucas 1c79c1646f ui: scroll active page into view when selection changes 2026-10-20 12:53:21 -03:00
YarilaFox bf3fc3cc6e M7: dismiss comment draft when switching tools 2026-10-20 20:47:16 +05:00
NetterSilverandClaude Haiku 5.5 8b198ea364 Strip default port in same_server when the address has a path
Found while testing crates/engine/src/online.rs:118

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 15:41:47 +00:00
NetterSilverandClaude Haiku 5.5 7c68ebf183 Reject non-hex characters in Local::from_link token
Found while testing crates/collab/src/code.rs:~150 (Local::from_link, u64::from_str_radix on the token)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 14:27:09 +00:00
AganzeFelicite fc37c808aa M7: a document dropped on the canvas opens as a new file (#916)
A .figcraft, .fig or file JSON dropped on the canvas ran file.import,
which added its pages to the file in front. It now opens as a file of
its own, as on the home screen, in the browser too. Images and SVG
still import at the drop point; File > Import still adds pages.

- pending_open::open_dropped queues a dropped file as file.open; the
  home screen and the canvas share it.
- Dragging only documents over the canvas says "Drop to open" (not in
  the browser, which names no file until the drop).
- The tab-switch import test drops an SVG: it pinned where an import
  lands, using a .figcraft only as a file to import.
2026-10-20 15:27:27 +02:00
YarilaFox 23463f719b M7: keep saved document titles in sync with filenames 2026-10-20 17:56:30 +05:00
NetterSilverandClaude Haiku 5.5 49586b1c47 Reject malformed alpha and extra args in Color::parse_css
Found while testing crates/color/src/lib.rs:165 (also :173)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 09:30:01 +00:00
RiceDee b5a315a748 #903: name a new component set from its variants' path, not their first property
A component set took its name from the first variant's name up to the first '/' or '=',
so variants named "State=Default, Size=Small" made a set called "State". The set now
takes the path before the last '/' ("Button/State=Hover" -> "Button",
"Icons/Arrow/Dir=Up" -> "Icons/Arrow"), keeps a plain name as is ("Button"), and
otherwise gets the next numbered default ("Component 1"), as a new component does.
2026-10-20 16:32:16 +11:00
RiceDee bcd5b6e632 #903: Combine as variants in the context menu and Design panel; Add variant on a lone component 2026-10-20 16:18:13 +11:00
RiceDee bbe1a12eeb test(ui-egui): idle harness scans system fonts before its first frame 2026-10-20 15:29:27 +11:00
bflatastic 9b711e212b Merge main into #901 2026-10-20 06:20:04 +07:00
BFlat b5038726c4 Merge pull request #902 from storytold/fix/issue-892
M3: duplicating a main component makes an instance (#892)
2026-10-20 06:19:17 +07:00
BFlat 9c6920cf7d Merge pull request #896 from johnpetersa19/main
Add missing Brazilian Portuguese UI translations
2026-10-20 06:12:04 +07:00
BFlat 2bcd004071 Merge pull request #897 from devius/ka-header
i18n(ka): say how the Georgian catalog was made (AI-assisted, native-reviewed); still a draft
2026-10-20 06:11:27 +07:00
bflatastic f979878d9e Merge main into fix/issue-892
# Conflicts:
#	ROADMAP.md
2026-10-20 06:09:17 +07:00
sanches eb7ead9455 M9: Russian catalog catch-up: the 56 strings added since the review (machine-drafted) 2026-10-20 01:59:51 +03:00
bflatastic 64efe12e6f Merge main into fix/issue-890
# Conflicts:
#	ROADMAP.md
#	docs/ui-parity.md
2026-10-20 05:58:56 +07:00
bflatastic ab59877559 Merge main into #897 2026-10-20 05:47:17 +07:00
bflatastic 77ffc57432 #896: "Individual padding" uses the catalog's word for padding (Preenchimento is Fill) 2026-10-20 05:47:15 +07:00
bflatastic 4e7256bf6a Merge main into #896 2026-10-20 05:47:14 +07:00
bflatastic 8a46478e81 Merge main into fix/issue-879
# Conflicts:
#	ROADMAP.md
2026-10-20 05:46:30 +07:00
bflatastic b82369201d M3: duplicating a main component makes an instance (#892)
Duplicate and Alt-drag copied a main component as a second main. Within
its file the copy is now an instance of it (components::copy_in_file,
shared by edit.duplicate and the Alt-drag copy), as Copy then Paste
already was. A variant duplicated in its set stays a new variant.
2026-10-20 05:44:46 +07:00