Skip to content

Commit

Permalink
feat: integration settings page
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Aug 29, 2024
1 parent 09950e0 commit f9f1938
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 3 deletions.
1 change: 1 addition & 0 deletions icons/mgc/department_cute_re.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/renderer/src/atoms/settings/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const createDefineSettingItem =
key: K,
options: {
label: string
description?: string
description?: string | JSX.Element
onChange?: (value: T[K]) => void
hide?: boolean
},
Expand Down
19 changes: 19 additions & 0 deletions src/renderer/src/atoms/settings/integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { IntegrationSettings } from "@shared/interface/settings"

import { createSettingAtom } from "./helper"

export const createDefaultSettings = (): IntegrationSettings => ({
enableEagle: true,
enableReadwise: true,
readwiseToken: "",
})

export const {
useSettingKey: useIntegrationSettingKey,
useSettingSelector: useIntegrationSettingSelector,
setSetting: setIntegrationSetting,
clearSettings: clearIntegrationSettings,
initializeDefaultSettings: initializeDefaultIntegrationSettings,
getSettings: getIntegrationSettings,
useSettingValue: useIntegrationSettingValue,
} = createSettingAtom("integration", createDefaultSettings)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { cn } from "@renderer/lib/utils"
import type { SVGProps } from "react"

export function SimpleIconsReadwise(props: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 50 50"
className={cn(props.className, "rounded-sm")}
{...props}
>
<g>
<path d="M50 0H0V50H50V0Z" fill="currentColor" />
<path d="M36.2225 35.7866C37.2767 37.5404 38.1366 38.1234 39.8953 38.3323V40.0861H31.2186L23.091 26.527H21.0603V35.4174C21.0603 37.7979 21.6481 38.1282 24.15 38.3371V40.0909H11.0525V38.3371C13.5544 38.1282 14.1423 37.793 14.1423 35.4174V15.5524C14.1423 13.1331 13.6322 12.8416 11.0525 12.6327V10.8789H24.5338C32.6615 10.8789 36.9075 12.589 36.9075 18.5985C36.9075 23.1457 34.6971 25.3173 30.2422 26.0655L36.2225 35.7866ZM22.2311 13.7161C21.5266 13.7161 21.0603 14.2164 21.0603 14.9695V23.6898H24.4221C27.9005 23.6898 29.9701 22.4364 29.9701 18.5985C29.9701 14.7168 27.9005 13.7161 24.5387 13.7161H22.2311Z" fill="white" />
<path d="M31.345 11.918H18.7041V23.9856H31.345V11.918Z" fill="white" />
<path d="M29.7184 14.0234C29.0334 15.2914 30.0925 21.2669 30.0925 21.2669C30.1071 21.5827 29.8933 21.8596 29.5824 21.9276C29.5824 21.9276 23.1016 21.9568 20.9543 23.7446" fill="currentColor" />
</g>
</svg>
)
}
1 change: 1 addition & 0 deletions src/renderer/src/components/ui/platform-icon/icons.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./collections/eagle"
export * from "./collections/readwise"
export * from "./collections/rss3"
24 changes: 23 additions & 1 deletion src/renderer/src/modules/settings/control.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Button } from "@renderer/components/ui/button"
import { Checkbox } from "@renderer/components/ui/checkbox"
import { Input } from "@renderer/components/ui/input"
import { Label } from "@renderer/components/ui/label"
import { SegmentGroup, SegmentItem } from "@renderer/components/ui/segement"
import { Switch } from "@renderer/components/ui/switch"
import { cn } from "@renderer/lib/utils"
import type { ReactNode } from "react"
import type { ChangeEventHandler, ReactNode } from "react"
import { useId, useState } from "react"

export const SettingCheckbox: Component<{
Expand Down Expand Up @@ -47,6 +48,27 @@ export const SettingSwitch: Component<{
)
}

export const SettingInput: Component<{
label: string
value: string
onChange: ChangeEventHandler<HTMLInputElement>
}> = ({ value, label, onChange, className }) => {
const id = useId()
return (
<div
className={cn("mb-1 flex items-center justify-between gap-12", className)}
>
<Label className="shrink-0" htmlFor={id}>{label}</Label>
<Input
id={id}
value={value}
onChange={onChange}
className="text-xs"
/>
</div>
)
}

export const SettingTabbedSegment: Component<{
label: string
value: string
Expand Down
12 changes: 11 additions & 1 deletion src/renderer/src/modules/settings/setting-builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { isValidElement } from "react"
import {
SettingActionItem,
SettingDescription,
SettingInput,
SettingSwitch,
} from "./control"
import { SettingItemGroup, SettingSectionTitle } from "./section"
Expand Down Expand Up @@ -93,7 +94,16 @@ export const createSettingBuilder =
break
}
case "string": {
return null
ControlElement = (
<SettingInput
className="mt-4"
value={settingObject[assertSetting.key] as string}
onChange={(event) =>
assertSetting.onChange(event.target.value as T[keyof T])}
label={assertSetting.label}
/>
)
break
}
default: {
return null
Expand Down
90 changes: 90 additions & 0 deletions src/renderer/src/modules/settings/tabs/integration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { createSetting } from "@renderer/atoms/settings/helper"
import {
setIntegrationSetting,
useIntegrationSettingValue,
} from "@renderer/atoms/settings/integration"
import {
createDefaultSettings,
setUISetting,
useUISettingSelector,
} from "@renderer/atoms/settings/ui"
import { SimpleIconsEagle, SimpleIconsReadwise } from "@renderer/components/ui/platform-icon/icons"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@renderer/components/ui/select"
import { tipcClient } from "@renderer/lib/client"
import { useQuery } from "@tanstack/react-query"

import { SettingsTitle } from "../title"

const { defineSettingItem, SettingBuilder } = createSetting(
useIntegrationSettingValue,
setIntegrationSetting,
)
export const SettingIntegration = () => (
<>
<SettingsTitle />
<div className="mt-4">
<SettingBuilder
settings={[
{
type: "title",
value: <span className="flex items-center gap-1"><SimpleIconsEagle />Eagle</span>,
},
defineSettingItem("enableEagle", {
label: "Enable",
description: <>Display <i>Save media to Eagle</i> button when available.</>,
}),
{
type: "title",
value: <span className="flex items-center gap-1"><SimpleIconsReadwise />Readwise</span>,
},
defineSettingItem("enableReadwise", {
label: "Enable",
description: <>Display <i>Save to Readwise</i> button when available.</>,
}),
defineSettingItem("readwiseToken", {
label: "Readwise Access Token",
description: <>You can get it here: <a target="_blank" className="underline" rel="noreferrer noopener" href="https://readwise.io/access_token">readwise.io/access_token</a>.</>,
}),
]}
/>
</div>
</>
)

export const VoiceSelector = () => {
const { data } = useQuery({
queryFn: () => tipcClient?.getVoices(),
queryKey: ["voices"],
})
const voice = useUISettingSelector((state) => state.voice)

return (
<div className="-mt-1 mb-3 flex items-center justify-between">
<span className="shrink-0 text-sm font-medium">Voices</span>
<Select
defaultValue={createDefaultSettings().voice}
value={voice}
onValueChange={(value) => {
setUISetting("voice", value)
}}
>
<SelectTrigger size="sm" className="w-48">
<SelectValue />
</SelectTrigger>
<SelectContent className="h-64">
{data?.map((item) => (
<SelectItem key={item.ShortName} value={item.ShortName}>
{item.FriendlyName}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)
}
16 changes: 16 additions & 0 deletions src/renderer/src/pages/settings/(settings)/integration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { SettingIntegration } from "@renderer/modules/settings/tabs/integration"
import { defineSettingPage } from "@renderer/modules/settings/utils"

const iconName = "i-mgc-department-cute-re"
const name = "Integration"
const priority = 1025

export const loader = defineSettingPage({
iconName,
name,
priority,
})

export function Component() {
return <SettingIntegration />
}
6 changes: 6 additions & 0 deletions src/shared/src/interface/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ export interface UISettings {
// tts
voice: string
}

export interface IntegrationSettings {
enableEagle: boolean
enableReadwise: boolean
readwiseToken: string
}

0 comments on commit f9f1938

Please sign in to comment.