/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin */ use super::{ error::MyResult, layout::{trs, DynLayoutPage, LayoutPage}, node::{DatabaseNodeUserDataExt, NodeCard}, }; use crate::{api::AcceptJson, locale::AcceptLanguage, logic::session::Session}; use anyhow::anyhow; use jellybase::{database::Database, locale::tr}; use jellycommon::{api::ApiSearchResponse, Visibility}; use rocket::{get, serde::json::Json, Either, State}; use std::time::Instant; #[get("/search?&")] pub async fn r_search<'a>( session: Session, db: &State, aj: AcceptJson, query: Option<&str>, page: Option, lang: AcceptLanguage, ) -> MyResult, Json>> { let AcceptLanguage(lang) = lang; let results = if let Some(query) = query { let timing = Instant::now(); let (count, ids) = db.search(query, 32, page.unwrap_or_default() * 32)?; let mut nodes = ids .into_iter() .map(|id| db.get_node_with_userdata(id, &session)) .collect::, anyhow::Error>>()?; nodes.retain(|(n, _)| n.visibility >= Visibility::Reduced); let search_dur = timing.elapsed(); Some((count, nodes, search_dur)) } else { None }; let query = query.unwrap_or_default().to_string(); Ok(if *aj { let Some((count, results, _)) = results else { Err(anyhow!("no query"))? }; Either::Right(Json(ApiSearchResponse { count, results })) } else { Either::Left(LayoutPage { title: tr(lang, "search.title").to_string(), class: Some("search"), content: markup::new! { h1 { @trs(&lang, "search.title") } form[action="", method="GET"] { input[type="text", name="query", placeholder=&*tr(lang, "search.placeholder"), value=&query]; input[type="submit", value="Search"]; } @if let Some((count, results, search_dur)) = &results { h2 { @trs(&lang, "search.results.title") } p.stats { @tr(lang, "search.results.stats").replace("{count}", &count.to_string()).replace("{dur}", &format!("{search_dur:?}")) } ul.children {@for (node, udata) in results.iter() { li { @NodeCard { node, udata, lang: &lang } } }} // TODO pagination } }, }) }) }