From 09652176f97f11bc06f4c9b57a448e14744eac12 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 24 May 2025 12:59:43 +0000 Subject: feat: Allow defaulting to reader mode when clicking on bookmarks. Fixes #662 --- .../components/dashboard/bookmarks/LinkCard.tsx | 26 +++++- apps/web/components/settings/UserOptions.tsx | 102 ++++++++++++++++++++- 2 files changed, 120 insertions(+), 8 deletions(-) (limited to 'apps/web/components') diff --git a/apps/web/components/dashboard/bookmarks/LinkCard.tsx b/apps/web/components/dashboard/bookmarks/LinkCard.tsx index ec224ca6..2c91bd08 100644 --- a/apps/web/components/dashboard/bookmarks/LinkCard.tsx +++ b/apps/web/components/dashboard/bookmarks/LinkCard.tsx @@ -2,6 +2,7 @@ import Image from "next/image"; import Link from "next/link"; +import { useUserSettings } from "@/lib/userSettings"; import type { ZBookmarkTypeLink } from "@karakeep/shared/types/bookmarks"; import { @@ -14,11 +15,25 @@ import { import { BookmarkLayoutAdaptingCard } from "./BookmarkLayoutAdaptingCard"; import FooterLinkURL from "./FooterLinkURL"; +const useOnClickUrl = (bookmark: ZBookmarkTypeLink) => { + const userSettings = useUserSettings(); + return { + urlTarget: + userSettings.bookmarkClickAction === "open_original_link" + ? ("_blank" as const) + : ("_self" as const), + onClickUrl: + userSettings.bookmarkClickAction === "expand_bookmark_preview" + ? `/dashboard/preview/${bookmark.id}` + : bookmark.content.url, + }; +}; + function LinkTitle({ bookmark }: { bookmark: ZBookmarkTypeLink }) { - const link = bookmark.content; - const parsedUrl = new URL(link.url); + const { onClickUrl, urlTarget } = useOnClickUrl(bookmark); + const parsedUrl = new URL(bookmark.content.url); return ( - + {getBookmarkTitle(bookmark) ?? parsedUrl.host} ); @@ -31,6 +46,7 @@ function LinkImage({ bookmark: ZBookmarkTypeLink; className?: string; }) { + const { onClickUrl, urlTarget } = useOnClickUrl(bookmark); const link = bookmark.content; const imgComponent = (url: string, unoptimized: boolean) => ( @@ -61,8 +77,8 @@ function LinkImage({ return ( diff --git a/apps/web/components/settings/UserOptions.tsx b/apps/web/components/settings/UserOptions.tsx index 33ffc46a..c8aa5e86 100644 --- a/apps/web/components/settings/UserOptions.tsx +++ b/apps/web/components/settings/UserOptions.tsx @@ -1,11 +1,23 @@ "use client"; +import { useEffect } from "react"; +import { useClientConfig } from "@/lib/clientConfig"; import { useTranslation } from "@/lib/i18n/client"; import { useInterfaceLang } from "@/lib/userLocalSettings/bookmarksLayout"; import { updateInterfaceLang } from "@/lib/userLocalSettings/userLocalSettings"; +import { useUserSettings } from "@/lib/userSettings"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; +import { useUpdateUserSettings } from "@karakeep/shared-react/hooks/users"; import { langNameMappings } from "@karakeep/shared/langs"; +import { + ZUserSettings, + zUserSettingsSchema, +} from "@karakeep/shared/types/users"; +import { Form, FormField } from "../ui/form"; import { Label } from "../ui/label"; import { Select, @@ -14,6 +26,7 @@ import { SelectTrigger, SelectValue, } from "../ui/select"; +import { toast } from "../ui/use-toast"; const LanguageSelect = () => { const lang = useInterfaceLang(); @@ -38,6 +51,86 @@ const LanguageSelect = () => { ); }; +export default function UserSettings() { + const { t } = useTranslation(); + const clientConfig = useClientConfig(); + const data = useUserSettings(); + const { mutate } = useUpdateUserSettings({ + onSuccess: () => { + toast({ + description: t("settings.info.user_settings.user_settings_updated"), + }); + }, + onError: () => { + toast({ + description: t("common.something_went_wrong"), + variant: "destructive", + }); + }, + }); + + const bookmarkClickActionTranslation: Record< + ZUserSettings["bookmarkClickAction"], + string + > = { + open_original_link: t("settings.info.user_settings.open_external_url"), + expand_bookmark_preview: t( + "settings.info.user_settings.open_bookmark_details", + ), + }; + + const form = useForm>({ + resolver: zodResolver(zUserSettingsSchema), + defaultValues: data, + }); + + // When the actual user setting is loaded, reset the form to the current value + useEffect(() => { + form.reset(data); + }, [data]); + + return ( +
+ ( +
+ + +
+ )} + /> + + ); +} + export function UserOptions() { const { t } = useTranslation(); @@ -46,9 +139,12 @@ export function UserOptions() {
{t("settings.info.options")}
-
- - +
+
+ + +
+
); -- cgit v1.2.3-70-g09d2