ssr bug fix
This commit is contained in:
@@ -13,78 +13,72 @@ pub struct Project {
|
|||||||
pub code_url: String,
|
pub code_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deine vordefinierte Liste
|
||||||
fn get_all_projects() -> Vec<Project> {
|
fn get_all_projects() -> Vec<Project> {
|
||||||
vec![
|
vec![
|
||||||
Project {
|
Project {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "Malxte.de Rust Website".into(),
|
title: "Bytemalte.de Website".into(),
|
||||||
description: "Eine voll in Rust mit Yew Programmierte Website mit allen Links und allem über mich.".into(),
|
description: "Meine persönliche Community-Plattform, gebaut mit Rust und Leptos.".into(),
|
||||||
image_url: "/assets/malxte_de.png".into(),
|
image_url: "/assets/malxte_de.png".into(),
|
||||||
download_url: "https://github.com/.../releases".into(), // Dein Link
|
download_url: "https://github.com/malxte/bytemalte_de/releases".into(),
|
||||||
code_url: "https://gitea.malxte.de/Bytemalte/malxte_de.git".into(), // Dein Code Link
|
code_url: "https://github.com/malxte/bytemalte_de".into(),
|
||||||
},
|
},
|
||||||
Project {
|
Project {
|
||||||
id: 2,
|
id: 2,
|
||||||
title: "Bytemalte.de Community Website".into(),
|
title: "Anderes Projekt".into(),
|
||||||
description: "Die Webseite auf der du dich gerade befindest, gebaut mit Leptos für die Bytemalte Community.".into(),
|
description: "Beschreibung deines zweiten Projekts hier.".into(),
|
||||||
image_url: "/assets/bytemalte_de.png".into(),
|
image_url: "/assets/bytemalte_de.png".into(),
|
||||||
download_url: "#".into(),
|
download_url: "#".into(),
|
||||||
code_url: "https://gitea.malxte.de/Bytemalte/bytemalte_de".into(),
|
|
||||||
},
|
|
||||||
Project {
|
|
||||||
id: 3,
|
|
||||||
title: "Logo Design".into(),
|
|
||||||
description: "Das offizielle Bytemalte Logo. (Nicht frei verwendbar!)".into(),
|
|
||||||
image_url: "/assets/Logo.jpg".into(), // JPG geht natürlich auch
|
|
||||||
download_url: "/assets/Logo.jpg".into(), // Man kann Bilder auch direkt verlinken
|
|
||||||
code_url: "#".into(),
|
code_url: "#".into(),
|
||||||
},
|
},
|
||||||
|
// Füge hier weitere hinzu...
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn HomePage() -> impl IntoView {
|
pub fn HomePage() -> impl IntoView {
|
||||||
let (projects, set_projects) = signal(Vec::<Project>::new());
|
let items_per_page = 3;
|
||||||
|
let all_data = get_all_projects();
|
||||||
|
|
||||||
|
// WICHTIG: Wir laden die erste Seite direkt hier für das SSR!
|
||||||
|
let initial_projects = all_data.iter().take(items_per_page).cloned().collect::<Vec<_>>();
|
||||||
|
let has_more_initially = all_data.len() > items_per_page;
|
||||||
|
|
||||||
|
let (projects, set_projects) = signal(initial_projects);
|
||||||
let (page, set_page) = signal(1);
|
let (page, set_page) = signal(1);
|
||||||
let (loading, set_loading) = signal(false);
|
let (loading, set_loading) = signal(false);
|
||||||
let (all_loaded, set_all_loaded) = signal(false);
|
let (all_loaded, set_all_loaded) = signal(!has_more_initially);
|
||||||
|
|
||||||
let items_per_page = 3; // Wie viele Projekte pro Scroll-Schub geladen werden
|
|
||||||
let sentinel = NodeRef::<Div>::new();
|
let sentinel = NodeRef::<Div>::new();
|
||||||
|
|
||||||
let fetch_projects = move |p: usize| {
|
let fetch_projects = move |p: usize| {
|
||||||
if all_loaded.get_untracked() { return; }
|
if all_loaded.get_untracked() || loading.get_untracked() { return; }
|
||||||
|
|
||||||
set_loading.set(true);
|
set_loading.set(true);
|
||||||
|
let all_my_projects = get_all_projects();
|
||||||
// Simuliert eine kurze Ladezeit für das Feeling
|
let start = p * items_per_page;
|
||||||
|
let end = (start + items_per_page).min(all_my_projects.len());
|
||||||
|
|
||||||
|
if start >= all_my_projects.len() {
|
||||||
|
set_all_loaded.set(true);
|
||||||
|
set_loading.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simuliere Netzwerk-Delay für den Spinner
|
||||||
set_timeout(move || {
|
set_timeout(move || {
|
||||||
let all_my_projects = get_all_projects();
|
let slice = all_my_projects[start..end].to_vec();
|
||||||
let start = (p - 1) * items_per_page;
|
set_projects.update(|projs| projs.extend(slice));
|
||||||
let end = (start + items_per_page).min(all_my_projects.len());
|
|
||||||
|
|
||||||
if start >= all_my_projects.len() {
|
|
||||||
set_all_loaded.set(true);
|
|
||||||
set_loading.set(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let slice = &all_my_projects[start..end];
|
|
||||||
set_projects.update(|projs| projs.extend(slice.to_vec()));
|
|
||||||
|
|
||||||
if end >= all_my_projects.len() {
|
if end >= all_my_projects.len() {
|
||||||
set_all_loaded.set(true);
|
set_all_loaded.set(true);
|
||||||
}
|
}
|
||||||
set_loading.set(false);
|
set_loading.set(false);
|
||||||
}, std::time::Duration::from_millis(400));
|
}, std::time::Duration::from_millis(300));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialer Load
|
// Scroll-Event-Listener (Nur im Browser aktiv)
|
||||||
Effect::new(move |_| {
|
|
||||||
fetch_projects(page.get());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Scroll-Event-Listener
|
|
||||||
Effect::new(move |_| {
|
Effect::new(move |_| {
|
||||||
let w = window();
|
let w = window();
|
||||||
let w_clone = w.clone();
|
let w_clone = w.clone();
|
||||||
@@ -98,9 +92,10 @@ pub fn HomePage() -> impl IntoView {
|
|||||||
let inner_height = w_clone.inner_height().unwrap().as_f64().unwrap_or(0.0);
|
let inner_height = w_clone.inner_height().unwrap().as_f64().unwrap_or(0.0);
|
||||||
let total_height = el.offset_height() as f64;
|
let total_height = el.offset_height() as f64;
|
||||||
|
|
||||||
if scroll_y + inner_height >= total_height - 200.0 {
|
if scroll_y + inner_height >= total_height - 250.0 {
|
||||||
set_page.update(|p| *p += 1);
|
let next_page = page.get_untracked();
|
||||||
fetch_projects(page.get_untracked());
|
set_page.set(next_page + 1);
|
||||||
|
fetch_projects(next_page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +107,7 @@ pub fn HomePage() -> impl IntoView {
|
|||||||
<div class="home-container">
|
<div class="home-container">
|
||||||
<header class="home-hero">
|
<header class="home-hero">
|
||||||
<h1>"Bytemalte."</h1>
|
<h1>"Bytemalte."</h1>
|
||||||
<p>"Entdecke meine neuesten Projekte - Bytemalte."</p>
|
<p>"Entdecke meine neuesten Projekte."</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="projects-grid">
|
<main class="projects-grid">
|
||||||
@@ -140,14 +135,10 @@ pub fn HomePage() -> impl IntoView {
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div node_ref=sentinel class="loading-trigger">
|
<div node_ref=sentinel class="loading-trigger">
|
||||||
{move || {
|
{move || match (loading.get(), all_loaded.get()) {
|
||||||
if loading.get() {
|
(true, _) => view! { <div class="spinner"></div> }.into_any(),
|
||||||
view! { <div class="spinner"></div> }.into_any()
|
(_, true) => view! { <p class="end-msg">"Das waren alle Projekte ✨"</p> }.into_any(),
|
||||||
} else if all_loaded.get() {
|
_ => view! { <p>"Scrollen für mehr"</p> }.into_any(),
|
||||||
view! { <p class="end-msg">"Das waren alle Projekte ✨"</p> }.into_any()
|
|
||||||
} else {
|
|
||||||
view! { <p>"Mehr laden..."</p> }.into_any()
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user