Aspirational examples for app developer contract.

This commit is contained in:
2026-03-21 17:05:25 -04:00
parent d4ff472a14
commit f59d519448
8 changed files with 866 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
//! Aspirational RUIN app API for runtime-integrated filesystem and network I/O.
//!
//! Intentionally non-compiling; this is a design sketch.
use ruin::prelude::*;
#[ruin_runtime::async_main]
async fn main() -> ruin::Result<()> {
App::new()
.window(Window::new().title("RUIN Runtime I/O").size(1280.0, 820.0))
.mount::<RuntimeIoExample>()
.run()
.await
}
#[component]
fn RuntimeIoExample() -> impl View {
let manifest_path = use_signal(|| "./Cargo.toml".to_string());
let release_url =
use_signal(|| "https://api.github.com/repos/wtemple/ruin/releases/latest".to_string());
let manifest = use_resource(move || {
let path = manifest_path.get();
async move { ruin_runtime::fs::read_to_string(path).await }
});
let release = use_resource(move || {
let url = release_url.get();
async move { ruin_http::get_json::<ReleaseSummary>(&url).await }
});
let save_snapshot = use_action(move |_| {
let manifest = manifest.latest_cloned();
async move {
let manifest = manifest.ok_or_else(|| anyhow!("manifest is not loaded yet"))?;
ruin_runtime::fs::write("./tmp/manifest-snapshot.toml", manifest).await?;
Ok::<_, anyhow::Error>(())
}
});
use_async_effect(move || {
let url = release_url.get();
async move {
tracing::info!(%url, "release endpoint changed");
Ok::<_, anyhow::Error>(())
}
});
view! {
row(fill = true, gap = 20, padding = 20) {
block(fill = true, gap = 12) {
text(role = TextRole::Heading(1), size = 26, weight = FontWeight::Semibold) {
"Filesystem"
}
text_input(value = manifest_path, placeholder = "./Cargo.toml") {}
match manifest.read() {
Pending => view! { ProgressSpinner(label = "Reading file...") {} },
Ready(Ok(contents)) => view! {
column(gap = 12) {
button(
on_press = save_snapshot.dispatcher(),
disabled = save_snapshot.pending(),
) {
"Save snapshot"
}
CodeBlock(language = "toml") { contents }
}
},
Ready(Err(error)) => view! {
ErrorPanel(title = "Failed to read file", detail = error.to_string()) {}
},
}
}
block(fill = true, gap = 12) {
text(role = TextRole::Heading(1), size = 26, weight = FontWeight::Semibold) {
"Network"
}
text_input(value = release_url, placeholder = "https://...") {}
match release.read() {
Pending => view! { ProgressSpinner(label = "Fetching release summary...") {} },
Ready(Ok(release)) => view! {
column(gap = 8) {
text(size = 20, weight = FontWeight::Semibold) { release.name.clone() }
text(color = colors::muted()) { release.published_at.clone() }
text { release.notes.clone() }
}
},
Ready(Err(error)) => view! {
ErrorPanel(title = "Failed to fetch release", detail = error.to_string()) {}
},
}
}
}
}
}
struct ReleaseSummary {
name: String,
published_at: String,
notes: String,
}