//! 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::() .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::(&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, }