new hashtag filter option
All checks were successful
Android Build Final Fixed / build-android (push) Successful in 7m46s
All checks were successful
Android Build Final Fixed / build-android (push) Successful in 7m46s
This commit is contained in:
@@ -7,8 +7,8 @@ use yew::prelude::*;
|
||||
// Tauri 'invoke' Funktion deklarieren
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])]
|
||||
async fn invoke(cmd: &str, args: JsValue) -> JsValue;
|
||||
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"], catch)]
|
||||
async fn invoke(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
|
||||
// Wir definieren Post lokal, damit Yew weiß, wie die JSON-Daten vom Backend aussehen
|
||||
@@ -24,13 +24,17 @@ pub struct Post {
|
||||
pub fn home() -> Html {
|
||||
let posts = use_state(|| None::<Vec<Post>>);
|
||||
let error = use_state(|| false);
|
||||
let hashtag_input = use_state(|| String::new());
|
||||
let active_tags = use_state(Vec::<String>::new);
|
||||
|
||||
let load_posts = {
|
||||
let posts = posts.clone();
|
||||
let error = error.clone();
|
||||
let active_tags = active_tags.clone();
|
||||
Callback::from(move |_e: MouseEvent| {
|
||||
let posts = posts.clone();
|
||||
let error = error.clone();
|
||||
let tags = (*active_tags).clone();
|
||||
|
||||
// UI zurücksetzen & Scrollen
|
||||
posts.set(None);
|
||||
@@ -43,14 +47,25 @@ pub fn home() -> Html {
|
||||
}
|
||||
|
||||
spawn_local(async move {
|
||||
// Daten vom Rust-Backend anfordern
|
||||
let res = invoke("fetch_nostr_posts", JsValue::NULL).await;
|
||||
#[derive(Serialize)]
|
||||
struct HashtagArgs {
|
||||
hashtags: Vec<String>,
|
||||
}
|
||||
let args = serde_wasm_bindgen::to_value(&HashtagArgs { hashtags: tags }).unwrap();
|
||||
|
||||
// JSON-Resultat in Vec<Post> umwandeln
|
||||
if let Ok(new_posts) = serde_wasm_bindgen::from_value::<Vec<Post>>(res) {
|
||||
posts.set(Some(new_posts));
|
||||
} else {
|
||||
error.set(true);
|
||||
// Daten vom Rust-Backend anfordern
|
||||
match invoke("fetch_nostr_posts", args).await {
|
||||
Ok(res) => {
|
||||
// JSON-Resultat in Vec<Post> umwandeln
|
||||
if let Ok(new_posts) = serde_wasm_bindgen::from_value::<Vec<Post>>(res) {
|
||||
posts.set(Some(new_posts));
|
||||
} else {
|
||||
error.set(true);
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
@@ -68,10 +83,73 @@ pub fn home() -> Html {
|
||||
html! {
|
||||
<div class="feed-container">
|
||||
<div class="feed-header">
|
||||
<h1 class="feed-title">{"✨ Entdecken"}</h1>
|
||||
<button class="reload-btn" onclick={load_posts.clone()}>
|
||||
{"🔄"}
|
||||
</button>
|
||||
<div class="header-main">
|
||||
<h1 class="feed-title">{"✨ Entdecken"}</h1>
|
||||
<button class="reload-btn" onclick={load_posts.clone()}>
|
||||
{"🔄"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hashtag-section">
|
||||
<div class="hashtag-input-row">
|
||||
<input
|
||||
type="text"
|
||||
class="hashtag-input"
|
||||
placeholder="Tags hinzufügen (z.B. bitcoin, rust)..."
|
||||
value={(*hashtag_input).clone()}
|
||||
oninput={
|
||||
let hashtag_input = hashtag_input.clone();
|
||||
move |e: InputEvent| {
|
||||
let target: web_sys::HtmlInputElement = e.target_unchecked_into();
|
||||
hashtag_input.set(target.value());
|
||||
}
|
||||
}
|
||||
onkeydown={
|
||||
let hashtag_input = hashtag_input.clone();
|
||||
let active_tags = active_tags.clone();
|
||||
let load_posts = load_posts.clone();
|
||||
move |e: KeyboardEvent| {
|
||||
if e.key() == "Enter" {
|
||||
let val = (*hashtag_input).trim().to_string();
|
||||
if !val.is_empty() {
|
||||
let mut tags = (*active_tags).clone();
|
||||
// Mehrere Tags per Komma trennen
|
||||
for t in val.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()) {
|
||||
if !tags.contains(&t.to_string()) {
|
||||
tags.push(t.to_string());
|
||||
}
|
||||
}
|
||||
active_tags.set(tags);
|
||||
hashtag_input.set(String::new());
|
||||
load_posts.emit(MouseEvent::new("click").unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
if !active_tags.is_empty() {
|
||||
<div class="tag-chips">
|
||||
{ for active_tags.iter().map(|t| {
|
||||
let t_clone = t.clone();
|
||||
let active_tags = active_tags.clone();
|
||||
let load_posts = load_posts.clone();
|
||||
let remove = move |_| {
|
||||
let mut tags = (*active_tags).clone();
|
||||
tags.retain(|x| x != &t_clone);
|
||||
active_tags.set(tags);
|
||||
load_posts.emit(MouseEvent::new("click").unwrap());
|
||||
};
|
||||
html! {
|
||||
<span class="tag-chip" onclick={remove}>
|
||||
{ format!("#{}", t) }
|
||||
<span class="tag-remove">{"×"}</span>
|
||||
</span>
|
||||
}
|
||||
}) }
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user