use gloo::console::log; use gloo_net::http::Request; use itertools::Itertools; use serde::Deserialize; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::{ops::Deref, sync::Arc}; use wasm_bindgen::*; use web_sys::{EventTarget, HtmlInputElement}; use yew::prelude::*; //TODO: we should import this from the indexer #[derive(Debug, Clone, Deserialize)] pub struct IndexedResource { url: String, title: String, description: String, priority: u32, word: Arc, } //We implement PartialEq, Eq and Hash to ignore the priority field. impl PartialEq for IndexedResource { fn eq(&self, other: &Self) -> bool { self.url == other.url && self.word == other.word } } impl Eq for IndexedResource {} impl PartialOrd for IndexedResource { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for IndexedResource { fn cmp(&self, other: &Self) -> Ordering { self.priority.cmp(&other.priority).reverse() } } impl Hash for IndexedResource { fn hash(&self, state: &mut H) { self.url.hash(state); self.word.hash(state); } } #[derive(Properties, Clone, PartialEq, Eq)] pub struct ResultComponentProps { result: IndexedResource, } #[function_component(ResultComponent)] fn result_component(props: &ResultComponentProps) -> Html { html! { {props.result.url.clone()}{"--"}{props.result.title.clone()}{"----"}{props.result.description.clone()}{format!("PRIO: {}", props.result.priority)} } } #[derive(Debug, Clone)] struct State { pub search_query: String, pub results: Option>, //TODO: some loading? } #[function_component(OSSE)] fn osse() -> Html { let state = use_state(|| State { search_query: "".to_string(), results: None, }); let display_results = |maybe_results: &Option>| -> Html { let maybe_results = maybe_results.as_ref(); if maybe_results.is_none() { return html! {}; } let results = maybe_results.unwrap(); if !results.is_empty() { results .iter() .sorted() .map(|r| { html! {
} }) .collect::() } else { html! {

{"No results!"}

} } }; let search_query_changed = { let cloned_state = state.clone(); Callback::from(move |event: InputEvent| { let target: EventTarget = event .target() .expect("Event should have a target when dispatched"); let input = target.unchecked_into::().value(); log!("Input changed: {}", &input); let mut state = cloned_state.deref().clone(); state.search_query = input; cloned_state.set(state); }) }; let on_submit = { let cloned_state = state.clone(); Callback::from(move |event: FocusEvent| { event.prevent_default(); let state = cloned_state.deref().clone(); //fetch { let cloned_state = cloned_state.clone(); wasm_bindgen_futures::spawn_local(async move { let mut state = cloned_state.deref().clone(); //TODO: what if its on another host let endpoint = format!("http://127.0.0.1:4444/search/{}", &state.search_query); let fetched_results = Request::get(endpoint.as_str()).send().await.unwrap(); let fetched_json: Vec = match fetched_results.json().await { Err(e) => panic!("Im panic: {}", e), Ok(json) => json, }; state.results = Some(fetched_json); cloned_state.set(state); }); } log!("Submit: {}", state.search_query); }) }; let curr_state = state.deref().to_owned(); html! { <>
//SET AT MIDDLE OF VIEWPORT IF NO SEARCHING AND TOP 25% IF SEARCHING
{"OSSE"}

{"Your favorite independent search engine."}

{display_results(&curr_state.results)}
} } #[function_component(App)] fn app() -> Html { html! { <> } } //Your favorite search engine in navbar //Search in middle fn main() { yew::start_app::(); }