main
tag: launch-2026-06-01
tag: magicmirror-v0.1.1
tag: magicmirror-v0.3.0
tag: mnw-cli-v0.1.2
tag: mnw-cli-v0.1.3
tag: mnw-cli-v0.1.4
tag: pom-v0.4.1
tag: pom-v0.4.2
tag: pom-v0.4.3
tag: pom-v0.4.4
tag: pom-v0.4.5
tag: wam-v0.3.0
tag: wam-v0.3.1
Files
Commits
Tags
Notes
Issues
Describe the project Content panel, closing N12's round-trip filter
B4's centrepiece and the close condition makeover-layout N12 had been
waiting on: the ticks are a payload the renderer assembles, and the three
filter controls are a server round trip rather than a client-side pass
over rendered rows.
src/quasi/project_content.rs holds the whole panel. A View is the address
- search, status, type, sort, direction, open bundles, select-all - so
every narrowing tab-project-content.js kept in a closure and re-applied
after each swap is a query param that survives one. The bulk bar is the
shipped five verbs through Act::over, with Set Price and Add Tag using
Act::asking, which is the member that was grown off this exact bar.
Inline rename becomes the same shape. Nothing was added to quasi or
makeover-layout.
Not mounted by quasi: the address carries the project slug and a nest
strips its prefix, so the existing axum route serves both renderings and
reads QUASI_SCREENS per request. The described writes are registered only
under the switch and each answers the panel it happened in.
A narrowed panel answers without an ETag: the tag is the project's cache
generation and does not move when a filter does.
build.rs now writes quasi-selection.js and quasi-clock.js from the
renderer's own constants. The shell has named both addresses since S1 and
neither file existed, so every page linked scripts that 404ed and the
first described bulk bar would have shipped without its count.
23 unit tests, 16 pressed-control integration tests. Parity does not
apply to this one and the module says why.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
14 files changed,
+2224 insertions,
-23 deletions
10
10
11
11
# Generated stylesheets (makeover-build emits these from makeover-geometry and
12
12
# makeover-webview; the crates are the source, a checked-in copy would drift)
13
+
server/static/quasi-selection.js
14
+
server/static/quasi-clock.js
13
15
server/static/geometry.css
14
16
server/static/layout.css
15
17
server/static/embed-geometry.css
5396
5396
5397
5397
[[package]]
5398
5398
name = "makeover-layout"
5399
-
version = "0.31.0"
5399
+
version = "0.32.0"
5400
5400
5401
5401
[[package]]
5402
5402
name = "makeover-touch"
5403
-
version = "0.22.0"
5403
+
version = "0.22.1"
5404
5404
dependencies = [
5405
5405
"makeover-geometry",
5406
5406
"makeover-layout",
5408
5408
5409
5409
[[package]]
5410
5410
name = "makeover-webview"
5411
-
version = "0.53.0"
5411
+
version = "0.54.0"
5412
5412
dependencies = [
5413
5413
"makeover-geometry",
5414
5414
"makeover-layout",
6609
6609
6610
6610
[[package]]
6611
6611
name = "quasi-axum"
6612
-
version = "0.45.0"
6612
+
version = "0.46.0"
6613
6613
dependencies = [
6614
6614
"axum",
6615
6615
"http 1.4.2",
6620
6620
6621
6621
[[package]]
6622
6622
name = "quasi-basics"
6623
-
version = "0.45.0"
6623
+
version = "0.46.0"
6624
6624
dependencies = [
6625
6625
"makeover-layout",
6626
6626
"quasi-router",
6628
6628
6629
6629
[[package]]
6630
6630
name = "quasi-http"
6631
-
version = "0.45.0"
6631
+
version = "0.46.0"
6632
6632
dependencies = [
6633
6633
"form_urlencoded",
6634
6634
"http 1.4.2",
6637
6637
6638
6638
[[package]]
6639
6639
name = "quasi-router"
6640
-
version = "0.45.0"
6640
+
version = "0.46.0"
6641
6641
dependencies = [
6642
6642
"makeover-layout",
6643
6643
]
6660
6660
6661
6661
[[package]]
6662
6662
name = "quasi-webview"
6663
-
version = "0.45.0"
6663
+
version = "0.46.0"
6664
6664
dependencies = [
6665
6665
"docengine",
6666
6666
"makeover-layout",
10734
10734
10735
10735
[[patch.unused]]
10736
10736
name = "synckit-client"
10737
-
version = "0.8.0"
10737
+
version = "0.8.1"
10738
10738
10739
10739
[[patch.unused]]
10740
10740
name = "synckit-config"
10742
10742
10743
10743
[[patch.unused]]
10744
10744
name = "quasi-immediate"
10745
-
version = "0.45.0"
10745
+
version = "0.46.0"
10746
10746
10747
10747
[[patch.unused]]
10748
10748
name = "quasi-notifs"
10749
-
version = "0.45.0"
10749
+
version = "0.46.0"
10750
10750
10751
10751
[[patch.unused]]
10752
10752
name = "quasi-store"
10754
10754
10755
10755
[[patch.unused]]
10756
10756
name = "quasi-tauri"
10757
-
version = "0.45.0"
10758
-
10759
-
[[patch.unused]]
10760
-
name = "makeover-immediate"
10761
-
version = "0.30.0"
10762
-
10763
-
[[patch.unused]]
10764
-
name = "makeover-tui"
10765
-
version = "0.30.0"
10757
+
version = "0.46.0"
10766
10758
10767
10759
[[patch.unused]]
10768
10760
name = "kberg"
10775
10767
[[patch.unused]]
10776
10768
name = "painhours"
10777
10769
version = "0.1.0"
10770
+
10771
+
[[patch.unused]]
10772
+
name = "makeover-immediate"
10773
+
version = "0.31.0"
10774
+
10775
+
[[patch.unused]]
10776
+
name = "makeover-tui"
10777
+
version = "0.31.0"
266
266
# two Quasi Monos. Under the tree's `[patch]` block the rev is ignored and the
267
267
# working copy is what builds.
268
268
quasi-type = { git = "https://makenot.work/git/max/quasi-type.git", version = "0.1", rev = "e40330602e68fbdd2a9d2917bdec33a7ce573a1f" }
269
+
# Writes the two scripts the renderer ships into `static/`, from the constants
270
+
# the crate carries. They are the renderer's behaviour rather than the app's --
271
+
# a bulk bar's count, a readout that keeps ticking -- and the shell has always
272
+
# named their addresses, so without this the head links two files that 404.
273
+
# Written from the crate rather than copied into the repo for the reason the
274
+
# constants exist: a stale copy in a static directory is a silently dead bulk
275
+
# bar, and the version has to be the one the emitter agrees with.
276
+
quasi-webview = { git = "https://makenot.work/git/max/quasi.git", version = "0.46" }
269
277
270
278
[dev-dependencies]
271
279
tower = { version = "0.5.3", features = ["util"] }
21
21
// No explicit touch selector: density hangs off (hover: none),
22
22
// (pointer: coarse) alone, because the server has no mode class to key it
23
23
// on. GO passes `.ui-mode-mobile` because it has one.
24
+
// The two scripts quasi-webview ships, written where the shell already says
25
+
// they are served from. Both are behaviour a description cannot state and a
26
+
// renderer therefore owns: how many rows are ticked and that a control over
27
+
// none of them should not be pressable (`quasi-selection.js`), and a readout
28
+
// reckoned against the current time that keeps moving (`quasi-clock.js`).
29
+
// `Shell::under("/static")` has named both addresses since S1 and neither
30
+
// file existed, so every page linked two scripts that 404ed and the first
31
+
// described bulk bar would have shipped without its count.
32
+
//
33
+
// Written from the crate's own constants for the reason they are constants:
34
+
// the script reads hooks the emitter writes, so a copy checked in here goes
35
+
// stale against the next bump in silence. Gitignored, like the stylesheets.
36
+
fs::write("static/quasi-selection.js", quasi_webview::SELECTION_JS)
37
+
.expect("write static/quasi-selection.js");
38
+
fs::write("static/quasi-clock.js", quasi_webview::CLOCK_JS)
39
+
.expect("write static/quasi-clock.js");
40
+
24
41
makeover_build::geometry_css("static/geometry.css", None);
25
42
makeover_build::layout_css("static/layout.css", &makeover_build::Emit::default());
26
43
37
37
pub mod item_tabs;
38
38
pub mod library_contacts;
39
39
pub mod library_tabs;
40
+
pub mod project_content;
40
41
pub mod project_tabs;
41
42
pub mod rich_field;
42
43
pub mod settings_tabs;
90
90
mod payment_crash_recovery;
91
91
mod postmark;
92
92
mod preferences;
93
+
mod project_content_panel;
93
94
mod project_management;
94
95
mod project_sections;
95
96
mod promo_codes_checkout;
30
30
mod guest_checkout;
31
31
mod imports;
32
32
pub(crate) mod internal;
33
-
mod items;
33
+
pub(crate) mod items;
34
34
pub(crate) mod license_keys;
35
35
mod links;
36
36
mod passkeys;
14
14
15
15
use super::super::verify_project_ownership;
16
16
17
-
const BULK_ITEM_LIMIT: usize = 100;
17
+
/// How many items one bulk write may name.
18
+
///
19
+
/// `pub(crate)` since 2026-08-21: the described Content panel's own bulk route
20
+
/// enforces the same ceiling, and two copies of it would be two ceilings.
21
+
pub(crate) const BULK_ITEM_LIMIT: usize = 100;
18
22
19
23
/// Form input for bulk item operations.
20
24
///
9
9
mod tags;
10
10
mod versions;
11
11
12
+
pub(crate) use bulk::BULK_ITEM_LIMIT;
12
13
pub(super) use bulk::{bulk_delete, bulk_price, bulk_publish, bulk_tag, bulk_unpublish};
13
14
pub(super) use bundles::{bundle_add, bundle_create_child, bundle_remove, bundle_toggle_listed};
14
15
pub(super) use chapters::{create_chapter, delete_chapter, list_chapters, update_chapter};
255
255
// hash the page's JS has to act on. `6b24f2df`.
256
256
let shown = quasi::project_tabs::shown_at(query.tab.as_deref(), git_enabled, synckit_enabled);
257
257
let panel = match quasi::project_tabs::route_at(shown, git_enabled, synckit_enabled) {
258
+
// The described panel goes in without the region wrapper its route
259
+
// answers with: the strip draws that div, and two elements carrying one
260
+
// id is a target nothing can aim at.
261
+
"content" if config.quasi_screens.enabled(quasi::project_content::SCREEN) => {
262
+
let content = project_tabs::build_content(&db, &session_user, &db_project).await?;
263
+
Ok(quasi::project_content::fill(
264
+
db_project.slug.as_ref(),
265
+
&content.items,
266
+
&content.deleted_items,
267
+
&content.posts,
268
+
&quasi::project_content::View::default(),
269
+
))
270
+
}
258
271
"content" => project_tabs::build_content(&db, &session_user, &db_project)
259
272
.await?
260
273
.render(),