max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
- Claude-Session
- https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
7 files changed,
+210 insertions,
-197 deletions
| @@ -2875,7 +2875,7 @@ | |||
| 2875 | 2875 | checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" | |
| 2876 | 2876 | dependencies = [ | |
| 2877 | 2877 | "libc", | |
| 2878 | - | "windows-sys 0.52.0", | |
| 2878 | + | "windows-sys 0.59.0", | |
| 2879 | 2879 | ] | |
| 2880 | 2880 | ||
| 2881 | 2881 | [[package]] | |
| @@ -6636,7 +6636,7 @@ | |||
| 6636 | 6636 | ||
| 6637 | 6637 | [[package]] | |
| 6638 | 6638 | name = "quasi-axum" | |
| 6639 | - | version = "0.99.1" | |
| 6639 | + | version = "0.100.0" | |
| 6640 | 6640 | dependencies = [ | |
| 6641 | 6641 | "axum", | |
| 6642 | 6642 | "http 1.4.2", | |
| @@ -6647,7 +6647,7 @@ | |||
| 6647 | 6647 | ||
| 6648 | 6648 | [[package]] | |
| 6649 | 6649 | name = "quasi-basics" | |
| 6650 | - | version = "0.99.1" | |
| 6650 | + | version = "0.100.0" | |
| 6651 | 6651 | dependencies = [ | |
| 6652 | 6652 | "makeover-layout", | |
| 6653 | 6653 | "quasi-router", | |
| @@ -6655,7 +6655,7 @@ | |||
| 6655 | 6655 | ||
| 6656 | 6656 | [[package]] | |
| 6657 | 6657 | name = "quasi-http" | |
| 6658 | - | version = "0.99.1" | |
| 6658 | + | version = "0.100.0" | |
| 6659 | 6659 | dependencies = [ | |
| 6660 | 6660 | "form_urlencoded", | |
| 6661 | 6661 | "http 1.4.2", | |
| @@ -6664,7 +6664,7 @@ | |||
| 6664 | 6664 | ||
| 6665 | 6665 | [[package]] | |
| 6666 | 6666 | name = "quasi-router" | |
| 6667 | - | version = "0.99.1" | |
| 6667 | + | version = "0.100.0" | |
| 6668 | 6668 | dependencies = [ | |
| 6669 | 6669 | "makeover-layout", | |
| 6670 | 6670 | ] | |
| @@ -6687,7 +6687,7 @@ | |||
| 6687 | 6687 | ||
| 6688 | 6688 | [[package]] | |
| 6689 | 6689 | name = "quasi-webview" | |
| 6690 | - | version = "0.99.1" | |
| 6690 | + | version = "0.100.0" | |
| 6691 | 6691 | dependencies = [ | |
| 6692 | 6692 | "docengine", | |
| 6693 | 6693 | "makeover-layout", | |
| @@ -7339,7 +7339,7 @@ | |||
| 7339 | 7339 | "errno", | |
| 7340 | 7340 | "libc", | |
| 7341 | 7341 | "linux-raw-sys 0.12.1", | |
| 7342 | - | "windows-sys 0.52.0", | |
| 7342 | + | "windows-sys 0.59.0", | |
| 7343 | 7343 | ] | |
| 7344 | 7344 | ||
| 7345 | 7345 | [[package]] | |
| @@ -7419,7 +7419,7 @@ | |||
| 7419 | 7419 | "security-framework 3.7.0", | |
| 7420 | 7420 | "security-framework-sys", | |
| 7421 | 7421 | "webpki-root-certs", | |
| 7422 | - | "windows-sys 0.52.0", | |
| 7422 | + | "windows-sys 0.59.0", | |
| 7423 | 7423 | ] | |
| 7424 | 7424 | ||
| 7425 | 7425 | [[package]] | |
| @@ -8545,7 +8545,7 @@ | |||
| 8545 | 8545 | "getrandom 0.4.3", | |
| 8546 | 8546 | "once_cell", | |
| 8547 | 8547 | "rustix 1.1.4", | |
| 8548 | - | "windows-sys 0.52.0", | |
| 8548 | + | "windows-sys 0.59.0", | |
| 8549 | 8549 | ] | |
| 8550 | 8550 | ||
| 8551 | 8551 | [[package]] | |
| @@ -10761,11 +10761,11 @@ | |||
| 10761 | 10761 | ||
| 10762 | 10762 | [[patch.unused]] | |
| 10763 | 10763 | name = "quasi-immediate" | |
| 10764 | - | version = "0.99.1" | |
| 10764 | + | version = "0.100.0" | |
| 10765 | 10765 | ||
| 10766 | 10766 | [[patch.unused]] | |
| 10767 | 10767 | name = "quasi-notifs" | |
| 10768 | - | version = "0.99.1" | |
| 10768 | + | version = "0.100.0" | |
| 10769 | 10769 | ||
| 10770 | 10770 | [[patch.unused]] | |
| 10771 | 10771 | name = "quasi-store" | |
| @@ -10773,7 +10773,15 @@ | |||
| 10773 | 10773 | ||
| 10774 | 10774 | [[patch.unused]] | |
| 10775 | 10775 | name = "quasi-tauri" | |
| 10776 | - | version = "0.99.1" | |
| 10776 | + | version = "0.100.0" | |
| 10777 | + | ||
| 10778 | + | [[patch.unused]] | |
| 10779 | + | name = "synckit-client" | |
| 10780 | + | version = "0.10.0" | |
| 10781 | + | ||
| 10782 | + | [[patch.unused]] | |
| 10783 | + | name = "synckit-config" | |
| 10784 | + | version = "0.2.0" | |
| 10777 | 10785 | ||
| 10778 | 10786 | [[patch.unused]] | |
| 10779 | 10787 | name = "kberg" | |
| @@ -10786,11 +10794,3 @@ | |||
| 10786 | 10794 | [[patch.unused]] | |
| 10787 | 10795 | name = "painhours" | |
| 10788 | 10796 | version = "0.1.0" | |
| 10789 | - | ||
| 10790 | - | [[patch.unused]] | |
| 10791 | - | name = "synckit-client" | |
| 10792 | - | version = "0.10.0" | |
| 10793 | - | ||
| 10794 | - | [[patch.unused]] | |
| 10795 | - | name = "synckit-config" | |
| 10796 | - | version = "0.2.0" |
| @@ -163,7 +163,7 @@ | |||
| 163 | 163 | # through quasi beside its Askama equivalent, so the cost of describing a screen | |
| 164 | 164 | # here is measured rather than argued. Not load-bearing for any shipped route. | |
| 165 | 165 | # See wiki look-wave-2, tier G. | |
| 166 | - | quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.99" } | |
| 166 | + | quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.100" } | |
| 167 | 167 | # The description vocabulary quasi's screen types are built from. Pinned here | |
| 168 | 168 | # rather than reached through quasi-router's re-export because a described | |
| 169 | 169 | # screen names FieldKind and Tone directly; it has to track what quasi-router | |
| @@ -179,13 +179,13 @@ | |||
| 179 | 179 | # For the request head the per-viewer state factory reads. axum re-exports it, | |
| 180 | 180 | # but the factory's signature is quasi-axum's and names `http::request::Parts`. | |
| 181 | 181 | http = "1.3.1" | |
| 182 | - | quasi-axum = { git = "https://makenot.work/git/max/quasi.git", version = "0.99" } | |
| 183 | - | quasi-webview = { git = "https://makenot.work/git/max/quasi.git", version = "0.99" } | |
| 182 | + | quasi-axum = { git = "https://makenot.work/git/max/quasi.git", version = "0.100" } | |
| 183 | + | quasi-webview = { git = "https://makenot.work/git/max/quasi.git", version = "0.100" } | |
| 184 | 184 | # The first-party widget set. The carousel was proved here against three pages | |
| 185 | 185 | # and then moved there; what is left in `quasi/widgets/carousel.rs` is the | |
| 186 | 186 | # Askama glue. Not `makeover-basics`: a widget is an assembly of `Node`s, so it | |
| 187 | 187 | # sits above quasi-router rather than inside the description suite. | |
| 188 | - | quasi-basics = { git = "https://makenot.work/git/max/quasi.git", version = "0.99" } | |
| 188 | + | quasi-basics = { git = "https://makenot.work/git/max/quasi.git", version = "0.100" } | |
| 189 | 189 | ||
| 190 | 190 | # Git source browser | |
| 191 | 191 | gix = { version = "0.86", default-features = false, features = ["blame", "mailmap", "revision", "sha1", "max-performance-safe"] } | |
| @@ -277,7 +277,7 @@ | |||
| 277 | 277 | # Written from the crate rather than copied into the repo for the reason the | |
| 278 | 278 | # constants exist: a stale copy in a static directory is a silently dead bulk | |
| 279 | 279 | # bar, and the version has to be the one the emitter agrees with. | |
| 280 | - | quasi-webview = { git = "https://makenot.work/git/max/quasi.git", version = "0.99" } | |
| 280 | + | quasi-webview = { git = "https://makenot.work/git/max/quasi.git", version = "0.100" } | |
| 281 | 281 | ||
| 282 | 282 | [dev-dependencies] | |
| 283 | 283 | tower = { version = "0.5.3", features = ["util"] } |
| @@ -31,7 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | 32 | use makeover_layout as layout; | |
| 33 | 33 | use quasi_router::screen::{Cell, Cells, Column, Lexeme}; | |
| 34 | - | use quasi_router::{Action, Document, Node, RegionKind, Screen, Slot}; | |
| 34 | + | use quasi_router::{Action, Document, Node, RegionKind, Run, Screen, Slot}; | |
| 35 | 35 | use quasi_webview::Webview; | |
| 36 | 36 | ||
| 37 | 37 | use crate::git::{BlameLine, Breadcrumb, RefInfo}; | |
| @@ -107,31 +107,32 @@ | |||
| 107 | 107 | }; | |
| 108 | 108 | ||
| 109 | 109 | Node::Region( | |
| 110 | - | Slot::new("git-file-header", RegionKind::Group) | |
| 111 | - | .across(layout::Fallback::Wrap) | |
| 112 | - | .beside(Node::text(lines), layout::Priority::Secondary) | |
| 113 | - | .beside( | |
| 114 | - | Node::Link { | |
| 115 | - | text: "Source".to_owned(), | |
| 116 | - | action: Action::get(format!( | |
| 117 | - | "{base}/tree/{}/{}", | |
| 118 | - | view.current_ref, view.file_path | |
| 119 | - | )) | |
| 120 | - | .navigating(), | |
| 121 | - | }, | |
| 122 | - | layout::Priority::Essential, | |
| 123 | - | ) | |
| 124 | - | .beside( | |
| 125 | - | Node::Link { | |
| 126 | - | text: "Raw".to_owned(), | |
| 127 | - | action: Action::get(format!( | |
| 128 | - | "{base}/raw/{}/{}", | |
| 129 | - | view.current_ref, view.file_path | |
| 130 | - | )) | |
| 131 | - | .navigating(), | |
| 132 | - | }, | |
| 133 | - | layout::Priority::Essential, | |
| 134 | - | ), | |
| 110 | + | Slot::new("git-file-header", RegionKind::Group).across( | |
| 111 | + | Run::new(layout::Fallback::Wrap) | |
| 112 | + | .beside(Node::text(lines), layout::Priority::Secondary) | |
| 113 | + | .beside( | |
| 114 | + | Node::Link { | |
| 115 | + | text: "Source".to_owned(), | |
| 116 | + | action: Action::get(format!( | |
| 117 | + | "{base}/tree/{}/{}", | |
| 118 | + | view.current_ref, view.file_path | |
| 119 | + | )) | |
| 120 | + | .navigating(), | |
| 121 | + | }, | |
| 122 | + | layout::Priority::Essential, | |
| 123 | + | ) | |
| 124 | + | .beside( | |
| 125 | + | Node::Link { | |
| 126 | + | text: "Raw".to_owned(), | |
| 127 | + | action: Action::get(format!( | |
| 128 | + | "{base}/raw/{}/{}", | |
| 129 | + | view.current_ref, view.file_path | |
| 130 | + | )) | |
| 131 | + | .navigating(), | |
| 132 | + | }, | |
| 133 | + | layout::Priority::Essential, | |
| 134 | + | ), | |
| 135 | + | ), | |
| 135 | 136 | ) | |
| 136 | 137 | } | |
| 137 | 138 |
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | 21 | use makeover_layout as layout; | |
| 22 | 22 | use quasi_router::screen::{Cell, Cells, Column, Lexeme}; | |
| 23 | - | use quasi_router::{Action, Document, Node, RegionKind, Screen, Slot}; | |
| 23 | + | use quasi_router::{Action, Document, Node, RegionKind, Run, Screen, Slot}; | |
| 24 | 24 | use quasi_webview::Webview; | |
| 25 | 25 | ||
| 26 | 26 | use crate::git::{Breadcrumb, RefInfo, TreeItem, TreeItemKind}; | |
| @@ -213,9 +213,8 @@ | |||
| 213 | 213 | format!("{} - {count} lines", file.file_size) | |
| 214 | 214 | }; | |
| 215 | 215 | ||
| 216 | - | let mut strip = Slot::new("git-file-header", RegionKind::Group) | |
| 217 | - | .across(layout::Fallback::Wrap) | |
| 218 | - | .beside(Node::text(meta), layout::Priority::Secondary); | |
| 216 | + | let mut strip = | |
| 217 | + | Run::new(layout::Fallback::Wrap).beside(Node::text(meta), layout::Priority::Secondary); | |
| 219 | 218 | ||
| 220 | 219 | for (label, route) in [ | |
| 221 | 220 | ( | |
| @@ -240,31 +239,32 @@ | |||
| 240 | 239 | ); | |
| 241 | 240 | } | |
| 242 | 241 | ||
| 243 | - | Node::Region(strip) | |
| 242 | + | Node::Region(Slot::new("git-file-header", RegionKind::Group).across(strip)) | |
| 244 | 243 | } | |
| 245 | 244 | ||
| 246 | 245 | /// A file nothing can usefully draw, and the way to get it anyway. | |
| 247 | 246 | fn binary(frame: &Frame<'_>, file: &File<'_>) -> Node { | |
| 248 | 247 | Node::Region( | |
| 249 | - | Slot::new("git-binary-notice", RegionKind::Group) | |
| 250 | - | .across(layout::Fallback::Wrap) | |
| 251 | - | .beside( | |
| 252 | - | Node::text(format!("Binary file ({}).", file.file_size)), | |
| 253 | - | layout::Priority::Essential, | |
| 254 | - | ) | |
| 255 | - | .beside( | |
| 256 | - | Node::Link { | |
| 257 | - | text: "Download".to_owned(), | |
| 258 | - | action: Action::get(format!( | |
| 259 | - | "{}/raw/{}/{}", | |
| 260 | - | frame.base(), | |
| 261 | - | frame.current_ref, | |
| 262 | - | file.file_path | |
| 263 | - | )) | |
| 264 | - | .navigating(), | |
| 265 | - | }, | |
| 266 | - | layout::Priority::Essential, | |
| 267 | - | ), | |
| 248 | + | Slot::new("git-binary-notice", RegionKind::Group).across( | |
| 249 | + | Run::new(layout::Fallback::Wrap) | |
| 250 | + | .beside( | |
| 251 | + | Node::text(format!("Binary file ({}).", file.file_size)), | |
| 252 | + | layout::Priority::Essential, | |
| 253 | + | ) | |
| 254 | + | .beside( | |
| 255 | + | Node::Link { | |
| 256 | + | text: "Download".to_owned(), | |
| 257 | + | action: Action::get(format!( | |
| 258 | + | "{}/raw/{}/{}", | |
| 259 | + | frame.base(), | |
| 260 | + | frame.current_ref, | |
| 261 | + | file.file_path | |
| 262 | + | )) | |
| 263 | + | .navigating(), | |
| 264 | + | }, | |
| 265 | + | layout::Priority::Essential, | |
| 266 | + | ), | |
| 267 | + | ), | |
| 268 | 268 | ) | |
| 269 | 269 | } | |
| 270 | 270 |
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | 36 | use makeover_layout as layout; | |
| 37 | 37 | use quasi_router::screen::{Cell, Cells, Column, Field, Lexeme, Row}; | |
| 38 | - | use quasi_router::{Act, Action, Document, Node, RegionKind, Screen, Slot}; | |
| 38 | + | use quasi_router::{Act, Action, Document, Node, RegionKind, Run, Screen, Slot}; | |
| 39 | 39 | use quasi_webview::Webview; | |
| 40 | 40 | ||
| 41 | 41 | use crate::git::signing::SignatureStatus; | |
| @@ -179,23 +179,22 @@ | |||
| 179 | 179 | // The full id, which is machine text: it is copied into a command far more | |
| 180 | 180 | // often than it is read. | |
| 181 | 181 | meta = meta.with(Node::Region( | |
| 182 | - | Slot::new("git-commit-oid", RegionKind::Group) | |
| 183 | - | .across(layout::Fallback::Wrap) | |
| 184 | - | .beside(Node::text("Commit:"), layout::Priority::Secondary) | |
| 185 | - | .beside(literal(&detail.oid), layout::Priority::Essential), | |
| 182 | + | Slot::new("git-commit-oid", RegionKind::Group).across( | |
| 183 | + | Run::new(layout::Fallback::Wrap) | |
| 184 | + | .beside(Node::text("Commit:"), layout::Priority::Secondary) | |
| 185 | + | .beside(literal(&detail.oid), layout::Priority::Essential), | |
| 186 | + | ), | |
| 186 | 187 | )); | |
| 187 | 188 | ||
| 188 | 189 | if !detail.parents.is_empty() { | |
| 189 | - | let mut parents = Slot::new("git-commit-parents", RegionKind::Group) | |
| 190 | - | .across(layout::Fallback::Wrap) | |
| 191 | - | .beside( | |
| 192 | - | Node::text(if detail.parents.len() == 1 { | |
| 193 | - | "Parent:" | |
| 194 | - | } else { | |
| 195 | - | "Parents:" | |
| 196 | - | }), | |
| 197 | - | layout::Priority::Secondary, | |
| 198 | - | ); | |
| 190 | + | let mut parents = Run::new(layout::Fallback::Wrap).beside( | |
| 191 | + | Node::text(if detail.parents.len() == 1 { | |
| 192 | + | "Parent:" | |
| 193 | + | } else { | |
| 194 | + | "Parents:" | |
| 195 | + | }), | |
| 196 | + | layout::Priority::Secondary, | |
| 197 | + | ); | |
| 199 | 198 | for parent in &detail.parents { | |
| 200 | 199 | parents = parents.beside( | |
| 201 | 200 | Node::Link { | |
| @@ -206,7 +205,9 @@ | |||
| 206 | 205 | layout::Priority::Essential, | |
| 207 | 206 | ); | |
| 208 | 207 | } | |
| 209 | - | meta = meta.with(Node::Region(parents)); | |
| 208 | + | meta = meta.with(Node::Region( | |
| 209 | + | Slot::new("git-commit-parents", RegionKind::Group).across(parents), | |
| 210 | + | )); | |
| 210 | 211 | } | |
| 211 | 212 | ||
| 212 | 213 | Node::Region(block.with(Node::Region(meta))) | |
| @@ -238,14 +239,16 @@ | |||
| 238 | 239 | } => Some(Node::Region( | |
| 239 | 240 | Slot::new("git-signature", RegionKind::Group) | |
| 240 | 241 | .named(format!("Signed by {username}, key {fingerprint}")) | |
| 241 | - | .across(layout::Fallback::Wrap) | |
| 242 | - | .beside(Node::text("Signed by"), layout::Priority::Essential) | |
| 243 | - | .beside( | |
| 244 | - | Node::Link { | |
| 245 | - | text: username.clone(), | |
| 246 | - | action: Action::get(format!("/u/{username}")).navigating(), | |
| 247 | - | }, | |
| 248 | - | layout::Priority::Essential, | |
| 242 | + | .across( | |
| 243 | + | Run::new(layout::Fallback::Wrap) | |
| 244 | + | .beside(Node::text("Signed by"), layout::Priority::Essential) | |
| 245 | + | .beside( | |
| 246 | + | Node::Link { | |
| 247 | + | text: username.clone(), | |
| 248 | + | action: Action::get(format!("/u/{username}")).navigating(), | |
| 249 | + | }, | |
| 250 | + | layout::Priority::Essential, | |
| 251 | + | ), | |
| 249 | 252 | ), | |
| 250 | 253 | )), | |
| 251 | 254 | SignatureStatus::ValidUnknownKey { .. } => { | |
| @@ -353,14 +356,10 @@ | |||
| 353 | 356 | )); | |
| 354 | 357 | ||
| 355 | 358 | for annotation in view.personal_annotations { | |
| 356 | - | let mut header = Slot::new( | |
| 357 | - | format!("annotation-header-{}", annotation.short_target), | |
| 358 | - | RegionKind::Group, | |
| 359 | - | ) | |
| 360 | - | .across(layout::Fallback::Wrap); | |
| 359 | + | let mut row = Run::new(layout::Fallback::Wrap); | |
| 361 | 360 | ||
| 362 | 361 | if let Some(origin) = &annotation.origin { | |
| 363 | - | header = header.beside( | |
| 362 | + | row = row.beside( | |
| 364 | 363 | match &annotation.link { | |
| 365 | 364 | Some(link) => Node::Link { | |
| 366 | 365 | text: origin.clone(), | |
| @@ -371,18 +370,18 @@ | |||
| 371 | 370 | layout::Priority::Secondary, | |
| 372 | 371 | ); | |
| 373 | 372 | } | |
| 374 | - | header = header.beside( | |
| 373 | + | row = row.beside( | |
| 375 | 374 | literal(&annotation.short_target), | |
| 376 | 375 | layout::Priority::Essential, | |
| 377 | 376 | ); | |
| 378 | 377 | if !annotation.updated.is_empty() { | |
| 379 | - | header = header.beside( | |
| 378 | + | row = row.beside( | |
| 380 | 379 | Node::text(annotation.updated.clone()), | |
| 381 | 380 | layout::Priority::Optional, | |
| 382 | 381 | ); | |
| 383 | 382 | } | |
| 384 | 383 | if annotation.orphan { | |
| 385 | - | header = header.beside( | |
| 384 | + | row = row.beside( | |
| 386 | 385 | Node::Text { | |
| 387 | 386 | text: "Annotates a commit makenot.work no longer serves.".to_owned(), | |
| 388 | 387 | tone: layout::Tone::Warning, | |
| @@ -391,6 +390,12 @@ | |||
| 391 | 390 | ); | |
| 392 | 391 | } | |
| 393 | 392 | ||
| 393 | + | let header = Slot::new( | |
| 394 | + | format!("annotation-header-{}", annotation.short_target), | |
| 395 | + | RegionKind::Group, | |
| 396 | + | ) | |
| 397 | + | .across(row); | |
| 398 | + | ||
| 394 | 399 | block = block.with(Node::Region( | |
| 395 | 400 | Slot::new( | |
| 396 | 401 | format!("annotation-{}", annotation.short_target), | |
| @@ -484,26 +489,27 @@ | |||
| 484 | 489 | }; | |
| 485 | 490 | ||
| 486 | 491 | Node::Region( | |
| 487 | - | Slot::new("git-diff-stats", RegionKind::Group) | |
| 488 | - | .across(layout::Fallback::Wrap) | |
| 489 | - | .beside( | |
| 490 | - | Node::text(format!("{} changed,", plural(view.total_files, "file"))), | |
| 491 | - | layout::Priority::Essential, | |
| 492 | - | ) | |
| 493 | - | .beside( | |
| 494 | - | Node::Text { | |
| 495 | - | text: format!("+{},", plural(view.total_additions, "insertion")), | |
| 496 | - | tone: layout::Tone::Success, | |
| 497 | - | }, | |
| 498 | - | layout::Priority::Essential, | |
| 499 | - | ) | |
| 500 | - | .beside( | |
| 501 | - | Node::Text { | |
| 502 | - | text: format!("-{}", plural(view.total_deletions, "deletion")), | |
| 503 | - | tone: layout::Tone::Danger, | |
| 504 | - | }, | |
| 505 | - | layout::Priority::Essential, | |
| 506 | - | ), | |
| 492 | + | Slot::new("git-diff-stats", RegionKind::Group).across( | |
| 493 | + | Run::new(layout::Fallback::Wrap) | |
| 494 | + | .beside( | |
| 495 | + | Node::text(format!("{} changed,", plural(view.total_files, "file"))), | |
| 496 | + | layout::Priority::Essential, | |
| 497 | + | ) | |
| 498 | + | .beside( | |
| 499 | + | Node::Text { | |
| 500 | + | text: format!("+{},", plural(view.total_additions, "insertion")), | |
| 501 | + | tone: layout::Tone::Success, | |
| 502 | + | }, | |
| 503 | + | layout::Priority::Essential, | |
| 504 | + | ) | |
| 505 | + | .beside( | |
| 506 | + | Node::Text { | |
| 507 | + | text: format!("-{}", plural(view.total_deletions, "deletion")), | |
| 508 | + | tone: layout::Tone::Danger, | |
| 509 | + | }, | |
| 510 | + | layout::Priority::Essential, | |
| 511 | + | ), | |
| 512 | + | ), | |
| 507 | 513 | ) | |
| 508 | 514 | } | |
| 509 | 515 | ||
| @@ -515,37 +521,33 @@ | |||
| 515 | 521 | None => file.path.clone(), | |
| 516 | 522 | }; | |
| 517 | 523 | ||
| 518 | - | let mut header = Slot::new( | |
| 519 | - | format!("diff-header-{}", slug(&file.path)), | |
| 520 | - | RegionKind::Group, | |
| 521 | - | ) | |
| 522 | - | .across(layout::Fallback::Wrap) | |
| 523 | - | // The one-letter status, as the tag it always was. | |
| 524 | - | .beside( | |
| 525 | - | { | |
| 526 | - | let mut badge = quasi_router::screen::Tag::badge(file.status.label()); | |
| 527 | - | // The four colours the shipped `.diff-status-*` rules picked, | |
| 528 | - | // said as tones rather than as a class per status. | |
| 529 | - | badge.tone = match file.status { | |
| 530 | - | crate::git::DiffStatus::Added => layout::Tone::Success, | |
| 531 | - | crate::git::DiffStatus::Deleted => layout::Tone::Danger, | |
| 532 | - | crate::git::DiffStatus::Modified => layout::Tone::Warning, | |
| 533 | - | crate::git::DiffStatus::Renamed => layout::Tone::Info, | |
| 534 | - | }; | |
| 535 | - | Node::Token(badge.hinted(file.status.name())) | |
| 536 | - | }, | |
| 537 | - | layout::Priority::Essential, | |
| 538 | - | ) | |
| 539 | - | .beside( | |
| 540 | - | Node::Link { | |
| 541 | - | text: label, | |
| 542 | - | action: Action::get(path_url).navigating(), | |
| 543 | - | }, | |
| 544 | - | layout::Priority::Essential, | |
| 545 | - | ); | |
| 524 | + | let mut row = Run::new(layout::Fallback::Wrap) | |
| 525 | + | // The one-letter status, as the tag it always was. | |
| 526 | + | .beside( | |
| 527 | + | { | |
| 528 | + | let mut badge = quasi_router::screen::Tag::badge(file.status.label()); | |
| 529 | + | // The four colours the shipped `.diff-status-*` rules picked, | |
| 530 | + | // said as tones rather than as a class per status. | |
| 531 | + | badge.tone = match file.status { | |
| 532 | + | crate::git::DiffStatus::Added => layout::Tone::Success, | |
| 533 | + | crate::git::DiffStatus::Deleted => layout::Tone::Danger, | |
| 534 | + | crate::git::DiffStatus::Modified => layout::Tone::Warning, | |
| 535 | + | crate::git::DiffStatus::Renamed => layout::Tone::Info, | |
| 536 | + | }; | |
| 537 | + | Node::Token(badge.hinted(file.status.name())) | |
| 538 | + | }, | |
| 539 | + | layout::Priority::Essential, | |
| 540 | + | ) | |
| 541 | + | .beside( | |
| 542 | + | Node::Link { | |
| 543 | + | text: label, | |
| 544 | + | action: Action::get(path_url).navigating(), | |
| 545 | + | }, | |
| 546 | + | layout::Priority::Essential, | |
| 547 | + | ); | |
| 546 | 548 | ||
| 547 | 549 | if file.additions > 0 { | |
| 548 | - | header = header.beside( | |
| 550 | + | row = row.beside( | |
| 549 | 551 | Node::Text { | |
| 550 | 552 | text: format!("+{}", file.additions), | |
| 551 | 553 | tone: layout::Tone::Success, | |
| @@ -554,7 +556,7 @@ | |||
| 554 | 556 | ); | |
| 555 | 557 | } | |
| 556 | 558 | if file.deletions > 0 { | |
| 557 | - | header = header.beside( | |
| 559 | + | row = row.beside( | |
| 558 | 560 | Node::Text { | |
| 559 | 561 | text: format!("-{}", file.deletions), | |
| 560 | 562 | tone: layout::Tone::Danger, | |
| @@ -563,6 +565,12 @@ | |||
| 563 | 565 | ); | |
| 564 | 566 | } | |
| 565 | 567 | ||
| 568 | + | let header = Slot::new( | |
| 569 | + | format!("diff-header-{}", slug(&file.path)), | |
| 570 | + | RegionKind::Group, | |
| 571 | + | ) | |
| 572 | + | .across(row); | |
| 573 | + | ||
| 566 | 574 | let mut block = Slot::new(format!("diff-{}", slug(&file.path)), RegionKind::Group) | |
| 567 | 575 | .with(Node::Region(header)); | |
| 568 | 576 |
| @@ -43,7 +43,7 @@ | |||
| 43 | 43 | ||
| 44 | 44 | use makeover_layout as layout; | |
| 45 | 45 | use quasi_router::screen::{Field, Row}; | |
| 46 | - | use quasi_router::{Action, Node, RegionKind, Slot}; | |
| 46 | + | use quasi_router::{Action, Node, RegionKind, Run, Slot}; | |
| 47 | 47 | ||
| 48 | 48 | use crate::git::{Breadcrumb, RefInfo}; | |
| 49 | 49 | ||
| @@ -91,16 +91,16 @@ | |||
| 91 | 91 | /// that changes nothing on the page. They pass no refs and get the strip. | |
| 92 | 92 | #[must_use] | |
| 93 | 93 | pub fn region(nav: &Nav<'_>) -> Node { | |
| 94 | - | let mut bar = Slot::new(REGION, RegionKind::Group) | |
| 95 | - | // The bar is one row that wraps below the breakpoint. Nothing in it may | |
| 96 | - | // drop: the chooser and the strip are the only ways off this page. | |
| 97 | - | .across(layout::Fallback::Wrap); | |
| 94 | + | // The bar is one row that wraps below the breakpoint. Nothing in it may | |
| 95 | + | // drop: the chooser and the strip are the only ways off this page. | |
| 96 | + | let mut bar = Run::new(layout::Fallback::Wrap); | |
| 98 | 97 | ||
| 99 | 98 | if !nav.refs.is_empty() { | |
| 100 | 99 | bar = bar.beside(Node::field(chooser(nav)), layout::Priority::Essential); | |
| 101 | 100 | } | |
| 102 | 101 | ||
| 103 | - | Node::Region(bar.beside(strip(nav), layout::Priority::Essential)) | |
| 102 | + | let bar = bar.beside(strip(nav), layout::Priority::Essential); | |
| 103 | + | Node::Region(Slot::new(REGION, RegionKind::Group).across(bar)) | |
| 104 | 104 | } | |
| 105 | 105 | ||
| 106 | 106 | /// The markup, for an Askama template to drop in. | |
| @@ -206,20 +206,22 @@ | |||
| 206 | 206 | Node::Region( | |
| 207 | 207 | Slot::new("git-repo-name", RegionKind::Group) | |
| 208 | 208 | .named(format!("{owner} / {repo}")) | |
| 209 | - | .across(layout::Fallback::Wrap) | |
| 210 | - | .beside( | |
| 211 | - | Node::Link { | |
| 212 | - | text: owner.to_owned(), | |
| 213 | - | action: Action::get(format!("/git/{owner}")).navigating(), | |
| 214 | - | }, | |
| 215 | - | layout::Priority::Essential, | |
| 216 | - | ) | |
| 217 | - | .beside( | |
| 218 | - | Node::Link { | |
| 219 | - | text: repo.to_owned(), | |
| 220 | - | action: Action::get(format!("/git/{owner}/{repo}")).navigating(), | |
| 221 | - | }, | |
| 222 | - | layout::Priority::Essential, | |
| 209 | + | .across( | |
| 210 | + | Run::new(layout::Fallback::Wrap) | |
| 211 | + | .beside( | |
| 212 | + | Node::Link { | |
| 213 | + | text: owner.to_owned(), | |
| 214 | + | action: Action::get(format!("/git/{owner}")).navigating(), | |
| 215 | + | }, | |
| 216 | + | layout::Priority::Essential, | |
| 217 | + | ) | |
| 218 | + | .beside( | |
| 219 | + | Node::Link { | |
| 220 | + | text: repo.to_owned(), | |
| 221 | + | action: Action::get(format!("/git/{owner}/{repo}")).navigating(), | |
| 222 | + | }, | |
| 223 | + | layout::Priority::Essential, | |
| 224 | + | ), | |
| 223 | 225 | ), | |
| 224 | 226 | ) | |
| 225 | 227 | } | |
| @@ -233,16 +235,13 @@ | |||
| 233 | 235 | pub fn breadcrumb(owner: &str, repo: &str, current_ref: &str, crumbs: &[Breadcrumb]) -> Node { | |
| 234 | 236 | let tree = format!("/git/{owner}/{repo}/tree/{current_ref}"); | |
| 235 | 237 | ||
| 236 | - | let mut trail = Slot::new("git-breadcrumb", RegionKind::Group) | |
| 237 | - | .named("Path") | |
| 238 | - | .across(layout::Fallback::Wrap) | |
| 239 | - | .beside( | |
| 240 | - | Node::Link { | |
| 241 | - | text: repo.to_owned(), | |
| 242 | - | action: Action::get(tree.clone()).navigating(), | |
| 243 | - | }, | |
| 244 | - | layout::Priority::Essential, | |
| 245 | - | ); | |
| 238 | + | let mut trail = Run::new(layout::Fallback::Wrap).beside( | |
| 239 | + | Node::Link { | |
| 240 | + | text: repo.to_owned(), | |
| 241 | + | action: Action::get(tree.clone()).navigating(), | |
| 242 | + | }, | |
| 243 | + | layout::Priority::Essential, | |
| 244 | + | ); | |
| 246 | 245 | ||
| 247 | 246 | for crumb in crumbs { | |
| 248 | 247 | let node = if crumb.is_link { | |
| @@ -256,7 +255,11 @@ | |||
| 256 | 255 | trail = trail.beside(node, layout::Priority::Essential); | |
| 257 | 256 | } | |
| 258 | 257 | ||
| 259 | - | Node::Region(trail) | |
| 258 | + | Node::Region( | |
| 259 | + | Slot::new("git-breadcrumb", RegionKind::Group) | |
| 260 | + | .named("Path") | |
| 261 | + | .across(trail), | |
| 262 | + | ) | |
| 260 | 263 | } | |
| 261 | 264 | ||
| 262 | 265 | #[cfg(test)] |
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | 31 | use makeover_layout as layout; | |
| 32 | 32 | use quasi_router::screen::Lexeme; | |
| 33 | - | use quasi_router::{Node, RegionKind, Slot}; | |
| 33 | + | use quasi_router::{Node, RegionKind, Run, Slot}; | |
| 34 | 34 | use quasi_webview::Webview; | |
| 35 | 35 | ||
| 36 | 36 | use crate::routes::git::notes_view::CommitNote; | |
| @@ -122,15 +122,10 @@ | |||
| 122 | 122 | ||
| 123 | 123 | /// One note: what it is, where it came from, and what it says. | |
| 124 | 124 | fn one(note: &CommitNote) -> Slot { | |
| 125 | - | let mut header = Slot::new( | |
| 126 | - | format!("note-header-{}", slug(¬e.namespace)), | |
| 127 | - | RegionKind::Group, | |
| 128 | - | ) | |
| 129 | 125 | // The header is one line: a name on the left and a provenance on the | |
| 130 | 126 | // right. Wrapping keeps both when there is no room for one line, which | |
| 131 | 127 | // is what the shipped rule's `flex-wrap` did. | |
| 132 | - | .across(layout::Fallback::Wrap) | |
| 133 | - | .beside( | |
| 128 | + | let mut header = Run::new(layout::Fallback::Wrap).beside( | |
| 134 | 129 | Node::Code { | |
| 135 | 130 | runs: vec![Lexeme::plain(¬e.namespace)], | |
| 136 | 131 | language: None, | |
| @@ -173,7 +168,13 @@ | |||
| 173 | 168 | } | |
| 174 | 169 | ||
| 175 | 170 | Slot::new(format!("note-{}", slug(¬e.namespace)), RegionKind::Group) | |
| 176 | - | .with(Node::Region(header)) | |
| 171 | + | .with(Node::Region( | |
| 172 | + | Slot::new( | |
| 173 | + | format!("note-header-{}", slug(¬e.namespace)), | |
| 174 | + | RegionKind::Group, | |
| 175 | + | ) | |
| 176 | + | .across(header), | |
| 177 | + | )) | |
| 177 | 178 | .with(Node::Region(Slot::handover( | |
| 178 | 179 | body_region(¬e.namespace), | |
| 179 | 180 | "a rendered note", |