diff options
Diffstat (limited to 'src/ui.rs')
| -rw-r--r-- | src/ui.rs | 34 |
1 files changed, 26 insertions, 8 deletions
@@ -1,24 +1,24 @@ use axum::{ - extract::Path, + extract::{Path, State}, http::{header, StatusCode}, - response::{IntoResponse, Response}, + response::{IntoResponse, Redirect, Response}, routing::get, Router, }; use mime_guess::Mime; use rust_embed::EmbeddedFile; +use crate::{app::App, channel, error::Internal, login::Login}; + #[derive(rust_embed::Embed)] #[folder = "hi-ui/build"] struct Assets; -pub fn router<S>() -> Router<S> -where - S: Clone + Send + Sync + 'static, -{ +pub fn router() -> Router<App> { Router::new() .route("/*path", get(asset)) .route("/", get(root)) + .route("/ch/:channel", get(channel)) } async fn asset(Path(path): Path<String>) -> Result<Asset, NotFound<String>> { @@ -29,8 +29,24 @@ async fn asset(Path(path): Path<String>) -> Result<Asset, NotFound<String>> { .ok_or(NotFound(format!("not found: {path}"))) } -async fn root() -> impl IntoResponse { - asset(Path(String::from("index.html"))).await +async fn root() -> Result<Asset, Internal> { + // "not found" in this case really is an internal error, as it should + // never happen. `index.html` is a known-valid path. + Ok(asset(Path(String::from("index.html"))).await?) +} + +async fn channel( + State(app): State<App>, + login: Option<Login>, + Path(channel): Path<channel::Id>, +) -> Result<impl IntoResponse, Internal> { + Ok(if login.is_none() { + Redirect::temporary("/").into_response() + } else if app.channels().get(&channel).await?.is_none() { + NotFound(root().await?).into_response() + } else { + root().await?.into_response() + }) } struct Asset(Mime, EmbeddedFile); @@ -47,6 +63,8 @@ impl IntoResponse for Asset { } } +#[derive(Debug, thiserror::Error)] +#[error("{0}")] struct NotFound<E>(pub E); impl<E> IntoResponse for NotFound<E> |
