Make the quasi feature build and run again
cargo check --all-features failed with 73 errors and the tests could not run
at all, so nine described screens and their tests had been unverified for an
unknown stretch. The default build stayed green throughout and reported
nothing, which is how it went unnoticed: the feature is off by default, so
nothing in the ordinary loop ever built it.
Two faults, the first hiding the second.
The lock held makeover-touch 0.8.2, which pins makeover-layout 0.14.0, while
the rest of the graph had moved to 0.15.0. Two Tone types, and
Response::toast would not take the one the app had. No pin was wrong:
makeover-touch 0.8.3 tracks layout 0.15.0, was already published, and already
satisfied makeover-webview 0.26.0's caret range. The lock had just never been
refreshed, so this is cargo update -p makeover-touch and nothing more.
With that compiling, every quasi test panicked at path.rs:70. quasi-router
retired :name captures for {name} on 2026-08-11 (quasi ccc1cd0) and goingson
had not followed, because it could not build to find out. All 46 captures
across ten files are rewritten, doc comments included.
541 tests pass under --all-features, 388 under default features.
The remaining gap is that nothing gates this configuration. Filed as a task:
an off-by-default feature holding nine screens needs --all-features in the
check matrix, or it rots again.
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
11 files changed,
+68 insertions,
-51 deletions
| 2234 |
2234 |
|
"makeover",
|
| 2235 |
2235 |
|
"makeover-build",
|
| 2236 |
2236 |
|
"makeover-geometry",
|
| 2237 |
|
- |
"makeover-layout",
|
| 2238 |
|
- |
"makeover-webview",
|
|
2237 |
+ |
"makeover-layout 0.15.0",
|
|
2238 |
+ |
"makeover-webview 0.26.0",
|
| 2239 |
2239 |
|
"notify",
|
| 2240 |
2240 |
|
"notify-debouncer-mini",
|
| 2241 |
2241 |
|
"open",
|
| 3404 |
3404 |
|
dependencies = [
|
| 3405 |
3405 |
|
"makeover",
|
| 3406 |
3406 |
|
"makeover-geometry",
|
| 3407 |
|
- |
"makeover-webview",
|
|
3407 |
+ |
"makeover-webview 0.25.1",
|
| 3408 |
3408 |
|
]
|
| 3409 |
3409 |
|
|
| 3410 |
3410 |
|
[[package]]
|
| 3420 |
3420 |
|
checksum = "e08cfaa62476d03061dc86a2befc0c24129399ba37a6f7645fbb72b011abf2f0"
|
| 3421 |
3421 |
|
|
| 3422 |
3422 |
|
[[package]]
|
| 3423 |
|
- |
name = "makeover-touch"
|
| 3424 |
|
- |
version = "0.8.2"
|
|
3423 |
+ |
name = "makeover-layout"
|
|
3424 |
+ |
version = "0.15.0"
|
| 3425 |
3425 |
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 3426 |
|
- |
checksum = "42481d14654fcbe37a3b2fcfca239448e3c6c7cf474e26a9837b02447fbb1e5c"
|
|
3426 |
+ |
checksum = "9f18920c6ac0fe10a8f7b45c2224d0ad39e4863151b3fbe0fe042c938b9b0a9d"
|
|
3427 |
+ |
|
|
3428 |
+ |
[[package]]
|
|
3429 |
+ |
name = "makeover-touch"
|
|
3430 |
+ |
version = "0.8.3"
|
|
3431 |
+ |
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3432 |
+ |
checksum = "eb5ea885f63ad2509b4b028a7cff0e027d4201c40e990346ecae01228edcc962"
|
| 3427 |
3433 |
|
dependencies = [
|
| 3428 |
3434 |
|
"makeover-geometry",
|
| 3429 |
|
- |
"makeover-layout",
|
|
3435 |
+ |
"makeover-layout 0.15.0",
|
| 3430 |
3436 |
|
]
|
| 3431 |
3437 |
|
|
| 3432 |
3438 |
|
[[package]]
|
| 3433 |
3439 |
|
name = "makeover-tui"
|
| 3434 |
|
- |
version = "0.13.0"
|
|
3440 |
+ |
version = "0.14.0"
|
| 3435 |
3441 |
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 3436 |
|
- |
checksum = "5c81462316380492a2b339250324273c5d72f98b28d2718628441b1682e64ff9"
|
|
3442 |
+ |
checksum = "9532a834ce6d9590ebe43c10fa6b33aef2e87fbe1090a3e693e75c8aaf29adb5"
|
| 3437 |
3443 |
|
dependencies = [
|
| 3438 |
3444 |
|
"makeover",
|
| 3439 |
|
- |
"makeover-layout",
|
|
3445 |
+ |
"makeover-layout 0.14.0",
|
| 3440 |
3446 |
|
"ratatui",
|
| 3441 |
3447 |
|
]
|
| 3442 |
3448 |
|
|
| 3447 |
3453 |
|
checksum = "41fb147debeae14c46a48286459712f70cd89d1cce49595fd46a947528c302d5"
|
| 3448 |
3454 |
|
dependencies = [
|
| 3449 |
3455 |
|
"makeover-geometry",
|
| 3450 |
|
- |
"makeover-layout",
|
|
3456 |
+ |
"makeover-layout 0.14.0",
|
|
3457 |
+ |
"makeover-touch",
|
|
3458 |
+ |
]
|
|
3459 |
+ |
|
|
3460 |
+ |
[[package]]
|
|
3461 |
+ |
name = "makeover-webview"
|
|
3462 |
+ |
version = "0.26.0"
|
|
3463 |
+ |
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3464 |
+ |
checksum = "104d377d660eabeace98de31fab5dfb63f6ccbf679a68c2e761cde29f7f79062"
|
|
3465 |
+ |
dependencies = [
|
|
3466 |
+ |
"makeover-geometry",
|
|
3467 |
+ |
"makeover-layout 0.15.0",
|
| 3451 |
3468 |
|
"makeover-touch",
|
| 3452 |
3469 |
|
]
|
| 3453 |
3470 |
|
|
| 4662 |
4679 |
|
name = "quasi-router"
|
| 4663 |
4680 |
|
version = "0.1.0"
|
| 4664 |
4681 |
|
dependencies = [
|
| 4665 |
|
- |
"makeover-layout",
|
|
4682 |
+ |
"makeover-layout 0.15.0",
|
| 4666 |
4683 |
|
]
|
| 4667 |
4684 |
|
|
| 4668 |
4685 |
|
[[package]]
|
| 4680 |
4697 |
|
version = "0.1.0"
|
| 4681 |
4698 |
|
dependencies = [
|
| 4682 |
4699 |
|
"docengine",
|
| 4683 |
|
- |
"makeover-layout",
|
| 4684 |
|
- |
"makeover-webview",
|
|
4700 |
+ |
"makeover-layout 0.15.0",
|
|
4701 |
+ |
"makeover-webview 0.26.0",
|
| 4685 |
4702 |
|
"quasi-http",
|
| 4686 |
4703 |
|
"quasi-router",
|
| 4687 |
4704 |
|
]
|
| 478 |
478 |
|
router
|
| 479 |
479 |
|
.get("/contacts", index)
|
| 480 |
480 |
|
.get("/contacts/list", list)
|
| 481 |
|
- |
.get("/contacts/:id", detail)
|
| 482 |
|
- |
.post("/contacts/:id/email/:sub/delete", remove_email)
|
| 483 |
|
- |
.post("/contacts/:id/phone/:sub/delete", remove_phone)
|
| 484 |
|
- |
.post("/contacts/:id/social/:sub/delete", remove_social)
|
| 485 |
|
- |
.post("/contacts/:id/field/:sub/delete", remove_field)
|
|
481 |
+ |
.get("/contacts/{id}", detail)
|
|
482 |
+ |
.post("/contacts/{id}/email/{sub}/delete", remove_email)
|
|
483 |
+ |
.post("/contacts/{id}/phone/{sub}/delete", remove_phone)
|
|
484 |
+ |
.post("/contacts/{id}/social/{sub}/delete", remove_social)
|
|
485 |
+ |
.post("/contacts/{id}/field/{sub}/delete", remove_field)
|
| 486 |
486 |
|
}
|
| 1157 |
1157 |
|
// not have to know that to be sure `list` never arrives as an id.
|
| 1158 |
1158 |
|
.get("/emails/list", list_only)
|
| 1159 |
1159 |
|
.get("/emails", index)
|
| 1160 |
|
- |
.get("/emails/:id", thread)
|
| 1161 |
|
- |
.post("/emails/:id/read", set_read)
|
| 1162 |
|
- |
.post("/emails/:id/archive", set_archived)
|
| 1163 |
|
- |
.post("/emails/:id/delete", remove)
|
| 1164 |
|
- |
.post("/emails/:id/labels", set_labels)
|
| 1165 |
|
- |
.post("/emails/:id/folder", set_folder)
|
| 1166 |
|
- |
.post("/emails/:id/snooze", set_snooze)
|
| 1167 |
|
- |
.post("/emails/:id/task", to_task)
|
| 1168 |
|
- |
.post("/emails/:id/event", to_event)
|
|
1160 |
+ |
.get("/emails/{id}", thread)
|
|
1161 |
+ |
.post("/emails/{id}/read", set_read)
|
|
1162 |
+ |
.post("/emails/{id}/archive", set_archived)
|
|
1163 |
+ |
.post("/emails/{id}/delete", remove)
|
|
1164 |
+ |
.post("/emails/{id}/labels", set_labels)
|
|
1165 |
+ |
.post("/emails/{id}/folder", set_folder)
|
|
1166 |
+ |
.post("/emails/{id}/snooze", set_snooze)
|
|
1167 |
+ |
.post("/emails/{id}/task", to_task)
|
|
1168 |
+ |
.post("/emails/{id}/event", to_event)
|
| 1169 |
1169 |
|
}
|
| 635 |
635 |
|
router
|
| 636 |
636 |
|
.get("/monthly-review", review)
|
| 637 |
637 |
|
.post("/monthly-review/goals", add_goal)
|
| 638 |
|
- |
.post("/monthly-review/goals/:id/status", set_goal_status)
|
| 639 |
|
- |
.post("/monthly-review/goals/:id/delete", delete_goal)
|
|
638 |
+ |
.post("/monthly-review/goals/{id}/status", set_goal_status)
|
|
639 |
+ |
.post("/monthly-review/goals/{id}/delete", delete_goal)
|
| 640 |
640 |
|
.post("/monthly-review/complete", complete)
|
| 641 |
641 |
|
}
|
| 513 |
513 |
|
router
|
| 514 |
514 |
|
.get("/problems", index)
|
| 515 |
515 |
|
.get("/problems/list", list)
|
| 516 |
|
- |
.post("/problems/:id/promote", promote_one)
|
| 517 |
|
- |
.post("/problems/:id/status", set_status)
|
|
516 |
+ |
.post("/problems/{id}/promote", promote_one)
|
|
517 |
+ |
.post("/problems/{id}/status", set_status)
|
| 518 |
518 |
|
}
|
| 639 |
639 |
|
/// The projects screen's routes.
|
| 640 |
640 |
|
#[must_use]
|
| 641 |
641 |
|
pub fn routes(router: Router<AppState>) -> Router<AppState> {
|
| 642 |
|
- |
// `/projects/new` and `/projects/:id` collide, and the router settles it by
|
|
642 |
+ |
// `/projects/new` and `/projects/{id}` collide, and the router settles it by
|
| 643 |
643 |
|
// specificity rather than by the order they are written in, so `new` is
|
| 644 |
644 |
|
// tried first wherever it sits here.
|
| 645 |
645 |
|
let router = router
|
| 646 |
646 |
|
.get("/projects", index)
|
| 647 |
647 |
|
.get("/projects/list", list)
|
| 648 |
648 |
|
.get("/projects/new", new)
|
| 649 |
|
- |
.get("/projects/:id", detail)
|
|
649 |
+ |
.get("/projects/{id}", detail)
|
| 650 |
650 |
|
.post("/projects", create)
|
| 651 |
|
- |
.post("/projects/:id/delete", remove);
|
|
651 |
+ |
.post("/projects/{id}/delete", remove);
|
| 652 |
652 |
|
dashboard::routes(router)
|
| 653 |
653 |
|
}
|
| 431 |
431 |
|
pub fn routes(router: Router<AppState>) -> Router<AppState> {
|
| 432 |
432 |
|
router
|
| 433 |
433 |
|
.get("/settings", index)
|
| 434 |
|
- |
.get("/settings/:section", section)
|
| 435 |
|
- |
.post("/settings/config/:key", set)
|
|
434 |
+ |
.get("/settings/{section}", section)
|
|
435 |
+ |
.post("/settings/config/{key}", set)
|
| 436 |
436 |
|
}
|
| 642 |
642 |
|
#[must_use]
|
| 643 |
643 |
|
pub fn routes(router: Router<AppState>) -> Router<AppState> {
|
| 644 |
644 |
|
router
|
| 645 |
|
- |
.get("/tasks/:id", overview)
|
| 646 |
|
- |
.post("/tasks/:id/complete", complete)
|
| 647 |
|
- |
.post("/tasks/:id/delete", remove)
|
| 648 |
|
- |
.post("/tasks/:id/subtasks", add_subtask)
|
| 649 |
|
- |
.post("/tasks/:id/subtasks/:sub/toggle", toggle_subtask)
|
| 650 |
|
- |
.post("/tasks/:id/notes", add_note)
|
|
645 |
+ |
.get("/tasks/{id}", overview)
|
|
646 |
+ |
.post("/tasks/{id}/complete", complete)
|
|
647 |
+ |
.post("/tasks/{id}/delete", remove)
|
|
648 |
+ |
.post("/tasks/{id}/subtasks", add_subtask)
|
|
649 |
+ |
.post("/tasks/{id}/subtasks/{sub}/toggle", toggle_subtask)
|
|
650 |
+ |
.post("/tasks/{id}/notes", add_note)
|
| 651 |
651 |
|
}
|
| 715 |
715 |
|
// id. Written in this order anyway, because a reader should not have to
|
| 716 |
716 |
|
// know that to be sure.
|
| 717 |
717 |
|
.post("/weekly-review/focus/clear", clear_focus)
|
| 718 |
|
- |
.post("/weekly-review/focus/:id", set_focus)
|
| 719 |
|
- |
.post("/weekly-review/vacation/:day", toggle_vacation)
|
|
718 |
+ |
.post("/weekly-review/focus/{id}", set_focus)
|
|
719 |
+ |
.post("/weekly-review/vacation/{day}", toggle_vacation)
|
| 720 |
720 |
|
.post("/weekly-review/complete", complete)
|
| 721 |
721 |
|
}
|
| 647 |
647 |
|
#[must_use]
|
| 648 |
648 |
|
pub(super) fn routes(router: Router<AppState>) -> Router<AppState> {
|
| 649 |
649 |
|
router
|
| 650 |
|
- |
.get("/projects/:id/dashboard", dashboard)
|
| 651 |
|
- |
.post("/projects/:id/milestones/:milestone/move", move_milestone)
|
|
650 |
+ |
.get("/projects/{id}/dashboard", dashboard)
|
|
651 |
+ |
.post("/projects/{id}/milestones/{milestone}/move", move_milestone)
|
| 652 |
652 |
|
.post(
|
| 653 |
|
- |
"/projects/:id/milestones/:milestone/delete",
|
|
653 |
+ |
"/projects/{id}/milestones/{milestone}/delete",
|
| 654 |
654 |
|
delete_milestone,
|
| 655 |
655 |
|
)
|
| 656 |
|
- |
.post("/projects/:id/attachments", attach)
|
| 657 |
|
- |
.get("/projects/:id/attachments/:attachment/open", open)
|
|
656 |
+ |
.post("/projects/{id}/attachments", attach)
|
|
657 |
+ |
.get("/projects/{id}/attachments/{attachment}/open", open)
|
| 658 |
658 |
|
}
|
| 147 |
147 |
|
|
| 148 |
148 |
|
#[tokio::test]
|
| 149 |
149 |
|
async fn the_dashboard_route_is_not_swallowed_by_the_detail_route() {
|
| 150 |
|
- |
// `/projects/:id` and `/projects/:id/dashboard` are different lengths so
|
|
150 |
+ |
// `/projects/{id}` and `/projects/{id}/dashboard` are different lengths so
|
| 151 |
151 |
|
// they cannot collide, but the detail route is registered first and this is
|
| 152 |
152 |
|
// the assertion that says the composition order does not matter.
|
| 153 |
153 |
|
let state = state().await;
|