generated from Dicken/dickendock
round68: Spaeter-lesen als Liste mit Datum/Uhrzeit statt Icon-Raster, Suche im Android-Design nutzt jetzt dieselbe Rangierfunktion wie das klassische Design
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
faPen,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import type { Category, Service, Bookmark, SearchResult } from "@launchpad/shared";
|
||||
import { rankSearchResults } from "@launchpad/shared";
|
||||
import { ResultsList, Button } from "@launchpad/ui";
|
||||
import { useHomeLayout, type HomeSlot, type ItemRef } from "../hooks/useHomeLayout.js";
|
||||
|
||||
@@ -83,6 +84,14 @@ function slotId(): string {
|
||||
return `slot-${Math.random().toString(36).slice(2, 10)}-${Date.now().toString(36)}`;
|
||||
}
|
||||
|
||||
function formatSavedAt(iso: string): string {
|
||||
const date = new Date(iso);
|
||||
if (Number.isNaN(date.getTime())) return "";
|
||||
const datePart = date.toLocaleDateString("de-DE", { day: "2-digit", month: "2-digit", year: "2-digit" });
|
||||
const timePart = date.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" });
|
||||
return `${datePart}, ${timePart}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reine Funktion, die aus dem Ist-Zustand (Layout) + der abgeschlossenen
|
||||
* Ziehgeste das NEUE Layout berechnet - bewusst ohne React-State-Zugriff,
|
||||
@@ -221,7 +230,7 @@ export interface MobileAndroidHomeProps {
|
||||
categoryColors: Record<string, string>;
|
||||
allSearchItems: SearchResult[];
|
||||
recentVisits: MinimalVisitItem[];
|
||||
readLaterItems: Array<{ id: string; url: string; displayName: string; favicon: string | null }>;
|
||||
readLaterItems: Array<{ id: string; url: string; displayName: string; favicon: string | null; savedAt: string }>;
|
||||
onOpen: (item: OpenTarget) => void;
|
||||
onToggleFavorite: (item: SearchResult) => void;
|
||||
onAddReadLater: (url: string) => void;
|
||||
@@ -383,12 +392,15 @@ export function MobileAndroidHome({
|
||||
}
|
||||
|
||||
const searchResults = useMemo(() => {
|
||||
if (query.trim().length === 0) return [];
|
||||
const q = query.toLowerCase();
|
||||
return allSearchItems
|
||||
.filter((i) => i.kind !== "device")
|
||||
.filter((i) => i.displayName.toLowerCase().includes(q) || i.alias?.some((a) => a.toLowerCase().includes(q)))
|
||||
.slice(0, 30);
|
||||
// WICHTIG (Bugfix): vorher stand hier ein eigener, simpler
|
||||
// .includes()-Filter, der zusätzlich Geräte komplett ausgeschlossen hat
|
||||
// - dadurch fand die Suche im Android-Design weniger als im normalen
|
||||
// Design (siehe Bugreport). Jetzt exakt dieselbe Rangier-Funktion wie im
|
||||
// klassischen Design (siehe HomePage.tsx), inklusive Geräten - ein Klick
|
||||
// auf ein Gerät bleibt trotzdem ohne Wirkung (kein eigenes Ziel, siehe
|
||||
// onOpen/openItem in HomePage.tsx), aber es taucht wie gewohnt als
|
||||
// Treffer auf.
|
||||
return rankSearchResults(allSearchItems, query);
|
||||
}, [query, allSearchItems]);
|
||||
|
||||
const closeSearch = () => {
|
||||
@@ -702,20 +714,25 @@ export function MobileAndroidHome({
|
||||
</Button>
|
||||
</form>
|
||||
{readLaterItems.length > 0 ? (
|
||||
<div className="grid grid-cols-4 gap-x-3 gap-y-5">
|
||||
{readLaterItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
onClick={() => onOpen({ url: item.url, id: item.id, kind: "bookmark" })}
|
||||
className="flex flex-col items-center gap-1.5"
|
||||
>
|
||||
<TileIcon favicon={item.favicon} label={item.displayName} />
|
||||
<span className="line-clamp-2 w-full text-center text-[11px] leading-tight text-black/70 dark:text-white/70">
|
||||
{item.displayName}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
<div className="flex flex-col divide-y divide-black/5 dark:divide-white/10">
|
||||
{[...readLaterItems]
|
||||
.sort((a, b) => new Date(b.savedAt).getTime() - new Date(a.savedAt).getTime())
|
||||
.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
onClick={() => onOpen({ url: item.url, id: item.id, kind: "bookmark" })}
|
||||
className="flex items-center gap-3 py-2.5 text-left"
|
||||
>
|
||||
<TileIcon favicon={item.favicon} label={item.displayName} size="small" />
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="block truncate text-sm text-black dark:text-white">{item.displayName}</span>
|
||||
<span className="block text-[11px] text-black/40 dark:text-white/40">
|
||||
{formatSavedAt(item.savedAt)}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-black/40 dark:text-white/40">Noch nichts gemerkt.</p>
|
||||
|
||||
Reference in New Issue
Block a user