"use client"; import { Button } from "@/components/ui/button"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Separator } from "@/components/ui/separator"; import { Slider } from "@/components/ui/slider"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { useTranslation } from "@/lib/i18n/client"; import { useReaderSettings } from "@/lib/readerSettings"; import { Globe, Laptop, Minus, Plus, RotateCcw, Settings, Type, X, } from "lucide-react"; import { formatFontSize, formatLineHeight, READER_DEFAULTS, READER_SETTING_CONSTRAINTS, } from "@karakeep/shared/types/readers"; interface ReaderSettingsPopoverProps { open?: boolean; onOpenChange?: (open: boolean) => void; variant?: "outline" | "ghost"; } export default function ReaderSettingsPopover({ open, onOpenChange, variant = "outline", }: ReaderSettingsPopoverProps) { const { t } = useTranslation(); const { settings, serverSettings, localOverrides, sessionOverrides, hasSessionChanges, hasLocalOverrides, isSaving, updateSession, clearSession, saveToDevice, clearLocalOverride, saveToServer, } = useReaderSettings(); // Helper to get the effective server value (server setting or default) const getServerValue = (key: K) => { return serverSettings[key] ?? READER_DEFAULTS[key]; }; // Helper to check if a setting has a local override const hasLocalOverride = (key: keyof typeof localOverrides) => { return localOverrides[key] !== undefined; }; // Build tooltip message for the settings button const getSettingsTooltip = () => { if (hasSessionChanges && hasLocalOverrides) { return t("settings.info.reader_settings.tooltip_preview_and_local"); } if (hasSessionChanges) { return t("settings.info.reader_settings.tooltip_preview"); } if (hasLocalOverrides) { return t("settings.info.reader_settings.tooltip_local"); } return t("settings.info.reader_settings.tooltip_default"); }; return (

{getSettingsTooltip()}

{t("settings.info.reader_settings.title")}

{hasSessionChanges && ( {t("settings.info.reader_settings.preview")} )}
{sessionOverrides.fontFamily !== undefined && ( {t("settings.info.reader_settings.preview_inline")} )} {hasLocalOverride("fontFamily") && sessionOverrides.fontFamily === undefined && (

{t( "settings.info.reader_settings.clear_override_hint", { value: t( `settings.info.reader_settings.${getServerValue("fontFamily")}` as const, ), }, )}

)}
{formatFontSize(settings.fontSize)} {sessionOverrides.fontSize !== undefined && ( {t("settings.info.reader_settings.preview_inline")} )} {hasLocalOverride("fontSize") && sessionOverrides.fontSize === undefined && (

{t( "settings.info.reader_settings.clear_override_hint", { value: formatFontSize( getServerValue("fontSize"), ), }, )}

)}
updateSession({ fontSize: value }) } max={READER_SETTING_CONSTRAINTS.fontSize.max} min={READER_SETTING_CONSTRAINTS.fontSize.min} step={READER_SETTING_CONSTRAINTS.fontSize.step} className={`flex-1 ${ hasLocalOverride("fontSize") && sessionOverrides.fontSize === undefined ? "[&_[role=slider]]:border-primary/50" : "" }`} />
{formatLineHeight(settings.lineHeight)} {sessionOverrides.lineHeight !== undefined && ( {t("settings.info.reader_settings.preview_inline")} )} {hasLocalOverride("lineHeight") && sessionOverrides.lineHeight === undefined && (

{t( "settings.info.reader_settings.clear_override_hint", { value: formatLineHeight( getServerValue("lineHeight"), ), }, )}

)}
updateSession({ lineHeight: value }) } max={READER_SETTING_CONSTRAINTS.lineHeight.max} min={READER_SETTING_CONSTRAINTS.lineHeight.min} step={READER_SETTING_CONSTRAINTS.lineHeight.step} className={`flex-1 ${ hasLocalOverride("lineHeight") && sessionOverrides.lineHeight === undefined ? "[&_[role=slider]]:border-primary/50" : "" }`} />
{hasSessionChanges && ( <>

{t("settings.info.reader_settings.save_hint")}

)} {!hasSessionChanges && (

{t("settings.info.reader_settings.adjust_hint")}

)}
); }