use axum::{
Router,
http::header,
response::{IntoResponse, Response},
routing::get,
};
use crate::AppState;
const TABULATOR_JS: &str = include_str!("../assets/tabulator/tabulator.min.js");
const TABULATOR_CSS: &str = include_str!("../assets/tabulator/tabulator.min.css");
const APP_JS: &str = include_str!("../assets/app.js");
const APP_CSS: &str = include_str!("../assets/app.css");
const APPICON_SVG: &str = include_str!("../assets/kovra-appicon.svg");
const ICONMARK_SVG: &str = include_str!("../assets/kovra-iconmark.svg");
const MARK_COLOR_PNG: &[u8] = include_bytes!("../assets/kovra-mark-color.png");
const SORA_600: &[u8] = include_bytes!("../assets/fonts/sora-latin-600-normal.woff2");
const INTER_400: &[u8] = include_bytes!("../assets/fonts/inter-latin-400-normal.woff2");
const INTER_500: &[u8] = include_bytes!("../assets/fonts/inter-latin-500-normal.woff2");
const INTER_600: &[u8] = include_bytes!("../assets/fonts/inter-latin-600-normal.woff2");
const JS: &str = "text/javascript; charset=utf-8";
const CSS: &str = "text/css; charset=utf-8";
const SVG: &str = "image/svg+xml; charset=utf-8";
const PNG: &str = "image/png";
const WOFF2: &str = "font/woff2";
pub fn routes() -> Router<AppState> {
Router::new()
.route("/assets/tabulator/tabulator.min.js", get(tabulator_js))
.route("/assets/tabulator/tabulator.min.css", get(tabulator_css))
.route("/assets/app.js", get(app_js))
.route("/assets/app.css", get(app_css))
.route("/assets/kovra-appicon.svg", get(appicon_svg))
.route("/assets/kovra-iconmark.svg", get(iconmark_svg))
.route("/assets/kovra-mark-color.png", get(mark_color_png))
.route("/assets/fonts/sora-latin-600-normal.woff2", get(sora_600))
.route("/assets/fonts/inter-latin-400-normal.woff2", get(inter_400))
.route("/assets/fonts/inter-latin-500-normal.woff2", get(inter_500))
.route("/assets/fonts/inter-latin-600-normal.woff2", get(inter_600))
}
#[cfg(debug_assertions)]
fn dev_disk(name: &str) -> Option<String> {
let dir = std::env::var_os("KOVRA_WEBUI_DEV")?;
std::fs::read_to_string(std::path::Path::new(&dir).join(name)).ok()
}
fn text_asset(content_type: &'static str, embedded: &'static str, _name: &str) -> Response {
#[cfg(debug_assertions)]
if let Some(body) = dev_disk(_name) {
return (
[
(header::CONTENT_TYPE, content_type),
(header::CACHE_CONTROL, "no-store"),
],
body,
)
.into_response();
}
asset(content_type, embedded).into_response()
}
fn asset(content_type: &'static str, body: &'static str) -> impl IntoResponse {
(
[
(header::CONTENT_TYPE, content_type),
(header::CACHE_CONTROL, "no-store"),
],
body,
)
}
fn binary(content_type: &'static str, body: &'static [u8]) -> impl IntoResponse {
(
[
(header::CONTENT_TYPE, content_type),
(header::CACHE_CONTROL, "no-store"),
],
body,
)
}
async fn tabulator_js() -> impl IntoResponse {
asset(JS, TABULATOR_JS)
}
async fn tabulator_css() -> impl IntoResponse {
asset(CSS, TABULATOR_CSS)
}
async fn app_js() -> Response {
text_asset(JS, APP_JS, "app.js")
}
async fn app_css() -> Response {
text_asset(CSS, APP_CSS, "app.css")
}
async fn appicon_svg() -> Response {
text_asset(SVG, APPICON_SVG, "kovra-appicon.svg")
}
async fn iconmark_svg() -> Response {
text_asset(SVG, ICONMARK_SVG, "kovra-iconmark.svg")
}
async fn mark_color_png() -> impl IntoResponse {
binary(PNG, MARK_COLOR_PNG)
}
async fn sora_600() -> impl IntoResponse {
binary(WOFF2, SORA_600)
}
async fn inter_400() -> impl IntoResponse {
binary(WOFF2, INTER_400)
}
async fn inter_500() -> impl IntoResponse {
binary(WOFF2, INTER_500)
}
async fn inter_600() -> impl IntoResponse {
binary(WOFF2, INTER_600)
}