3 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| a2b05c56c9 |
feat(makepad-table): opt-in capabilities feature, and raise the matrix_client defect
The two caveats from the dependency investigation. ## The capabilities feature Camera and location attachments are now available behind `features = ["capabilities"]`, which pulls `nigig-uikit` and supplies `UikitAttachmentProvider`. Measured: 89 crates by default, 275 with the feature on. That cost is real and it is inherent, not packaging waste. `camera_widget` imports `send_geocode_request` and `request_map_tile` from `nigig-core`, both of which call `spawn_async` — the shared Tokio runtime — and the first makes an HTTPS call to Nominatim. A camera that geocodes needs an async runtime and an HTTP client; there is no lighter honest version. It is affordable because it is opt-in, and because any app enabling it already depends on `nigig-core`, so that app's own tree grows by nothing. Everything touching `nigig-uikit` is in one module, so the boundary is a file rather than `#[cfg]` scattered through the widget. The provider holds no widgets of its own: the host owns the `CameraWidget` already in its tree and this asks it to open, because a provider that instantiated a second camera would fight the first for the device. A second request while one is outstanding is refused rather than overwriting. The table turns that refusal into `AttachmentUnavailable`, so the user is told the camera is busy instead of watching their first request vanish. File picking is deliberately declined here — `robius-file-picker` already ships unconditionally and costs nothing, and two paths for one job is one too many. Two CI gates, both verified to fail when they should: the opt-in build must keep compiling, and the default build must pull none of `tokio`, `reqwest`, `hyper`, `clap`, `csv`, `image`, `nigig-uikit` or `nigig-core`. The second checks the resolved `cargo tree` rather than the manifest, because feature unification can switch an optional dependency on from a sibling crate. Tests 99 default, 105 with the feature. Both clippy-clean. ## The matrix_client defect Raised in REVIEWS/MATRIX_CLIENT_FEATURE_GATE.md rather than fixed. It is not my crate, nothing depends on the broken combination, and a blind fix could change behaviour someone relies on. `matrix_client` declares `native = ["dep:tokio", "dep:reqwest", "dep:rusqlite"]` but its source gates on `#[cfg(not(target_arch = "wasm32"))]`. Two switches for the same modules, so on a native target with the feature off the modules compile and their dependencies do not — 19 errors, 26 ungated uses across 7 files. There is no CI job for the crate, which is why it rotted unnoticed. The note corrects an overstatement I made while arguing for the trait hook. I said fixing this would unblock wasm. It would not: `matrix_client` already builds clean for wasm32 with `--no-default-features`, and `nigig-core` has 8 wasm errors of its own (`crate::platform::spawn` missing) that have nothing to do with it. The only broken combination is native-target-with-feature-off, which nothing builds. I also said earlier that `matrix_client` was heavy — it is a 7-dependency local crate, not matrix-sdk. That was wrong and it inflated the case for the trait hook; the note records the measured numbers instead. |
|||
| b83e7122c4 |
feat(makepad-table): file picker, search, recents, New/Delete (Invoicer UI Phase 3)
Some checks failed
email.yml / feat(makepad-table): file picker, search, recents, New/Delete (Invoicer UI Phase 3) (push) Failing after 0s
repo hygiene / hygiene (push) Has been cancelled
makepad-table / model (push) Has been cancelled
makepad-table / widget (push) Has been cancelled
makepad-table / hygiene (push) Has been cancelled
The last open phase. The sidebar gains a search box, a filtered document list and a recents list; the toolbar gains New Invoice/Quote/Receipt, Open, Save As and Delete. **The file picker is robius, not makepad's.** Makepad has an `open_system_openfile_dialog`, and it is implemented on macOS only — the Linux and Android backends never handle `CxOsOp::SelectFileDialog`, so the op is queued and dropped. It compiles, it runs, the dialog never appears. That is the worst kind of broken, so this uses `robius-file-picker`, the same crate `nigig-build`, `nigig-pay-ui` and `nigig-sms` already depend on at the same pinned revision, which goes through `rfd` on desktop and the platform picker on Android. CI gates against the macOS-only call returning. The picker's callback runs off the UI thread with no `Cx`, so it parks its outcome in a mutex and signals; `drain_file_picker` applies it on the next `Event::Signal`. Same shape as the SMS bulk CSV import. Model additions, in `makepad-doc-model` so they are testable without a window: `DocKind` with `blank()` constructors, `DocumentLibrary::create`, `remove`, and `selection_after_remove`. Decisions worth naming, because each has a wrong answer that looks fine: - **A new document is empty**, not seeded from the samples. A blank invoice arriving with "Acme Studio LLC" on it invites someone to export it without noticing whose name is there. `issue_date` is blank too — there is no clock in that crate and a guessed date is worse than none. - **Generated numbers cannot collide**, including with documents loaded from disk, and they reuse gaps left by deletions. The number becomes the filename: two documents called INV-1 save over each other and one is lost silently. - **Delete removes the row, not the file.** Removing an entry from a list is not consent to delete a document off disk, and there is no undo here. The status line says the file is untouched. - **Save reports "Choose where to save…", not "Saved."** The dialog being open is not the file being written. - **Search filters on every keystroke**, unlike the header fields, which commit on Return. Every prefix of a query is a valid narrower search; there is no such thing as a half-typed one. - **Searching does not move the selection.** Filtering is a view change, and switching the open document because a letter was typed loses the user's place. - **`selection_after_remove` is separate and exhaustively tested.** Deleting before the selection shifts it, deleting the selection keeps the index unless it was last, deleting after it changes nothing, and emptying the library selects nothing. Every wrong answer silently shows a different document; one of them indexes out of range. The document list is a fixed pool of 12 button slots rather than a `PortalList`, because this app opens documents one at a time. The pool is honest about its limit: anything past it renders as "+n more — narrow the search to reach them" rather than being dropped. Tests 79 -> 90. Six of them are the invoicer's first: `App` derives `Script` and cannot be built outside a live `Cx`, so the sidebar's presentation logic was extracted into four pure functions and tested there. Verified by reintroducing six defects across the two crates — silent overflow, a selection marker that shifts the indent, whitespace counting as a search, colliding numbers, a selection that ignores the shift, and a `blank()` that pre-fills. Also fixed, all pre-existing and all now blocking the `-D warnings` gate that has been running on these crates since the workflow was added: `std::io::Error::new(ErrorKind::Other, _)` in two crates, a manual `RangeInclusive::contains`, a manual `is_multiple_of`, a single-arm `match`, and a duplicated `#[test]` attribute that was annotating one function twice — which is why the count reads 36 rather than 37 here; no test was lost. The sample data keeps its `12_000_00` money literals, where the last group is the minor units and the number reads as "12,000.00" at a glance. `inconsistent_digit_grouping` is allowed at the crate root with that reasoning, rather than regrouping every amount into thousands and making each one need arithmetic to check against its comment. |
|||
| ab17c72c55 |
feat(makepad-table): drag-reorder columns, and the first tests this crate has
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
email.yml / feat(makepad-table): drag-reorder columns, and the first tests this crate has (push) Failing after 0s
makepad-table / model (push) Has been cancelled
makepad-table / widget (push) Has been cancelled
makepad-table / hygiene (push) Has been cancelled
Phase 4 of the README's table, plus the test infrastructure Phases 1-3 never
had. The crate had zero tests before this; it now has 21.
Drag-reorder:
- A press on a column header no longer commits to an action. It arms a drag
and resolves on release: travel more than 8px and it reorders, release
without travelling and it opens the column menu as before. Without that
ambiguity resolved, every menu open would jitter into a one-pixel drag.
The threshold matches `TouchTracker::MOVE_THRESHOLD` so a mouse and a
finger agree on what a drag is.
- While dragging, the carried column is tinted full-height and a 2px bar
marks the boundary it would land on. The bar is suppressed when the drop
is a no-op, so no bar means nothing will happen rather than a bar sitting
misleadingly at the source edge.
- `TableAction::ColumnMoved { from, to }` fires only when the index actually
changed, so a host persisting column order is not asked to write on every
wobble. An open cell editor is cancelled, because it addresses a cell by
index and the indices just moved underneath it.
`draw_drag: DrawVector` — declared, never used anywhere — is replaced by two
`DrawColor` layers. `DrawVector` is a full tessellator with path, vertex,
index and paint state; a translucent rectangle and a vertical bar do not
need any of it.
Testability, which needed a structural change rather than a test file:
`Table` derives `Script` and `Widget`, so it has no `Default` and cannot be
constructed without a live `Cx`. Nothing about it was unit-testable. The
logic worth testing does not need a widget, so it moved off it —
`ColumnGeometry` owns boundary and drop-position arithmetic, and a free
`reorder_columns` owns the move. `Table` forwards to both, and
`compute_layout` now goes through `ColumnGeometry` too, so there is one
implementation rather than two that can drift.
The 21 tests cover column geometry at even and uneven widths and at a
non-zero origin, drop-position resolution including the exact-midpoint case
and clamping outside the table, the index shift in both directions, no-op
drops, out-of-range refusal, cells travelling with their header, ragged
rows, a permutation property over repeated drags, and the Phase 3 menu's
geometry and hit-testing.
Verified by reintroducing three defects separately: removing the shift for
the removed source column fails 7 tests, dropping the no-op guard fails 1,
and moving headers without their cells fails 3.
Phase 3 was marked "scaffolds only" in the README and was in fact
substantially complete — menu state, open, hit-test, apply, and drawing all
present, with 15 row and column actions wired. Corrected to done, with its
geometry now under test.
Also adds `.forgejo/workflows/makepad-table.yml`, the first CI this tree has
had. Every step passes `--manifest-path` explicitly: the crate is excluded
from the root workspace, so `-p` from the repo root cannot reach it and
`--workspace` skips it — omitting the flag does not fail loudly, it silently
tests nothing. The workflow gates tests, clippy at `-D warnings` and fmt,
and asserts three invariants that would otherwise regress quietly: that the
exclusion still holds from both sides, that no manifest tracks a git branch
instead of pinning a revision, and that monetary fields stay integer.
Each gate was checked by breaking what it protects. The exclusion check
caught a defect in itself while being tested: a bare grep for the path also
matched the explanatory comment above the exclude list, so deleting the
entry and keeping the comment passed. It now anchors on the quoted entry.
Two pre-existing clippy warnings fixed so the new `-D warnings` gate starts
from zero.
|