From 086ddfd618c314af7d8663120b4e14814113d041 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Thu, 29 Aug 2024 18:08:16 +0800 Subject: [PATCH] feat: save to readwise --- .../ui/platform-icon/collections/readwise.tsx | 2 +- .../src/hooks/biz/useEntryActions.tsx | 98 +++++++++++++------ .../src/modules/settings/tabs/integration.tsx | 4 +- 3 files changed, 70 insertions(+), 34 deletions(-) diff --git a/src/renderer/src/components/ui/platform-icon/collections/readwise.tsx b/src/renderer/src/components/ui/platform-icon/collections/readwise.tsx index cd1cddcbe..7b7ff309a 100644 --- a/src/renderer/src/components/ui/platform-icon/collections/readwise.tsx +++ b/src/renderer/src/components/ui/platform-icon/collections/readwise.tsx @@ -8,8 +8,8 @@ export function SimpleIconsReadwise(props: SVGProps) { width="1em" height="1em" viewBox="0 0 50 50" - className={cn(props.className, "rounded-sm")} {...props} + className={cn(props.className, "rounded-[2px]")} > diff --git a/src/renderer/src/hooks/biz/useEntryActions.tsx b/src/renderer/src/hooks/biz/useEntryActions.tsx index eff1034c4..d17cdf36c 100644 --- a/src/renderer/src/hooks/biz/useEntryActions.tsx +++ b/src/renderer/src/hooks/biz/useEntryActions.tsx @@ -4,8 +4,9 @@ import { setReadabilityContent, setReadabilityStatus, } from "@renderer/atoms/readability" +import { useIntegrationSettingKey } from "@renderer/atoms/settings/integration" import { whoami } from "@renderer/atoms/user" -import { SimpleIconsEagle } from "@renderer/components/ui/platform-icon/icons" +import { SimpleIconsEagle, SimpleIconsReadwise } from "@renderer/components/ui/platform-icon/icons" import { COPY_MAP } from "@renderer/constants" import { shortcuts } from "@renderer/constants/shortcuts" import { tipcClient } from "@renderer/lib/client" @@ -136,6 +137,9 @@ export const useEntryActions = ({ const uncollect = useUnCollect(populatedEntry) const read = useRead() const unread = useUnread() + const enableEagle = useIntegrationSettingKey("enableEagle") + const enableReadwise = useIntegrationSettingKey("enableReadwise") + const readwiseToken = useIntegrationSettingKey("readwiseToken") const items = useMemo(() => { if (!populatedEntry || view === undefined) return [] @@ -150,6 +154,68 @@ export const useEntryActions = ({ disabled?: boolean onClick: () => void }[] = [ + { + name: "Save media to Eagle", + icon: , + key: "saveToEagle", + hide: + !enableEagle || (checkEagle.isLoading ? true : !checkEagle.data) || + !populatedEntry.entries.media?.length, + onClick: async () => { + if ( + !populatedEntry.entries.url || + !populatedEntry.entries.media?.length + ) { + return + } + const response = await tipcClient?.saveToEagle({ + url: populatedEntry.entries.url, + mediaUrls: populatedEntry.entries.media.map((m) => m.url), + }) + if (response?.status === "success") { + toast.success("Saved to Eagle.", { + duration: 3000, + }) + } else { + toast.error("Failed to save to Eagle.", { + duration: 3000, + }) + } + }, + }, + { + name: "Save to Readwise", + icon: , + key: "saveToReadwise", + hide: !enableReadwise || !readwiseToken || !populatedEntry.entries.url, + onClick: async () => { + try { + const data = await ofetch("https://readwise.io/api/v3/save/", { + method: "POST", + headers: { + Authorization: `Token ${readwiseToken}`, + }, + body: { + url: populatedEntry.entries.url, + html: populatedEntry.entries.content || undefined, + title: populatedEntry.entries.title || undefined, + author: populatedEntry.entries.author || undefined, + summary: populatedEntry.entries.description || undefined, + published_date: populatedEntry.entries.publishedAt || undefined, + image_url: populatedEntry.entries.media?.[0]?.url || undefined, + saved_using: "Follow", + }, + }) + toast.success(<>Saved to Readwise, view, { + duration: 3000, + }) + } catch { + toast.error("Failed to save to Readwise.", { + duration: 3000, + }) + } + }, + }, { key: "tip", shortcut: shortcuts.entry.tip.key, @@ -205,36 +271,6 @@ export const useEntryActions = ({ window.open(populatedEntry.entries.url, "_blank") }, }, - - { - name: "Save media to Eagle", - icon: , - key: "saveToEagle", - hide: - (checkEagle.isLoading ? true : !checkEagle.data) || - !populatedEntry.entries.media?.length, - onClick: async () => { - if ( - !populatedEntry.entries.url || - !populatedEntry.entries.media?.length - ) { - return - } - const response = await tipcClient?.saveToEagle({ - url: populatedEntry.entries.url, - mediaUrls: populatedEntry.entries.media.map((m) => m.url), - }) - if (response?.status === "success") { - toast("Saved to Eagle.", { - duration: 3000, - }) - } else { - toast("Failed to save to Eagle.", { - duration: 3000, - }) - } - }, - }, { name: "Share", key: "share", diff --git a/src/renderer/src/modules/settings/tabs/integration.tsx b/src/renderer/src/modules/settings/tabs/integration.tsx index 272886107..cc1141625 100644 --- a/src/renderer/src/modules/settings/tabs/integration.tsx +++ b/src/renderer/src/modules/settings/tabs/integration.tsx @@ -33,7 +33,7 @@ export const SettingIntegration = () => ( settings={[ { type: "title", - value: Eagle, + value: Eagle, }, defineSettingItem("enableEagle", { label: "Enable", @@ -41,7 +41,7 @@ export const SettingIntegration = () => ( }), { type: "title", - value: Readwise, + value: Readwise, }, defineSettingItem("enableReadwise", { label: "Enable",