Feat: simple html frontend
This commit is contained in:
parent
65401700c0
commit
e496324049
9 changed files with 253 additions and 5 deletions
|
@ -1,27 +1,45 @@
|
|||
use axum::{extract::Query, routing::get, Router};
|
||||
use cairo::{Context, Format, ImageSurface};
|
||||
use serde::Deserialize;
|
||||
use serde::{de, Deserialize};
|
||||
|
||||
use crate::{polygon, SharedState};
|
||||
use crate::{color::Color, polygon, SharedState};
|
||||
|
||||
fn default_as_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deserialize_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let s: &str = de::Deserialize::deserialize(deserializer)?;
|
||||
|
||||
match s {
|
||||
"true" | "on" => Ok(true),
|
||||
"false" | "off" => Ok(false),
|
||||
_ => Err(de::Error::unknown_variant(
|
||||
s,
|
||||
&["true", "on", "false", "off"],
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ImageProperties {
|
||||
#[serde(default = "default_as_false")]
|
||||
#[serde(deserialize_with = "deserialize_bool")]
|
||||
dark_mode: bool,
|
||||
background_color: Option<Color>,
|
||||
}
|
||||
|
||||
async fn handler(Query(properties): Query<ImageProperties>) -> impl axum::response::IntoResponse {
|
||||
let surface = ImageSurface::create(Format::ARgb32, 400, 400).unwrap();
|
||||
let context = Context::new(&surface).unwrap();
|
||||
|
||||
if properties.dark_mode {
|
||||
context.set_source_rgb(0.0, 0.0, 0.0);
|
||||
if let Some(c) = properties.background_color {
|
||||
context.set_source_rgb(c.r as f64 / 255.0, c.g as f64 / 255.0, c.b as f64 / 255.0);
|
||||
} else {
|
||||
context.set_source_rgb(1.0, 1.0, 1.0);
|
||||
context.set_source_rgba(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
context.paint().unwrap();
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
pub mod favicon;
|
||||
pub mod logo;
|
||||
pub mod static_files;
|
||||
|
|
56
src/routes/static_files.rs
Normal file
56
src/routes/static_files.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use axum::{
|
||||
body::{boxed, Full},
|
||||
http::{header, StatusCode, Uri},
|
||||
response::{IntoResponse, Response},
|
||||
Router,
|
||||
};
|
||||
use rust_embed::{EmbeddedFile, RustEmbed};
|
||||
|
||||
use crate::SharedState;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "static"]
|
||||
struct StaticFiles;
|
||||
|
||||
async fn static_files(uri: Uri) -> impl IntoResponse {
|
||||
let path = uri.path().trim_start_matches('/');
|
||||
|
||||
match StaticFiles::get(path) {
|
||||
Some(file) => response(file, path),
|
||||
None => {
|
||||
if uri.path() == "/" {
|
||||
index()
|
||||
} else {
|
||||
not_found()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn index() -> Response {
|
||||
match StaticFiles::get("index.html") {
|
||||
Some(file) => response(file, "index.html"),
|
||||
None => not_found(),
|
||||
}
|
||||
}
|
||||
|
||||
fn response(file: EmbeddedFile, path: &str) -> Response {
|
||||
let body = boxed(Full::from(file.data));
|
||||
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
||||
|
||||
Response::builder()
|
||||
.header(header::CONTENT_TYPE, mime.as_ref())
|
||||
.body(body)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn not_found() -> Response {
|
||||
Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(boxed(Full::from("404")))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn routes() -> Router<SharedState> {
|
||||
Router::new().fallback(static_files)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue