use super::{AppState, asset};
use axum::Router;
use axum::extract::State;
use axum::http::{HeaderMap, HeaderValue, header};
use axum::response::{IntoResponse, Response};
use axum::routing::get;
use std::sync::Arc;
const MODULES: [(&str, &str); 6] = [
("/_zeyn/share.js", include_str!("../../assets/share.js")),
("/_zeyn/chips.js", include_str!("../../assets/chips.js")),
("/_zeyn/preview.js", include_str!("../../assets/preview.js")),
(
"/_zeyn/reactions.js",
include_str!("../../assets/reactions.js"),
),
("/_zeyn/hero.js", include_str!("../../assets/hero.js")),
("/_zeyn/state.js", include_str!("../../assets/state.js")),
];
pub(super) const ASSETS: [&str; MODULES.len()] = {
let mut paths = [""; MODULES.len()];
let mut i = 0;
while i < MODULES.len() {
paths[i] = MODULES[i].0;
i += 1;
}
paths
};
pub(super) fn routes(mut router: Router<Arc<AppState>>) -> Router<Arc<AppState>> {
for (path, body) in MODULES {
router = router.route(
path,
get(move || async move { asset(body, "text/javascript; charset=utf-8") }),
);
}
router
.route("/_zeyn/prefs", get(prefs))
.route("/_zeyn/speculation.json", get(speculation))
}
async fn speculation(State(st): State<Arc<AppState>>) -> Response {
let base = st.prefix.trim_end_matches('/');
let rules = if st.prefetch == super::Prefetch::Moderate {
serde_json::json!({ "prefetch": [{
"source": "document",
"where": { "and": [
{ "href_matches": format!("{base}/*") },
{ "not": { "href_matches": format!("{base}/_zeyn/*") } },
{ "not": { "href_matches": format!("{base}/api/*") } },
{ "not": { "href_matches": "/*.*" } },
{ "not": { "selector_matches": "[data-zeyn-reload], [download], [target], [data-zeyn-no-prefetch], [data-zeyn-nav] a" } },
] },
"eagerness": "moderate",
}] })
} else {
serde_json::json!({})
};
let mut r = axum::Json(rules).into_response();
let h = r.headers_mut();
h.insert(
header::CONTENT_TYPE,
HeaderValue::from_static("application/speculationrules+json"),
);
h.insert(header::CACHE_CONTROL, HeaderValue::from_static("no-cache"));
r
}
async fn prefs(State(st): State<Arc<AppState>>, headers: HeaderMap) -> Response {
let allowed = st
.services
.get::<crate::prefs::ClientPrefs>()
.and_then(|p| p.allowed)
.is_some_and(|hook| hook(&headers));
let mut r = axum::Json(serde_json::json!({ "preferences": allowed })).into_response();
r.headers_mut()
.insert(header::CACHE_CONTROL, HeaderValue::from_static("no-store"));
r
}