Skip to content

Commit 68e6585

Browse files
authored
feat(integration): add omnivore support (#909)
1 parent d248c85 commit 68e6585

File tree

8 files changed

+156
-0
lines changed

8 files changed

+156
-0
lines changed

apps/renderer/src/atoms/settings/integration.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,22 @@ import type { IntegrationSettings } from "@follow/shared/interface/settings"
33
import { createSettingAtom } from "./helper"
44

55
export const createDefaultSettings = (): IntegrationSettings => ({
6+
// eagle
67
enableEagle: true,
8+
9+
// readwise
710
enableReadwise: false,
811
readwiseToken: "",
12+
13+
// instapaper
914
enableInstapaper: false,
1015
instapaperUsername: "",
1116
instapaperPassword: "",
17+
18+
// omnivore
19+
enableOmnivore: false,
20+
omnivoreEndpoint: "",
21+
omnivoreToken: "",
1222
})
1323

1424
export const {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { SVGProps } from "react"
2+
3+
export function SimpleIconsOmnivore(props: SVGProps<SVGSVGElement>) {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16" {...props}>
6+
<path
7+
fill="#3D3D3D"
8+
d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"
9+
/>
10+
</svg>
11+
)
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./collections/eagle"
22
export * from "./collections/instapaper"
3+
export * from "./collections/omnivore"
34
export * from "./collections/readwise"
45
export * from "./collections/rss3"

apps/renderer/src/hooks/biz/useEntryActions.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { mountLottie } from "~/components/ui/lottie-container"
2525
import {
2626
SimpleIconsEagle,
2727
SimpleIconsInstapaper,
28+
SimpleIconsOmnivore,
2829
SimpleIconsReadwise,
2930
} from "~/components/ui/platform-icon/icons"
3031
import { shortcuts } from "~/constants/shortcuts"
@@ -167,6 +168,9 @@ export const useEntryActions = ({
167168
const enableInstapaper = useIntegrationSettingKey("enableInstapaper")
168169
const instapaperUsername = useIntegrationSettingKey("instapaperUsername")
169170
const instapaperPassword = useIntegrationSettingKey("instapaperPassword")
171+
const enableOmnivore = useIntegrationSettingKey("enableOmnivore")
172+
const omnivoreToken = useIntegrationSettingKey("omnivoreToken")
173+
const omnivoreEndpoint = useIntegrationSettingKey("omnivoreEndpoint")
170174

171175
const checkEagle = useQuery({
172176
queryKey: ["check-eagle"],
@@ -308,6 +312,64 @@ export const useEntryActions = ({
308312
}
309313
},
310314
},
315+
{
316+
name: t("entry_actions.save_to_omnivore"),
317+
icon: <SimpleIconsOmnivore />,
318+
key: "saveToomnivore",
319+
hide: !enableOmnivore || !omnivoreToken || !omnivoreEndpoint || !populatedEntry.entries.url,
320+
onClick: async () => {
321+
const saveUrlQuery = `
322+
mutation SaveUrl($input: SaveUrlInput!) {
323+
saveUrl(input: $input) {
324+
... on SaveSuccess {
325+
url
326+
clientRequestId
327+
}
328+
... on SaveError {
329+
errorCodes
330+
message
331+
}
332+
}
333+
}
334+
`
335+
336+
try {
337+
const data = await ofetch(omnivoreEndpoint, {
338+
method: "POST",
339+
headers: {
340+
"Content-Type": "application/json",
341+
Authorization: omnivoreToken,
342+
},
343+
body: {
344+
query: saveUrlQuery,
345+
variables: {
346+
input: {
347+
url: populatedEntry.entries.url,
348+
source: "Follow",
349+
clientRequestId: globalThis.crypto.randomUUID(),
350+
publishedAt: new Date(populatedEntry.entries.publishedAt),
351+
},
352+
},
353+
},
354+
})
355+
toast.success(
356+
<>
357+
{t("entry_actions.saved_to_omnivore")},{" "}
358+
<a target="_blank" className="underline" href={data.data.saveUrl.url}>
359+
view
360+
</a>
361+
</>,
362+
{
363+
duration: 3000,
364+
},
365+
)
366+
} catch {
367+
toast.error(t("entry_actions.failed_to_save_to_omnivore"), {
368+
duration: 3000,
369+
})
370+
}
371+
},
372+
},
311373
{
312374
key: "tip",
313375
shortcut: shortcuts.entry.tip.key,

apps/renderer/src/modules/settings/tabs/integration.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Divider } from "~/components/ui/divider"
77
import {
88
SimpleIconsEagle,
99
SimpleIconsInstapaper,
10+
SimpleIconsOmnivore,
1011
SimpleIconsReadwise,
1112
} from "~/components/ui/platform-icon/icons"
1213

@@ -100,6 +101,56 @@ export const SettingIntegration = () => {
100101
labelClassName: "w-[150px]",
101102
},
102103
}),
104+
{
105+
type: "title",
106+
value: (
107+
<span className="flex items-center gap-2 font-bold">
108+
<SimpleIconsOmnivore />
109+
{t("integration.omnivore.title")}
110+
</span>
111+
),
112+
},
113+
defineSettingItem("enableOmnivore", {
114+
label: t("integration.omnivore.enable.label"),
115+
description: t("integration.omnivore.enable.description"),
116+
}),
117+
defineSettingItem("omnivoreEndpoint", {
118+
label: t("integration.omnivore.endpoint.label"),
119+
vertical: true,
120+
description: (
121+
<>
122+
{t("integration.omnivore.endpoint.description")}{" "}
123+
<a
124+
target="_blank"
125+
className="underline"
126+
rel="noreferrer noopener"
127+
href="https://api-prod.omnivore.app/api/graphql"
128+
>
129+
https://api-prod.omnivore.app/api/graphql
130+
</a>
131+
.
132+
</>
133+
),
134+
}),
135+
defineSettingItem("omnivoreToken", {
136+
label: t("integration.omnivore.token.label"),
137+
vertical: true,
138+
type: "password",
139+
description: (
140+
<>
141+
{t("integration.omnivore.token.description")}{" "}
142+
<a
143+
target="_blank"
144+
className="underline"
145+
rel="noreferrer noopener"
146+
href="https://omnivore.app/settings/api"
147+
>
148+
omnivore.app/settings/api
149+
</a>
150+
.
151+
</>
152+
),
153+
}),
103154

104155
BottomTip,
105156
]}

locales/app/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,19 @@
5656
"entry_actions.copy_title": "Copy Title",
5757
"entry_actions.failed_to_save_to_eagle": "Failed to save to Eagle.",
5858
"entry_actions.failed_to_save_to_instapaper": "Failed to save to Instapaper.",
59+
"entry_actions.failed_to_save_to_omnivore": "Failed to save to Omnivore.",
5960
"entry_actions.failed_to_save_to_readwise": "Failed to save to Readwise.",
6061
"entry_actions.mark_as_read": "Mark as Read",
6162
"entry_actions.mark_as_unread": "Mark as Unread",
6263
"entry_actions.open_in_browser": "Open In {{which}}",
6364
"entry_actions.recent_reader": "Recent reader:",
6465
"entry_actions.save_media_to_eagle": "Save Media To Eagle",
6566
"entry_actions.save_to_instapaper": "Save To Instapaper",
67+
"entry_actions.save_to_omnivore": "Save To Omnivore",
6668
"entry_actions.save_to_readwise": "Save To Readwise",
6769
"entry_actions.saved_to_eagle": "Saved To Eagle.",
6870
"entry_actions.saved_to_instapaper": "Saved To Instapaper.",
71+
"entry_actions.saved_to_omnivore": "Saved To Omnivore.",
6972
"entry_actions.saved_to_readwise": "Saved To Readwise.",
7073
"entry_actions.share": "Share",
7174
"entry_actions.star": "Star",

locales/settings/en.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@
128128
"integration.instapaper.password.label": "Instapaper Password",
129129
"integration.instapaper.title": "Instapaper",
130130
"integration.instapaper.username.label": "Instapaper Username",
131+
"integration.omnivore.enable.description": "Display 'Save to Omnivore' button when available.",
132+
"integration.omnivore.enable.label": "Enable",
133+
"integration.omnivore.endpoint.description": "Omnivore Official Endpoint is: ",
134+
"integration.omnivore.endpoint.label": "Omnivore Endpoint",
135+
"integration.omnivore.title": "Omnivore",
136+
"integration.omnivore.token.description": "You can get it here: ",
137+
"integration.omnivore.token.label": "Omnivore API Key",
131138
"integration.readwise.enable.description": "Display 'Save to Readwise' button when available.",
132139
"integration.readwise.enable.label": "Enable",
133140
"integration.readwise.title": "Readwise",

packages/shared/src/interface/settings.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,20 @@ export interface UISettings {
4040
}
4141

4242
export interface IntegrationSettings {
43+
// eagle
4344
enableEagle: boolean
45+
46+
// readwise
4447
enableReadwise: boolean
4548
readwiseToken: string
49+
50+
// instapaper
4651
enableInstapaper: boolean
4752
instapaperUsername: string
4853
instapaperPassword: string
54+
55+
// omnivore
56+
enableOmnivore: boolean
57+
omnivoreEndpoint: string
58+
omnivoreToken: string
4959
}

0 commit comments

Comments
 (0)