"use client"; import { createElement, useEffect, useOptimistic, useState, useTransition, } from "react"; import { ButtonWithTooltip } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Label } from "@/components/ui/label"; import { Slider } from "@/components/ui/slider"; import { Switch } from "@/components/ui/switch"; import { useTranslation } from "@/lib/i18n/client"; import { useBookmarkDisplaySettings, useBookmarkLayout, useGridColumns, } from "@/lib/userLocalSettings/bookmarksLayout"; import { updateBookmarksLayout, updateGridColumns, updateImageFit, updateShowNotes, updateShowTags, updateShowTitle, } from "@/lib/userLocalSettings/userLocalSettings"; import { Check, Heading, Image, LayoutDashboard, LayoutGrid, LayoutList, List, LucideIcon, NotepadText, Settings, Tag, } from "lucide-react"; type LayoutType = "masonry" | "grid" | "list" | "compact"; const iconMap: Record = { masonry: LayoutDashboard, grid: LayoutGrid, list: LayoutList, compact: List, }; export default function ViewOptions() { const { t } = useTranslation(); const layout = useBookmarkLayout(); const gridColumns = useGridColumns(); const actualDisplaySettings = useBookmarkDisplaySettings(); const [tempColumns, setTempColumns] = useState(gridColumns); const [, startTransition] = useTransition(); // Optimistic state for all toggles const [optimisticDisplaySettings, setOptimisticDisplaySettings] = useOptimistic(actualDisplaySettings); const [optimisticLayout, setOptimisticLayout] = useOptimistic(layout); const [optimisticImageFit, setOptimisticImageFit] = useOptimistic( actualDisplaySettings.imageFit, ); const showColumnSlider = optimisticLayout === "grid" || optimisticLayout === "masonry"; // Update temp value when actual value changes useEffect(() => { setTempColumns(gridColumns); }, [gridColumns]); // Handlers with optimistic updates const handleLayoutChange = (newLayout: LayoutType) => { startTransition(async () => { setOptimisticLayout(newLayout); await updateBookmarksLayout(newLayout); }); }; const handleShowNotesChange = (checked: boolean) => { startTransition(async () => { setOptimisticDisplaySettings({ ...optimisticDisplaySettings, showNotes: checked, }); await updateShowNotes(checked); }); }; const handleShowTagsChange = (checked: boolean) => { startTransition(async () => { setOptimisticDisplaySettings({ ...optimisticDisplaySettings, showTags: checked, }); await updateShowTags(checked); }); }; const handleShowTitleChange = (checked: boolean) => { startTransition(async () => { setOptimisticDisplaySettings({ ...optimisticDisplaySettings, showTitle: checked, }); await updateShowTitle(checked); }); }; const handleImageFitChange = (fit: "cover" | "contain") => { startTransition(async () => { setOptimisticImageFit(fit); await updateImageFit(fit); }); }; return (
{t("view_options.layout")}
{(Object.keys(iconMap) as LayoutType[]).map((key) => ( { e.preventDefault(); handleLayoutChange(key); }} >
{createElement(iconMap[key as LayoutType], { size: 18 })} {t(`layouts.${key}`)}
{optimisticLayout === key && }
))} {showColumnSlider && ( <>
{t("view_options.columns")} {tempColumns}
setTempColumns(value)} onValueCommit={([value]) => updateGridColumns(value)} min={1} max={6} step={1} className="w-full" />
1 6
)}
{t("view_options.display_options")}
{t("view_options.image_options")}
{ e.preventDefault(); handleImageFitChange("cover"); }} >
{t("view_options.image_fit_cover")}
{optimisticImageFit === "cover" && ( )}
{ e.preventDefault(); handleImageFitChange("contain"); }} >
{t("view_options.image_fit_contain")}
{optimisticImageFit === "contain" && ( )}
); }