Skip to content

Commit

Permalink
feat(integration): Add readeck integration (#1972)
Browse files Browse the repository at this point in the history
  • Loading branch information
syfxlin authored Dec 2, 2024
1 parent a44d598 commit 1ce3f5b
Show file tree
Hide file tree
Showing 19 changed files with 222 additions and 6 deletions.
5 changes: 5 additions & 0 deletions apps/renderer/src/atoms/settings/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export const createDefaultSettings = (): IntegrationSettings => ({
outlineEndpoint: "",
outlineToken: "",
outlineCollection: "",

// readeck
enableReadeck: false,
readeckEndpoint: "",
readeckToken: "",
})

export const {
Expand Down
4 changes: 4 additions & 0 deletions apps/renderer/src/hooks/biz/useEntryActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ export const useEntryActions = ({ entryId, view }: { entryId: string; view?: Fee
id: COMMAND_ID.integration.saveToOutline,
onClick: runCmdFn(COMMAND_ID.integration.saveToOutline, [{ entryId }]),
},
{
id: COMMAND_ID.integration.saveToReadeck,
onClick: runCmdFn(COMMAND_ID.integration.saveToReadeck, [{ entryId }]),
},
{
id: COMMAND_ID.entry.tip,
onClick: runCmdFn(COMMAND_ID.entry.tip, [{ entryId, feedId: feed?.id }]),
Expand Down
1 change: 1 addition & 0 deletions apps/renderer/src/modules/command/commands/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const COMMAND_ID = {
saveToInstapaper: "integration:save-to-instapaper",
saveToObsidian: "integration:save-to-obsidian",
saveToOutline: "integration:save-to-outline",
saveToReadeck: "integration:save-to-readeck",
},
list: {
edit: "list:edit",
Expand Down
70 changes: 70 additions & 0 deletions apps/renderer/src/modules/command/commands/integration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
SimpleIconsInstapaper,
SimpleIconsObsidian,
SimpleIconsOutline,
SimpleIconsReadeck,
SimpleIconsReadwise,
} from "@follow/components/ui/platform-icon/icons.js"
import { IN_ELECTRON } from "@follow/shared/constants"
Expand Down Expand Up @@ -30,6 +31,7 @@ export const useRegisterIntegrationCommands = () => {
useRegisterInstapaperCommands()
useRegisterObsidianCommands()
useRegisterOutlineCommands()
useRegisterReadeckCommands()
}

const useRegisterEagleCommands = () => {
Expand Down Expand Up @@ -380,3 +382,71 @@ const useRegisterOutlineCommands = () => {
},
)
}

const useRegisterReadeckCommands = () => {
const { t } = useTranslation()

const enableReadeck = useIntegrationSettingKey("enableReadeck")
const readeckEndpoint = useIntegrationSettingKey("readeckEndpoint")
const readeckToken = useIntegrationSettingKey("readeckToken")
const readeckAvailable = enableReadeck && !!readeckEndpoint && !!readeckToken

useRegisterCommandEffect(
!readeckAvailable
? []
: defineFollowCommand({
id: COMMAND_ID.integration.saveToReadeck,
label: t("entry_actions.save_to_readeck"),
icon: <SimpleIconsReadeck />,
run: async ({ entryId }) => {
const entry = useEntryStore.getState().flatMapEntries[entryId]
if (!entry) {
toast.error("Failed to save to Readeck: entry is not available", { duration: 3000 })
return
}
try {
window.analytics?.capture("integration", {
type: "readeck",
event: "save",
})
const data = new FormData()
if (entry.entries.url) {
data.set("url", entry.entries.url)
}
if (entry.entries.title) {
data.set("title", entry.entries.title)
}
const response = await ofetch.raw(
`${readeckEndpoint.replace(/\/$/, "")}/api/bookmarks`,
{
method: "POST",
body: data,
headers: {
Authorization: `Bearer ${readeckToken}`,
},
},
)

toast.success(
<>
{t("entry_actions.saved_to_readeck")},{" "}
<a target="_blank" className="underline" href={response.headers.get("Location")!}>
view
</a>
</>,
{
duration: 3000,
},
)
} catch {
toast.error(t("entry_actions.failed_to_save_to_readeck"), {
duration: 3000,
})
}
},
}),
{
deps: [readeckAvailable],
},
)
}
6 changes: 6 additions & 0 deletions apps/renderer/src/modules/command/commands/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,17 @@ export type SaveToOutlineCommand = Command<{
fn: (payload: { entryId: string }) => void
}>

export type SaveToReadeckCommand = Command<{
id: typeof COMMAND_ID.integration.saveToReadeck
fn: (payload: { entryId: string }) => void
}>

export type IntegrationCommand =
| SaveToEagleCommand
| SaveToReadwiseCommand
| SaveToInstapaperCommand
| SaveToObsidianCommand
| SaveToOutlineCommand
| SaveToReadeckCommand

export type BasicCommand = EntryCommand | IntegrationCommand
26 changes: 25 additions & 1 deletion apps/renderer/src/modules/settings/tabs/integration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
SimpleIconsInstapaper,
SimpleIconsObsidian,
SimpleIconsOutline,
SimpleIconsReadeck,
SimpleIconsReadwise,
} from "@follow/components/ui/platform-icon/icons.js"
import { useEffect } from "react"
Expand Down Expand Up @@ -149,7 +150,30 @@ export const SettingIntegration = () => {
vertical: true,
description: t("integration.outline.collection.description"),
}),

{
type: "title",
value: (
<span className="flex items-center gap-2 font-bold">
<SimpleIconsReadeck />
{t("integration.readeck.title")}
</span>
),
},
defineSettingItem("enableReadeck", {
label: t("integration.readeck.enable.label"),
description: t("integration.readeck.enable.description"),
}),
defineSettingItem("readeckEndpoint", {
label: t("integration.readeck.endpoint.label"),
vertical: true,
description: t("integration.readeck.endpoint.description"),
}),
defineSettingItem("readeckToken", {
label: t("integration.readeck.token.label"),
vertical: true,
type: "password",
description: t("integration.readeck.token.description"),
}),
BottomTip,
]}
/>
Expand Down
5 changes: 4 additions & 1 deletion locales/app/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"entry_actions.failed_to_save_to_instapaper": "Failed to save to Instapaper.",
"entry_actions.failed_to_save_to_obsidian": "Failed to save to Obsidian",
"entry_actions.failed_to_save_to_outline": "Failed to save to Outline.",
"entry_actions.failed_to_save_to_readeck": "Failed to save to Readeck.",
"entry_actions.failed_to_save_to_readwise": "Failed to save to Readwise.",
"entry_actions.mark_as_read": "Mark as Read",
"entry_actions.mark_as_unread": "Mark as Unread",
Expand All @@ -121,11 +122,13 @@
"entry_actions.save_to_instapaper": "Save To Instapaper",
"entry_actions.save_to_obsidian": "Save to Obsidian",
"entry_actions.save_to_outline": "Save To Outline",
"entry_actions.save_to_readeck": "Save To Readeck",
"entry_actions.save_to_readwise": "Save To Readwise",
"entry_actions.saved_to_eagle": "Saved To Eagle.",
"entry_actions.saved_to_instapaper": "Saved To Instapaper.",
"entry_actions.saved_to_obsidian": "Saved to Obsidian",
"entry_actions.saved_to_outline": "Saved To Outline.",
"entry_actions.saved_to_readeck": "Saved To Readeck.",
"entry_actions.saved_to_readwise": "Saved To Readwise.",
"entry_actions.share": "Share",
"entry_actions.star": "Star",
Expand Down Expand Up @@ -244,7 +247,7 @@
"new_user_guide.step.behavior.unread_question.option2": "Balanced: Automatically marked as read when hovered over or scrolled out of view.",
"new_user_guide.step.behavior.unread_question.option3": "Conservative: Marked as read only when clicked.",
"new_user_guide.step.features.actions.description": "Action rules allow you to perform different actions for different feeds.\n- Using AI to summarize or translate.\n- Configure how to read entries.\n- Enable notifications for new entries or silence them.\n- Rewrite or block specific entries.\n- Send new entries to a webhook address.",
"new_user_guide.step.features.integration.description": "Integrations allow you to save entries to other services. Currently supported services are:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian",
"new_user_guide.step.features.integration.description": "Integrations allow you to save entries to other services. Currently supported services are:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian\n- Outline\n- Readeck",
"new_user_guide.step.migrate.profile": "Setup your profile",
"new_user_guide.step.migrate.title": "Migrate from OPML file",
"new_user_guide.step.migrate.wallet": "Check your wallet",
Expand Down
5 changes: 4 additions & 1 deletion locales/app/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"entry_actions.failed_to_save_to_instapaper": "Instapaper への保存に失敗しました。",
"entry_actions.failed_to_save_to_obsidian": "Obsidian への保存に失敗しました。",
"entry_actions.failed_to_save_to_outline": "Outline への保存に失敗しました。",
"entry_actions.failed_to_save_to_readeck": "Readeck への保存に失敗しました。",
"entry_actions.failed_to_save_to_readwise": "Readwise への保存に失敗しました。",
"entry_actions.mark_as_read": "既読にする",
"entry_actions.mark_as_unread": "未読にする",
Expand All @@ -121,11 +122,13 @@
"entry_actions.save_to_instapaper": "Instapaper に保存",
"entry_actions.save_to_obsidian": "Obsidian に保存",
"entry_actions.save_to_outline": "Outline に保存",
"entry_actions.save_to_readeck": "Readeck に保存",
"entry_actions.save_to_readwise": "Readwise に保存",
"entry_actions.saved_to_eagle": "Eagle に保存されました。",
"entry_actions.saved_to_instapaper": "Instapaper に保存されました。",
"entry_actions.saved_to_obsidian": "Obsidian に保存されました。",
"entry_actions.saved_to_outline": "Outline に保存されました。",
"entry_actions.saved_to_readeck": "Readeck に保存されました。",
"entry_actions.saved_to_readwise": "Readwise に保存されました。",
"entry_actions.share": "共有",
"entry_actions.star": "スター",
Expand Down Expand Up @@ -241,7 +244,7 @@
"new_user_guide.step.behavior.unread_question.option2": "バランス: ホバーしたりスクロールが終わると自動で既読にします。",
"new_user_guide.step.behavior.unread_question.option3": "コンサバ: クリックしたときのみ既読にします。",
"new_user_guide.step.features.actions.description": "アクションルールはフィードごとに違ったアクションを実行できます。\n - AI を使った要約や翻訳 \n - エントリーの読み方の設定 \n - 新着エントリーの通知の有効/無効 \n - 特定のエントリーの書き換えやブロック \n - 新着エントリーの Webhook アドレスへの送信など",
"new_user_guide.step.features.integration.description": "統合により、他のサービスにエントリーを保存することができます。現在対応しているサービスは以下のとおりです:\n- Eagle \n- Readwise \n- Instapaper \n- Obsidian \n- Outline",
"new_user_guide.step.features.integration.description": "統合により、他のサービスにエントリーを保存することができます。現在対応しているサービスは以下のとおりです:\n- Eagle \n- Readwise \n- Instapaper \n- Obsidian \n- Outline \n- Readeck",
"new_user_guide.step.migrate.profile": "プロファイルをセットアップ",
"new_user_guide.step.migrate.title": "OPML ファイルを構成する",
"new_user_guide.step.migrate.wallet": "ウォレットをチェック",
Expand Down
5 changes: 4 additions & 1 deletion locales/app/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"entry_actions.failed_to_save_to_instapaper": "保存到 Instapaper 失败。",
"entry_actions.failed_to_save_to_obsidian": "保存到 Obsidian 失败。",
"entry_actions.failed_to_save_to_outline": "保存到 Outline 失败。",
"entry_actions.failed_to_save_to_readeck": "保存到 Readeck 失败。",
"entry_actions.failed_to_save_to_readwise": "保存到 Readwise 失败。",
"entry_actions.mark_as_read": "标记为已读",
"entry_actions.mark_as_unread": "标记为未读",
Expand All @@ -121,11 +122,13 @@
"entry_actions.save_to_instapaper": "保存到 Instapaper",
"entry_actions.save_to_obsidian": "保存到 Obsidian",
"entry_actions.save_to_outline": "保存到 Outline",
"entry_actions.save_to_readeck": "保存到 Readeck",
"entry_actions.save_to_readwise": "保存到 Readwise",
"entry_actions.saved_to_eagle": "已保存到 Eagle。",
"entry_actions.saved_to_instapaper": "已保存到 Instapaper。",
"entry_actions.saved_to_obsidian": "已保存到 Obsidian。",
"entry_actions.saved_to_outline": "已保存到 Outline。",
"entry_actions.saved_to_readeck": "已保存到 Readeck。",
"entry_actions.saved_to_readwise": "已保存到 Readwise。",
"entry_actions.share": "分享",
"entry_actions.star": "收藏",
Expand Down Expand Up @@ -242,7 +245,7 @@
"new_user_guide.step.behavior.unread_question.option2": "平衡:悬停或滚出视野时自动标记为已读。",
"new_user_guide.step.behavior.unread_question.option3": "被动:仅在点击时标记为已读。",
"new_user_guide.step.features.actions.description": "自动化规则允许你对不同的订阅执行不同的操作。\n- 使用 AI 进行摘要或翻译\n- 配置阅读条目的方式\n- 启用新条目的通知或静音\n- 重写或屏蔽特定条目\n- 将新条目发送到 webhook 地址",
"new_user_guide.step.features.integration.description": "集成允许你将条目保存到其他服务。目前支持的服务有:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian",
"new_user_guide.step.features.integration.description": "集成允许你将条目保存到其他服务。目前支持的服务有:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian\n- Outline\n- Readeck",
"new_user_guide.step.migrate.profile": "设置你的个人资料",
"new_user_guide.step.migrate.title": "从 OPML 文件导入",
"new_user_guide.step.migrate.wallet": "检查你的钱包",
Expand Down
5 changes: 4 additions & 1 deletion locales/app/zh-HK.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"entry_actions.failed_to_save_to_instapaper": "無法儲存至 Instapaper",
"entry_actions.failed_to_save_to_obsidian": "無法儲存至 Obsidian ",
"entry_actions.failed_to_save_to_outline": "無法儲存至 Outline",
"entry_actions.failed_to_save_to_readeck": "無法儲存至 Readeck",
"entry_actions.failed_to_save_to_readwise": "無法儲存至 Readwise",
"entry_actions.mark_as_read": "標記為已讀",
"entry_actions.mark_as_unread": "標記為未讀",
Expand All @@ -121,11 +122,13 @@
"entry_actions.save_to_instapaper": "儲存至 Instapaper",
"entry_actions.save_to_obsidian": "儲存至 Obsidian",
"entry_actions.save_to_outline": "儲存至 Outline",
"entry_actions.save_to_readeck": "儲存至 Readeck",
"entry_actions.save_to_readwise": "儲存至 Readwise",
"entry_actions.saved_to_eagle": "已儲存至 Eagle",
"entry_actions.saved_to_instapaper": "已儲存至 Instapaper",
"entry_actions.saved_to_obsidian": "已儲存至 Obsidian",
"entry_actions.saved_to_outline": "已儲存至 Outline",
"entry_actions.saved_to_readeck": "已儲存至 Readeck",
"entry_actions.saved_to_readwise": "已儲存至 Readwise",
"entry_actions.share": "分享",
"entry_actions.star": "收藏",
Expand Down Expand Up @@ -244,7 +247,7 @@
"new_user_guide.step.behavior.unread_question.option2": "平衡:懸停或滾出視野時自動標記為已讀",
"new_user_guide.step.behavior.unread_question.option3": "被動:僅在點擊時標記為已讀",
"new_user_guide.step.features.actions.description": "自動化規則允許你對不同的訂閱執行不同的動作\n- 使用 AI 進行摘要或翻譯\n- 配置閱讀條目的方式\n- 啟用新條目的通知或靜音\n- 重寫或封鎖特定條目\n- 將新條目發送到 webhook 地址",
"new_user_guide.step.features.integration.description": "集成允許你將條目儲存到其他服務。目前支持的服務有:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian",
"new_user_guide.step.features.integration.description": "集成允許你將條目儲存到其他服務。目前支持的服務有:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian\n- Outline\n- Readeck",
"new_user_guide.step.migrate.profile": "設定你的個人資料",
"new_user_guide.step.migrate.title": "從 OPML 檔案匯入",
"new_user_guide.step.migrate.wallet": "檢查你的銀包",
Expand Down
5 changes: 4 additions & 1 deletion locales/app/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"entry_actions.failed_to_save_to_instapaper": "無法儲存到 Instapaper。",
"entry_actions.failed_to_save_to_obsidian": "儲存到 Obsidian 失敗",
"entry_actions.failed_to_save_to_outline": "無法儲存到 Outline。",
"entry_actions.failed_to_save_to_readeck": "無法儲存到 Readeck。",
"entry_actions.failed_to_save_to_readwise": "無法儲存到 Readwise。",
"entry_actions.mark_as_read": "標記為已讀",
"entry_actions.mark_as_unread": "標記為未讀",
Expand All @@ -121,11 +122,13 @@
"entry_actions.save_to_instapaper": "儲存到 Instapaper",
"entry_actions.save_to_obsidian": "儲存到 Obsidian",
"entry_actions.save_to_outline": "儲存到 Outline",
"entry_actions.save_to_readeck": "儲存到 Readeck",
"entry_actions.save_to_readwise": "儲存到 Readwise",
"entry_actions.saved_to_eagle": "已儲存至 Eagle。",
"entry_actions.saved_to_instapaper": "已儲存至 Instapaper。",
"entry_actions.saved_to_obsidian": "已儲存到 Obsidian",
"entry_actions.saved_to_outline": "已儲存至 Outline。",
"entry_actions.saved_to_readeck": "已儲存至 Readeck。",
"entry_actions.saved_to_readwise": "已儲存至 Readwise。",
"entry_actions.share": "分享",
"entry_actions.star": "收藏",
Expand Down Expand Up @@ -244,7 +247,7 @@
"new_user_guide.step.behavior.unread_question.option2": "平衡:滑過或離開視圖時自動標記為已讀。",
"new_user_guide.step.behavior.unread_question.option3": "保守:僅在點擊時標記為已讀。",
"new_user_guide.step.features.actions.description": "指令允許您為不同的訂閱源設定操作。\n- 使用 AI 進行總結或翻譯。\n- 設定條目的閱讀方式。\n- 為新條目啟用通知或靜音。\n- 覆寫或封鎖特定條目。\n- 將新條目發送到 webhook。",
"new_user_guide.step.features.integration.description": "整合功能允許您將條目保存到其他服務。目前支持的服務包括:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian",
"new_user_guide.step.features.integration.description": "整合功能允許您將條目保存到其他服務。目前支持的服務包括:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian\n- Outline\n- Readeck",
"new_user_guide.step.migrate.profile": "設定您的個人資料",
"new_user_guide.step.migrate.title": "從 OPML 文件導入",
"new_user_guide.step.migrate.wallet": "檢查您的錢包",
Expand Down
7 changes: 7 additions & 0 deletions locales/settings/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@
"integration.outline.title": "Outline",
"integration.outline.token.description": "You can get it from your Outline account settings.",
"integration.outline.token.label": "Outline API Key",
"integration.readeck.enable.description": "Display 'Save to Readeck' button when available.",
"integration.readeck.enable.label": "Enable",
"integration.readeck.endpoint.description": "The URL is 'https://<YOUR_READECK_DOMAIN>'.",
"integration.readeck.endpoint.label": "Readeck API Base URL",
"integration.readeck.title": "Readeck",
"integration.readeck.token.description": "You can get it from your Readeck account settings.",
"integration.readeck.token.label": "Readeck API Token",
"integration.readwise.enable.description": "Display 'Save to Readwise' button when available.",
"integration.readwise.enable.label": "Enable",
"integration.readwise.title": "Readwise",
Expand Down
Loading

0 comments on commit 1ce3f5b

Please sign in to comment.