T44d Web · Gallery builds for wasm32: one story per section by URL, themed by the host

The gallery's entry runs natively or, on wasm32, from a wasm_bindgen start
through gpui_web, single-threaded with WebGL2 fallback. ?page, ?story and
?theme choose what shows; an unknown one fails in the page and the log.
set_theme switches the mode later. Pictures load from ELY_GALLERY_ASSETS.
scripts/stories.py writes examples/gallery/stories.json from the pages.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-29 19:16:41 -04:00
1 parent 29f1c8f467
commit 09dd3fc2cb
83 files changed
+1000 -455

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@ mod billing;
mod sign_in;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 36,
+1 -1
View File
@@ -8,7 +8,7 @@ mod tools;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 24,
+1 -1
View File
@@ -5,7 +5,7 @@ mod choices;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 5,
+1 -1
View File
@@ -13,7 +13,7 @@ mod people;
mod times;
use super::Page;
use crate::{script::Step, ui::keep};
use crate::{step::Step, ui::keep};
pub const PAGE: Page = Page {
number: 30,
+1 -1
View File
@@ -8,7 +8,7 @@ mod plane;
mod tools;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 32,
+1 -1
View File
@@ -6,7 +6,7 @@ mod wholes;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 15,
+1 -2
View File
@@ -1,5 +1,3 @@
use std::time::Instant;
use ely_gpui_component::{
buttons::SegmentedControl,
chat::{
@@ -13,6 +11,7 @@ use ely_gpui_component::{
primitives::IconName,
};
use gpui::{App, Entity, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use web_time::Instant;
use crate::{
probe::probe,
+2 -1
View File
@@ -1,4 +1,4 @@
use std::time::{Duration, Instant};
use std::time::Duration;
use ely_gpui_component::{
buttons::{Button, ButtonVariant},
@@ -11,6 +11,7 @@ use ely_gpui_component::{
primitives::IconName,
};
use gpui::{App, Entity, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use web_time::Instant;
use crate::{
probe::probe,
+1 -1
View File
@@ -10,7 +10,7 @@ use ely_gpui_component::feedback::{ToastViewport, Toaster};
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::{script::Step, ui::keep};
use crate::{step::Step, ui::keep};
pub const PAGE: Page = Page {
number: 23,
+1 -1
View File
@@ -5,7 +5,7 @@ mod talk;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 22,
+1 -1
View File
@@ -4,7 +4,7 @@ mod board;
mod monitor;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 34,
+4 -6
View File
@@ -1,5 +1,3 @@
use std::path::Path;
use ely_gpui_component::{
buttons::{Button, ButtonVariant},
data_display::{BeforeAfter, Carousel, Gallery, Watermark},
@@ -12,7 +10,7 @@ use gpui::{App, IntoElement, ObjectFit, ParentElement, Styled, Window, div, px};
use crate::{
probe::probe,
ui::{keep, section, set},
ui::{keep, picture, section, set},
};
const PICTURES: [(&str, &str); 6] = [
@@ -35,7 +33,7 @@ pub fn carousel(cx: &mut App) -> impl IntoElement + use<> {
.relative()
.size_full()
.child(
Image::new(("carousel-picture", ix), Path::new(*path))
Image::new(("carousel-picture", ix), picture(*path))
.fit(ObjectFit::Cover)
.size_full(),
)
@@ -74,14 +72,14 @@ pub fn gallery(cx: &mut App) -> impl IntoElement + use<> {
"gallery",
div().w(px(420.)).child(Gallery::new(
"gallery",
PICTURES.map(|(path, caption)| Slide::new(Path::new(path), caption)),
PICTURES.map(|(path, caption)| Slide::new(picture(path), caption)),
)),
)))
}
pub fn before_after(cx: &mut App) -> impl IntoElement + use<> {
let picture = |id: &'static str, path: &'static str| {
Image::new(id, Path::new(path))
Image::new(id, picture(path))
.fit(ObjectFit::Cover)
.size_full()
};
+1 -1
View File
@@ -6,7 +6,7 @@ mod records;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 12,
+5 -8
View File
@@ -1,4 +1,4 @@
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use ely_gpui_component::{
buttons::{Button, ButtonVariant},
@@ -15,13 +15,10 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div};
use crate::{
probe::probe,
ui::{keep, row, section, set, specimen, specimens},
ui::{keep, picture, row, section, set, specimen, specimens},
};
const DUNES: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes-square.jpg"
);
const DUNES: &str = asset!("dunes-square.jpg");
pub fn badges(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let unread = keep("badge-unread", || 3usize, window, cx);
@@ -127,7 +124,7 @@ pub fn avatars(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
})))
.child(
specimens()
.child(specimen("picture", Avatar::new("avatar-photo", "Dunes").image(Path::new(DUNES)).size(AvatarSize::Lg), cx))
.child(specimen("picture", Avatar::new("avatar-photo", "Dunes").image(picture(DUNES)).size(AvatarSize::Lg), cx))
.child(specimen("online", Avatar::new("avatar-online", "Aiko Tanaka").size(AvatarSize::Lg).presence(Presence::Online), cx))
.child(specimen("away", Avatar::new("avatar-away", "Lucía Romero").size(AvatarSize::Lg).presence(Presence::Away), cx))
.child(specimen("busy", Avatar::new("avatar-busy", "Ben Carter").size(AvatarSize::Lg).presence(Presence::Busy), cx))
@@ -182,7 +179,7 @@ pub fn groups(cx: &mut App) -> impl IntoElement + use<> {
.child("Assigned to")
.child(UserChip::new("chip-grace", "Grace Hopper"))
.child("and")
.child(UserChip::new("chip-dunes", "Dune Studio").image(Path::new(DUNES)))
.child(UserChip::new("chip-dunes", "Dune Studio").image(picture(DUNES)))
.child("for review."),
)
}
+1 -1
View File
@@ -5,7 +5,7 @@ mod session;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 20,
+1 -1
View File
@@ -7,7 +7,7 @@ mod formats;
mod tools;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 33,
+1 -4
View File
@@ -12,10 +12,7 @@ use crate::{
ui::{keep, section, set},
};
const ATRIUM: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
);
const ATRIUM: &str = asset!("atrium.jpg");
const PEOPLE: [&str; 4] = ["ada", "grace", "linus", "margaret"];
+3 -12
View File
@@ -20,18 +20,9 @@ use crate::{
};
const COVERS: [&str; 3] = [
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
),
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes.jpg"
),
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium-olive.jpg"
),
asset!("atrium.jpg"),
asset!("dunes.jpg"),
asset!("atrium-olive.jpg"),
];
fn favorite(key: &str, icon: &str, title: &str) -> Favorite {
+1 -1
View File
@@ -5,7 +5,7 @@ mod reading;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 21,
+2 -20
View File
@@ -22,26 +22,8 @@ use crate::{
ui::{keep, section, set},
};
const PAGES: [&str; 2] = [
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/pages/lift-1.png"
),
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/pages/lift-2.png"
),
];
const SLIDES: [&str; 2] = [
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/pages/slide-1.png"
),
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/pages/slide-2.png"
),
];
const PAGES: [&str; 2] = [asset!("pages/lift-1.png"), asset!("pages/lift-2.png")];
const SLIDES: [&str; 2] = [asset!("pages/slide-1.png"), asset!("pages/slide-2.png")];
const WORDS: &str = include_str!("../../assets/pages/lift.json");
const GUIDE: &str = "# Lift\n\nA lift blends a color toward white.\n\n## In light\n\nPaper white under ink near black; accents at half a lift.\n\n## In dark\n\nWarm charcoal under off-white text; accents lift further, so they read with the same weight.\n\n### Surfaces\n\nA card sits one lift above the page, a menu one above the card.\n\n## In motion\n\nHover, press and focus are lifts of the accent, eased on one scale of durations.\n\n## Closing\n\nWhatever the hue, a step of lift means the same step of emphasis.";
+1 -1
View File
@@ -9,7 +9,7 @@ mod status;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 17,
+1 -1
View File
@@ -4,7 +4,7 @@ mod states;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 10,
+2 -1
View File
@@ -1,4 +1,4 @@
use std::time::{Duration, Instant};
use std::time::Duration;
use anyhow::anyhow;
use ely_gpui_component::{
@@ -13,6 +13,7 @@ use ely_gpui_component::{
typography::Caption,
};
use gpui::{App, Div, IntoElement, ParentElement, Styled, Window, div, prelude::FluentBuilder};
use web_time::Instant;
use crate::{
probe::probe,
+4 -9
View File
@@ -1,5 +1,3 @@
use std::path::Path;
use ely_gpui_component::{
debug::HexViewer,
documents::{Favorite, Favorites},
@@ -18,13 +16,10 @@ use jiff::{SignedDuration, Timestamp, ToSpan};
use crate::{
probe::probe,
ui::{change, keep, section},
ui::{change, keep, picture, section},
};
const ATRIUM: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
);
const ATRIUM: &str = asset!("atrium.jpg");
const BRIEF: &str = "# Atrium\n\nA quiet hall for the new library.\n\n- Light from above, all day\n- One stair, curved, in plaster\n- Olive trees by the windows\n\nNext: the model walkthrough on Friday.";
fn entry(name: &str, bytes: u64, hours: i64) -> DirEntry {
@@ -38,7 +33,7 @@ pub fn previews(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let chosen = picked.read(cx).clone();
let preview = |name: &SharedString| match name.as_ref() {
"Atrium.jpg" => FilePreview::new("files-look", entry("Atrium.jpg", 2_140_000, 50))
.picture(Path::new(ATRIUM), 1.5),
.picture(picture(ATRIUM), 1.5),
"Brief.md" => FilePreview::new("files-look", entry("Brief.md", 4_800, 2)).text(BRIEF),
other => FilePreview::new("files-look", entry(other, 48_000_000, 700)),
};
@@ -289,7 +284,7 @@ pub fn archive(cx: &mut App) -> impl IntoElement + use<> {
pub fn hex(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let bytes = keep(
"files-hex",
|| std::fs::read(ATRIUM).expect("the gallery's picture reads")[..512].to_vec(),
|| include_bytes!("../../assets/atrium.jpg")[..512].to_vec(),
window,
cx,
);
+1 -1
View File
@@ -14,7 +14,7 @@ mod transfers;
use super::Page;
use crate::{
probe::probe,
script::Step,
step::Step,
ui::{change, keep, section},
};
+2 -1
View File
@@ -1,4 +1,4 @@
use std::time::{Duration, Instant};
use std::time::Duration;
use ely_gpui_component::{
charts::PieChart,
@@ -13,6 +13,7 @@ use ely_gpui_component::{
};
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use jiff::{Timestamp, civil::date, tz::TimeZone};
use web_time::Instant;
use crate::ui::{keep, noise, row, section, set};
+1 -1
View File
@@ -7,7 +7,7 @@ mod trading;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 16,
+1 -1
View File
@@ -14,7 +14,7 @@ mod values;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 6,
+1 -1
View File
@@ -8,7 +8,7 @@ mod sound;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 25,
+4 -4
View File
@@ -1,4 +1,4 @@
use std::{path::Path, time::Duration};
use std::time::Duration;
use ely_gpui_component::{
data_display::BeforeAfter,
@@ -12,7 +12,7 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, p
use crate::{
probe::probe,
ui::{keep, section, set},
ui::{keep, picture, section, set},
};
fn jobs() -> Vec<Job> {
@@ -137,8 +137,8 @@ pub fn results(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
.child(
BeforeAfter::new(
"gen-compare",
Image::new("gen-compare-before", Path::new(asset!("atrium-before.jpg"))).size_full(),
Image::new("gen-compare-after", Path::new(asset!("atrium.jpg"))).size_full(),
Image::new("gen-compare-before", picture(asset!("atrium-before.jpg"))).size_full(),
Image::new("gen-compare-after", picture(asset!("atrium.jpg"))).size_full(),
)
.w(px(420.))
.h(px(280.)),
+1 -1
View File
@@ -5,7 +5,7 @@ mod work;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 19,
+1 -1
View File
@@ -12,7 +12,7 @@ mod a11y;
use super::Page;
use crate::probe::probe;
use crate::script::Step;
use crate::step::Step;
use crate::ui::{section, specimen, specimens};
pub const PAGE: Page = Page {
+1 -1
View File
@@ -6,7 +6,7 @@ mod pointer;
pub use keys::bind_keys;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 38,
+1 -1
View File
@@ -7,7 +7,7 @@ mod systems;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 3,
+1 -1
View File
@@ -6,7 +6,7 @@ mod trees;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 13,
+1 -1
View File
@@ -16,7 +16,7 @@ mod write;
use super::Page;
use crate::{
probe::probe,
script::Step,
step::Step,
ui::{change, keep, section},
};
+4 -6
View File
@@ -1,5 +1,3 @@
use std::path::PathBuf;
use ely_gpui_component::{
maps::{
CoordFormat, CoordinateDisplay, LatLon, LocationPicker, MapMarker, MapPopup, MapView,
@@ -16,8 +14,8 @@ mod world;
use super::Page;
use crate::probe::probe;
use crate::script::Step;
use crate::ui::{keep, section, set, specimen, specimens};
use crate::step::Step;
use crate::ui::{keep, picture, section, set, specimen, specimens};
pub const PAGE: Page = Page {
number: 41,
@@ -48,7 +46,7 @@ pub const PAGE: Page = Page {
],
};
const TILES: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/gallery/assets/tiles");
const TILES: &str = asset!("tiles");
pub(super) const ATTRIBUTION: &str = "Land: Natural Earth";
const CITIES: [(&str, &str, f64, f64, usize); 6] = [
@@ -62,7 +60,7 @@ const CITIES: [(&str, &str, f64, f64, usize); 6] = [
/// The gallery's tiles, cut from Natural Earth by `scripts/tiles.py`.
pub(super) fn tile(tile: Tile) -> ImageSource {
PathBuf::from(format!("{TILES}/{}/{}/{}.png", tile.z, tile.x, tile.y)).into()
picture(format!("{TILES}/{}/{}/{}.png", tile.z, tile.x, tile.y))
}
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
+4 -7
View File
@@ -1,4 +1,4 @@
use std::{path::Path, time::Duration};
use std::time::Duration;
use ely_gpui_component::media::{
AudioPlayer, AudioSpectrum, AudioWaveform, MediaControls, PlaybackSpeedControl, Playlist,
@@ -10,13 +10,10 @@ use gpui::{
use crate::{
probe::probe,
ui::{change, keep, noise, section},
ui::{change, keep, noise, picture, section},
};
const COVER: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes-square.jpg"
);
const COVER: &str = asset!("dunes-square.jpg");
/// How often the demo's clock moves while a song plays.
const TICK: Duration = Duration::from_millis(100);
const SONGS: [(&str, &str, &str, u64); 5] = [
@@ -181,7 +178,7 @@ pub fn player(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let (title, artist) = (SONGS[now.song].1, SONGS[now.song].2);
let seek = state.clone();
let player = AudioPlayer::new("media-audio", title, artist, now.length(), now.at)
.artwork(Path::new(COVER))
.artwork(picture(COVER))
.controls(controls("media-audio-transport", &state, &now))
.volume(volume("media-audio-volume", &state, &now))
.on_seek(move |at, _, cx| change(&seek, cx, |now| now.at = at));
+4 -7
View File
@@ -1,4 +1,4 @@
use std::{path::Path, sync::Arc};
use std::sync::Arc;
use ely_gpui_component::{
media::{
@@ -15,13 +15,10 @@ use gpui::{
use super::sculpt;
use crate::{
probe::probe,
ui::{change, keep, section},
ui::{change, keep, picture, section},
};
const OLIVE: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium-olive.jpg"
);
const OLIVE: &str = asset!("atrium-olive.jpg");
/// The model's frame, in pixels: twice the viewer's points.
const FRAME: (u32, u32) = (960, 640);
@@ -105,7 +102,7 @@ pub fn camera(cx: &mut App) -> impl IntoElement + use<> {
.child(
div().w(px(300.)).child(
CameraPreview::new("media-camera-on", 1.5)
.frame(Path::new(OLIVE))
.frame(picture(OLIVE))
.name("Studio camera"),
),
)
+7 -16
View File
@@ -1,4 +1,4 @@
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use ely_gpui_component::{
buttons::SegmentedControl,
@@ -9,21 +9,12 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, p
use crate::{
probe::probe,
ui::{keep, section, set},
ui::{keep, picture, section, set},
};
const ATRIUM: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
);
const STAIR: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium-stair.jpg"
);
const DUNES: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes.jpg"
);
const ATRIUM: &str = asset!("atrium.jpg");
const STAIR: &str = asset!("atrium-stair.jpg");
const DUNES: &str = asset!("dunes.jpg");
/// Crop shapes to pick from, width over height; none is free.
const ASPECTS: [(&str, Option<f32>); 4] = [
@@ -89,7 +80,7 @@ pub fn cropper(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
.child(probe(
"media-cropper",
div().w(px(560.)).child(
ImageCropper::new("media-cropper", Path::new(ATRIUM), 1.5, crop)
ImageCropper::new("media-cropper", picture(ATRIUM), 1.5, crop)
.aspect(aspect)
.on_change(move |crop, _, cx| {
let shape = moved.read(cx).1;
@@ -165,7 +156,7 @@ pub fn annotator(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
.child(probe(
"media-annotator",
div().w(px(560.)).child(
ImageAnnotator::new("media-annotator", Path::new(STAIR), 1.5, marks)
ImageAnnotator::new("media-annotator", picture(STAIR), 1.5, marks)
.on_change(move |marks, _, cx| set(&changed, marks.to_vec(), cx)),
),
))
+9 -46
View File
@@ -1,5 +1,3 @@
use std::path::{Path, PathBuf};
use ely_gpui_component::{
media::{ImageThumbnail, ImageViewer},
overlays::{Lightbox, Slide},
@@ -8,56 +6,21 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, p
use crate::{
probe::probe,
ui::{keep, row, section, set},
ui::{keep, picture, resource, row, section, set},
};
/// The gallery's pictures: a file, its width over height, a caption, and a corner label.
const PICTURES: [(&str, f32, &str, &str); 5] = [
(asset!("atrium.jpg"), 1.5, "An atrium, noon", ""),
(asset!("dunes.jpg"), 1.5, "Dunes at first light", ""),
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
),
1.5,
"An atrium, noon",
"",
),
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes.jpg"
),
1.5,
"Dunes at first light",
"",
),
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium-olive.jpg"
),
asset!("atrium-olive.jpg"),
1.5,
"An olive tree by the stair",
"HDR",
),
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes-grass.jpg"
),
1.5,
"Grass on the ridge",
"",
),
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes-square.jpg"
),
1.0,
"The long shadow",
"+2",
),
(asset!("dunes-grass.jpg"), 1.5, "Grass on the ridge", ""),
(asset!("dunes-square.jpg"), 1.0, "The long shadow", "+2"),
];
pub fn viewer(cx: &mut App) -> impl IntoElement + use<> {
@@ -68,7 +31,7 @@ pub fn viewer(cx: &mut App) -> impl IntoElement + use<> {
)
.child(probe(
"media-viewer",
div().w(px(640.)).h(px(440.)).child(ImageViewer::new("media-viewer", PathBuf::from(PICTURES[0].0))),
div().w(px(640.)).h(px(440.)).child(ImageViewer::new("media-viewer", resource(PICTURES[0].0))),
))
}
@@ -83,7 +46,7 @@ pub fn thumbnails(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
let (open, mark) = (shown.clone(), opened.clone());
let thumb = ImageThumbnail::new(
SharedString::from(format!("media-thumb-{ix}")),
Path::new(*path),
picture(*path),
*ratio,
)
.selected(ix == last)
@@ -102,7 +65,7 @@ pub fn thumbnails(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
let (step, close) = (shown.clone(), shown.clone());
Lightbox::new(
"media-lightbox",
PICTURES.map(|(path, _, caption, _)| Slide::new(Path::new(path), caption)),
PICTURES.map(|(path, _, caption, _)| Slide::new(picture(path), caption)),
at,
move |_, cx| set(&close, None, cx),
)
+1 -1
View File
@@ -8,7 +8,7 @@ mod video;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 26,
+7 -16
View File
@@ -1,4 +1,4 @@
use std::{path::Path, time::Duration};
use std::time::Duration;
use ely_gpui_component::media::{Cue, Scrubber, SubtitleEditor, VideoPlayer, VideoThumbnailStrip};
use gpui::{
@@ -7,22 +7,13 @@ use gpui::{
use crate::{
probe::probe,
ui::{keep, section, set},
ui::{keep, picture, section, set},
};
const FRAMES: [&str; 3] = [
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
),
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium-stair.jpg"
),
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium-olive.jpg"
),
asset!("atrium.jpg"),
asset!("atrium-stair.jpg"),
asset!("atrium-olive.jpg"),
];
const LENGTH: Duration = Duration::from_secs(90);
/// How often the demo's clock moves while it plays.
@@ -115,7 +106,7 @@ pub fn video(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
(state.clone(), state.clone(), state.clone(), state.clone());
let player = VideoPlayer::new(
"media-player",
Some(Path::new(frame(now.at)).into()),
Some(picture(frame(now.at))),
1.5,
LENGTH,
now.at,
@@ -190,7 +181,7 @@ pub fn strip(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let state = state(window, cx);
let now = state.read(cx).clone();
let (seek, cut) = (state.clone(), state.clone());
let frames = (0..8).map(|ix| Path::new(FRAMES[ix * 3 / 8]));
let frames = (0..8).map(|ix| picture(FRAMES[ix * 3 / 8]));
section(
"VideoThumbnailStrip",
"Frames along the video under its playhead, and the part kept between two handles. A press seeks; a handle trims; I and O set the ends at the playhead.",
+1 -1
View File
@@ -4,7 +4,7 @@ mod rows;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 8,
+5 -6
View File
@@ -1,5 +1,3 @@
use std::{path::Path, time::Instant};
use ely_gpui_component::{
buttons::Button,
data_display::Avatar,
@@ -10,10 +8,11 @@ use ely_gpui_component::{
theme::{ActiveTheme, TextSize},
};
use gpui::{App, Entity, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use web_time::Instant;
use crate::{
probe::probe,
ui::{change, keep, section},
ui::{change, keep, picture, section},
};
const ROOM: &str = asset!("atrium-olive.jpg");
@@ -126,7 +125,7 @@ pub fn grid(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let tile = |key: &'static str, name: &'static str| ParticipantTile::new(key, name, CAMERA);
let you = tile("messaging-tile-you", "You").muted(!now.mic);
let you = match now.camera {
true => you.frame(Path::new(ROOM)),
true => you.frame(picture(ROOM)),
false => you,
};
section(
@@ -138,7 +137,7 @@ pub fn grid(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"messaging-grid",
div().w(px(640.)).child(
VideoCallGrid::new("messaging-grid")
.child(tile("messaging-tile-ana", "Ana Lima").frame(Path::new(STAIR)).speaking(true))
.child(tile("messaging-tile-ana", "Ana Lima").frame(picture(STAIR)).speaking(true))
.child(tile("messaging-tile-ben", "Ben Ito").muted(true))
.child(you)
.child(tile("messaging-tile-chloe", "Chloé Martin"))
@@ -152,7 +151,7 @@ pub fn share(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let sharing = state.read(cx).share;
let tile = |key: &'static str, name: &'static str| ParticipantTile::new(key, name, CAMERA);
let view = ScreenShareView::new("messaging-share", "Ana Lima", 16.0 / 10.0)
.frame(Path::new(SCREEN))
.frame(picture(SCREEN))
.child(tile("messaging-strip-ben", "Ben Ito").muted(true))
.child(tile("messaging-strip-chloe", "Chloé Martin").speaking(true));
let view = match sharing {
+1 -1
View File
@@ -15,7 +15,7 @@ mod pickers;
use super::Page;
use crate::{
probe::probe,
script::Step,
step::Step,
ui::{change, keep, section},
};
+5 -7
View File
@@ -1,5 +1,3 @@
use std::path::Path;
use ely_gpui_component::{
messaging::{ChatMessage, Gif, GifPicker, Gifs, Sticker, StickerPack, StickerPicker},
primitives::Image,
@@ -12,7 +10,7 @@ use jiff::{civil::date, tz::TimeZone};
use crate::{
probe::probe,
ui::{keep, section, set, specimen, specimens},
ui::{keep, picture, section, set, specimen, specimens},
};
const ATRIUM: [(&str, &str, &str); 4] = [
@@ -60,7 +58,7 @@ const GIFS: [(&str, &str, &str, f32); 4] = [
fn pack(name: &str, stickers: [(&'static str, &'static str, &'static str); 4]) -> StickerPack {
StickerPack::new(
name.to_string(),
stickers.map(|(key, title, file)| Sticker::new(key, title, Path::new(file))),
stickers.map(|(key, title, file)| Sticker::new(key, title, picture(file))),
)
}
@@ -101,7 +99,7 @@ pub fn stickers(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
ElementId::from("messaging-sticker-picture"),
key.to_string(),
),
Path::new(*file),
picture(*file),
)
.fit(ObjectFit::Contain)
.size_full(),
@@ -146,7 +144,7 @@ fn found(words: &str) -> Vec<Gif> {
let words = words.to_lowercase();
GIFS.iter()
.filter(|(_, title, _, _)| title.to_lowercase().contains(&words))
.map(|(key, title, file, ratio)| Gif::new(*key, *title, Path::new(*file), *ratio))
.map(|(key, title, file, ratio)| Gif::new(*key, *title, picture(*file), *ratio))
.collect()
}
@@ -163,7 +161,7 @@ pub fn gifs(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
div().w(px(200.)).h(px(200. / ratio)).child(
Image::new(
(ElementId::from("messaging-gif-picture"), key.to_string()),
Path::new(*file),
picture(*file),
)
.size_full()
.rounded(round),
+4 -7
View File
@@ -1,16 +1,13 @@
use std::{path::PathBuf, sync::Arc};
use std::sync::Arc;
use ely_gpui_component::misc::{Captcha, CaptchaState, QrCodeScanner};
use gpui::{App, IntoElement, ParentElement, RenderImage, Styled, Window, div, px};
use crate::probe::probe;
use crate::ui::section;
use crate::ui::{picture, section};
const ANSWERS: [&str; 2] = ["W7XK", "Q3NP"];
const PICTURES: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/captcha"
);
const PICTURES: &str = asset!("captcha");
/// The frame a camera would hand in: a QR code on a card over a dim scene, in gpui's BGRA pixels.
fn scene() -> Arc<RenderImage> {
@@ -46,7 +43,7 @@ pub fn render(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let (ix, state) = *desk.read(cx);
let answer = ANSWERS[ix];
let (checked, refreshed) = (desk.clone(), desk);
let picture = PathBuf::from(format!("{PICTURES}/{}.png", answer.to_lowercase()));
let picture = picture(format!("{PICTURES}/{}.png", answer.to_lowercase()));
div()
.child(
section(
+1 -1
View File
@@ -4,7 +4,7 @@ use jiff::tz::TimeZone;
use super::Page;
use crate::probe::probe;
use crate::script::Step;
use crate::step::Step;
use crate::ui::{section, specimen, specimens};
mod asking;
+2 -1
View File
@@ -44,7 +44,7 @@ mod typography;
use gpui::{AnyElement, App, Window};
use crate::script::Step;
use crate::step::Step;
pub struct Page {
pub number: u8,
@@ -53,6 +53,7 @@ pub struct Page {
pub summary: &'static str,
pub render: fn(&mut Window, &mut App) -> AnyElement,
/// Interactions shot after the static pages.
#[cfg_attr(target_family = "wasm", allow(dead_code))]
pub script: &'static [Step],
}
+1 -1
View File
@@ -6,7 +6,7 @@ mod progress;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 11,
+1 -1
View File
@@ -6,7 +6,7 @@ mod tabs;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 7,
+1 -1
View File
@@ -4,7 +4,7 @@ mod flows;
mod help;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 37,
+5 -19
View File
@@ -1,5 +1,3 @@
use std::path::Path;
use ely_gpui_component::{
buttons::{Button, ButtonVariant, IconButton},
forms::{Input, TextInput},
@@ -14,24 +12,12 @@ use gpui::{
use crate::{
probe::probe,
ui::{keep, row, section, set, specimen},
ui::{keep, picture, row, section, set, specimen},
};
const PHOTOS: [(&str, &str); 2] = [
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes.jpg"
),
"Dunes at first light",
),
(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
),
"An atrium, noon",
),
(asset!("dunes.jpg"), "Dunes at first light"),
(asset!("atrium.jpg"), "An atrium, noon"),
];
pub fn lightbox(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
@@ -46,7 +32,7 @@ pub fn lightbox(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
.h_32()
.cursor_pointer()
.child(
Image::new(("thumb-image", ix), Path::new(*path))
Image::new(("thumb-image", ix), picture(*path))
.fit(ObjectFit::Cover)
.size_full(),
)
@@ -57,7 +43,7 @@ pub fn lightbox(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let (step, close) = (shown.clone(), shown.clone());
Lightbox::new(
"lightbox",
PHOTOS.map(|(path, caption)| Slide::new(Path::new(path), caption)),
PHOTOS.map(|(path, caption)| Slide::new(picture(path), caption)),
at,
move |_, cx| set(&close, None, cx),
)
+1 -1
View File
@@ -5,7 +5,7 @@ mod guides;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 9,
+1 -1
View File
@@ -4,7 +4,7 @@ mod parts;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 1,
+3 -6
View File
@@ -15,13 +15,10 @@ use gpui::{
use crate::{
probe::probe,
ui::{blocked, code, row, section, specimen, specimens},
ui::{blocked, code, picture, row, section, specimen, specimens},
};
const ATRIUM: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
);
const ATRIUM: &str = asset!("atrium.jpg");
fn counter(window: &mut Window, cx: &mut App, key: &'static str) -> gpui::Entity<u32> {
window.use_keyed_state(key, cx, |_, _| 0u32)
@@ -104,7 +101,7 @@ pub fn image(cx: &App) -> impl IntoElement + use<> {
specimens()
.child(specimen(
"loaded",
tile(Image::new("img-atrium", Path::new(ATRIUM)), cx),
tile(Image::new("img-atrium", picture(ATRIUM)), cx),
cx,
))
.child(specimen(
+1 -1
View File
@@ -14,7 +14,7 @@ mod tasks;
mod time;
use super::Page;
use crate::{script::Step, ui::keep};
use crate::{step::Step, ui::keep};
pub const PAGE: Page = Page {
number: 31,
+2 -1
View File
@@ -1,7 +1,8 @@
use std::time::{Duration, Instant};
use std::time::Duration;
use ely_gpui_component::project::{DatabaseView, PomodoroTimer, Status, TimeEntry, TimeTracker};
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use web_time::Instant;
use super::{board, quiet};
use crate::{
+1 -1
View File
@@ -4,7 +4,7 @@ mod pages;
mod window;
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 35,
+1 -1
View File
@@ -7,7 +7,7 @@ mod windows;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub use windows::{open_about, open_managed};
pub const PAGE: Page = Page {
+23 -21
View File
@@ -1,5 +1,3 @@
use std::path::Path;
use ely_gpui_component::{
buttons::{Button, ButtonVariant, IconButton},
primitives::{IconName, Image},
@@ -17,17 +15,11 @@ use gpui::{
use super::chrome::window_frame;
use crate::{
probe::{Opened, probe},
ui::{code, row, section, specimen},
ui::{code, own_window, picture, row, section, specimen},
};
const DUNES: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/dunes.jpg"
);
const ATRIUM: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/gallery/assets/atrium.jpg"
);
const DUNES: &str = asset!("dunes.jpg");
const ATRIUM: &str = asset!("atrium.jpg");
fn about() -> AboutDialog {
AboutDialog::new("Ely", "0.1.0 (2026.09)")
@@ -88,10 +80,13 @@ pub fn splash_screen(cx: &App) -> impl IntoElement + use<> {
.child(splash().progress(Some(0.62))),
cx,
))
.child(trigger("splash-open", "Show splash window", |cx| {
let result = splash().open(cx);
opened("splash", result, cx)
}))
.child(own_window(
trigger("splash-open", "Show splash window", |cx| {
let result = splash().open(cx);
opened("splash", result, cx)
}),
cx,
))
}
pub fn open_about(cx: &mut App) {
@@ -113,7 +108,10 @@ pub fn about_dialog(cx: &App) -> impl IntoElement + use<> {
.child(about()),
cx,
))
.child(trigger("about-open", "Open About window", open_about))
.child(own_window(
trigger("about-open", "Open About window", open_about),
cx,
))
}
struct Managed {
@@ -194,7 +192,10 @@ pub fn window_manager(cx: &mut App) -> impl IntoElement + use<> {
"Each new window cascades from the last; the manager knows them by name.",
cx,
)
.child(trigger("managed-open", "New window", open_managed))
.child(own_window(
trigger("managed-open", "New window", open_managed),
cx,
))
.child(
row().children(open.into_iter().enumerate().map(|(ix, (handle, title))| {
Button::new(("managed-focus", ix), title)
@@ -270,7 +271,7 @@ impl Render for Player {
.rounded(theme.radius(Radius::Md))
.overflow_hidden()
.child(
Image::new("player-art", Path::new(DUNES))
Image::new("player-art", picture(DUNES))
.fit(ObjectFit::Cover)
.size_full(),
),
@@ -309,7 +310,7 @@ impl Render for Picture {
.relative()
.size_full()
.child(
Image::new("pip-frame", Path::new(ATRIUM))
Image::new("pip-frame", picture(ATRIUM))
.fit(ObjectFit::Cover)
.size_full(),
)
@@ -334,7 +335,7 @@ pub fn mini_windows(cx: &App) -> impl IntoElement + use<> {
"Small windows above the rest. Hover for the bar; expand returns to the app.",
cx,
)
.child(
.child(own_window(
row()
.child(trigger("mini-open", "Mini player", |cx| {
let view = cx.new(|_| Player { playing: true });
@@ -358,7 +359,8 @@ pub fn mini_windows(cx: &App) -> impl IntoElement + use<> {
);
opened("pip", result, cx)
})),
)
cx,
))
.child(code(
"AlwaysOnTop is gpui's WindowOptions { kind: WindowKind::PopUp, .. }",
cx,
+1 -1
View File
@@ -5,7 +5,7 @@ mod grids;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 14,
+4 -8
View File
@@ -16,7 +16,7 @@ use gpui::{
use crate::{
probe::probe,
ui::{keep, section, set},
ui::{keep, set},
};
/// A build's output as a terminal printed it, colors and all.
@@ -84,7 +84,8 @@ fn field(key: &'static str, text: &str, window: &mut Window, cx: &mut App) -> En
})
}
pub fn live(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
/// The shell and the build's output, in tabs.
pub fn shell(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let tab = keep("terminal-tab", || SharedString::from("shell"), window, cx);
let shell = keep("terminal-shell-choice", || (0usize, 0usize), window, cx);
let (now_tab, (now_shell, start)) = (tab.read(cx).clone(), *shell.read(cx));
@@ -155,12 +156,7 @@ pub fn live(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
None => find,
};
let theme = cx.theme();
section(
"Terminal / TerminalTabs / TerminalSplit / TerminalToolbar / ShellSelector / TerminalSearch / TerminalLink",
"A real shell on a pseudo-terminal, drawn cell by cell in the theme's sixteen colors. Tabs hold shells and output; split for another shell beside it. Find lights every match through the scrollback. Cmd-press a link or a path:line.",
cx,
)
.child(
div().child(
div()
.w(px(840.))
.rounded(theme.radius(Radius::Md))
+22 -2
View File
@@ -1,11 +1,12 @@
mod blocks;
#[cfg(not(target_family = "wasm"))]
mod live;
mod panels;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::{step::Step, ui::section};
pub const PAGE: Page = Page {
number: 18,
@@ -36,9 +37,28 @@ const SCRIPT: &[Step] = &[
Step::Rest,
];
/// A live shell natively; a browser runs no processes, so there it says so.
fn live(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let section = section(
"Terminal / TerminalTabs / TerminalSplit / TerminalToolbar / ShellSelector / TerminalSearch / TerminalLink",
"A real shell on a pseudo-terminal, drawn cell by cell in the theme's sixteen colors. Tabs hold shells and output; split for another shell beside it. Find lights every match through the scrollback. Cmd-press a link or a path:line.",
cx,
);
#[cfg(not(target_family = "wasm"))]
return section.child(live::shell(window, cx));
#[cfg(target_family = "wasm")]
{
let _ = window;
section.child(crate::ui::blocked(
"A browser starts no processes and has no pseudo-terminal, so no shell runs here, and alacritty's grid, which draws the build's output, does not build for the web. The blocks, colored output, logs and processes below draw without one.",
cx,
))
}
}
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
div()
.child(live::live(window, cx))
.child(live(window, cx))
.child(blocks::blocks(window, cx))
.child(blocks::ansi(cx))
.child(panels::logs(window, cx))
+1 -1
View File
@@ -14,7 +14,7 @@ mod importing;
mod platform;
use super::Page;
use crate::script::Step;
use crate::step::Step;
use crate::ui::{section, specimen, specimens};
pub const PAGE: Page = Page {
+1 -1
View File
@@ -11,7 +11,7 @@ mod inspection;
use super::Page;
use crate::probe::probe;
use crate::script::Step;
use crate::step::Step;
use crate::ui::section;
pub const PAGE: Page = Page {
+1 -1
View File
@@ -5,7 +5,7 @@ mod values;
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
use super::Page;
use crate::script::Step;
use crate::step::Step;
pub const PAGE: Page = Page {
number: 2,