- Markiere Dienste/Lesezeichen im Adminbereich als Favorit – sie erscheinen dann hier.
-
- ) : null}
+ {layout.grid.length === 0 ? (
+
+ Markiere Dienste/Lesezeichen im Adminbereich als Favorit – sie erscheinen dann hier.
+
+ ) : null}
+ >
+ ) : (
+ // Platzhalter statt des Rasters, solange noch nicht ALLE nötigen
+ // Daten da sind (siehe isReady-Kommentar an der Prop weiter oben) -
+ // verhindert, dass z. B. "Zuletzt besucht" erst nachträglich
+ // auftaucht und alle Icons danach verschiebt (siehe Bugreport).
+
+ {Array.from({ length: 8 }).map((_, i) => (
+
+
+
+
+ ))}
+
+ )}
{/* Dock */}
@@ -588,7 +614,9 @@ export function MobileAndroidHome({
className="flex min-h-[4.5rem] min-w-[5rem] items-center gap-3 rounded-[28px] border border-white/40
bg-white/70 px-4 py-3 shadow-xl backdrop-blur-xl dark:border-white/10 dark:bg-neutral-900/70"
>
- {layout.dock.length === 0 ? (
+ {!isReady ? (
+
+ ) : layout.dock.length === 0 ? (
Icon hierher ziehen zum Anheften
) : (
layout.dock.map((slot) => renderTile(slot, "dock", "small"))
diff --git a/apps/frontend/src/routes/HomePage.tsx b/apps/frontend/src/routes/HomePage.tsx
index f18bf4b..22f425e 100644
--- a/apps/frontend/src/routes/HomePage.tsx
+++ b/apps/frontend/src/routes/HomePage.tsx
@@ -128,9 +128,9 @@ export function HomePage() {
const { data: services, isLoading: servicesLoading, isError: servicesError } = useServices();
const { data: bookmarks, isLoading: bookmarksLoading } = useBookmarks();
const { data: devices } = useDevices();
- const { data: settings } = useSettings();
- const { data: categories } = useCategories();
- const { data: recentVisits } = useRecentVisits();
+ const { data: settings, isLoading: settingsLoading } = useSettings();
+ const { data: categories, isLoading: categoriesLoading } = useCategories();
+ const { data: recentVisits, isLoading: recentVisitsLoading } = useRecentVisits();
const { data: readLaterItems } = useReadLater();
const inputRef = useRef(null);
const searchContainerRef = useRef(null);
@@ -334,6 +334,17 @@ export function HomePage() {
}, [settings?.mobileHomeStyle]);
const effectiveMobileHomeStyle = settings?.mobileHomeStyle ?? cachedMobileHomeStyle ?? "classic";
const useAndroidHome = isMobile && effectiveMobileHomeStyle === "android";
+ // WICHTIG: Dienste/Lesezeichen/Kategorien/"Zuletzt besucht"/Einstellungen
+ // laden über getrennte, unabhängig voneinander abgeschlossene
+ // Netzwerk-Anfragen - kämen sie einzeln nacheinander im Raster an, würde
+ // z. B. die "Zuletzt besucht"-Kachel nachträglich auftauchen und alle
+ // Icons danach verschieben (genau das im Bugreport beschriebene
+ // "Verschieben, weil manche Icons schneller da sind als andere"). Daher
+ // wird das komplette Raster erst gerendert, wenn ALLE beteiligten
+ // Abfragen mindestens einmal durch sind - dann in einem Rutsch, ohne
+ // Nachrücken einzelner Kacheln.
+ const androidHomeDataReady =
+ !servicesLoading && !bookmarksLoading && !categoriesLoading && !recentVisitsLoading && !settingsLoading;
const addReadLaterMutation = useMutation({
mutationFn: (url: string) => saveReadLaterRequest(url),
@@ -354,6 +365,7 @@ export function HomePage() {
onToggleFavorite={(item) => toggleFavorite.mutate(item)}
onAddReadLater={(url) => addReadLaterMutation.mutate(url)}
isOnline={isOnline}
+ isReady={androidHomeDataReady}
/>
);
}