Skip to content

Commit

Permalink
feat: apply title and description ai translation
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Jun 12, 2024
1 parent 78c0306 commit 8101112
Show file tree
Hide file tree
Showing 13 changed files with 127 additions and 62 deletions.
6 changes: 3 additions & 3 deletions src/renderer/src/components/entry-column/article-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useEntry } from "@renderer/store/entry"
import { ReactVirtuosoItemPlaceholder } from "../ui/placeholder"
import type { UniversalItemProps } from "./types"

export function ArticleItem({ entryId, entryPreview }: UniversalItemProps) {
export function ArticleItem({ entryId, entryPreview, translation }: UniversalItemProps) {
const entry = useEntry(entryId) || entryPreview

const asRead = useAsRead(entry)
Expand All @@ -33,13 +33,13 @@ export function ArticleItem({ entryId, entryPreview }: UniversalItemProps) {
</span>
</div>
<div className={cn("relative my-0.5 break-words", !!entry.collections && "pr-4", entry.entries.title ? "font-medium" : "text-[13px]")}>
{entry.entries.title || entry.entries.description}
{translation?.title || translation?.description || entry.entries.title || entry.entries.description}
{!!entry.collections && (
<i className="i-mingcute-star-fill absolute right-0 top-0.5 text-orange-400" />
)}
</div>
<div className={cn("text-[13px]", asRead ? "text-zinc-400" : "text-zinc-500")}>
{entry.entries.description}
{translation?.description || entry.entries.description}
</div>
</div>
{entry.entries.images?.[0] && (
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/components/entry-column/audio-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useEntry } from "@renderer/store/entry"
import { ReactVirtuosoItemPlaceholder } from "../ui/placeholder"
import type { UniversalItemProps } from "./types"

export function AudioItem({ entryId, entryPreview }: UniversalItemProps) {
export function AudioItem({ entryId, entryPreview, translation }: UniversalItemProps) {
const entry = useEntry(entryId) || entryPreview
if (!entry) return <ReactVirtuosoItemPlaceholder />
return (
Expand All @@ -26,7 +26,7 @@ export function AudioItem({ entryId, entryPreview }: UniversalItemProps) {
</span>
</div>
<div className={cn("relative my-0.5", !!entry.collections && "pr-4")}>
{entry.entries.title}
{translation?.title || entry.entries.title}
{!!entry.collections && (
<i className="i-mingcute-star-fill absolute right-0 top-0.5 text-orange-400" />
)}
Expand Down
46 changes: 2 additions & 44 deletions src/renderer/src/components/entry-column/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
} from "@renderer/components/ui/popover"
import { apiClient } from "@renderer/lib/api-fetch"
import { views } from "@renderer/lib/constants"
import { FeedViewType } from "@renderer/lib/enum"
import { buildStorageNS } from "@renderer/lib/ns"
import { getEntriesParams } from "@renderer/lib/utils"
import { useEntries } from "@renderer/queries/entries"
Expand All @@ -29,14 +28,7 @@ import { useEventCallback } from "usehooks-ts"
import { useShallow } from "zustand/react/shallow"

import { EmptyIcon } from "../icons/empty"
import { ArticleItem } from "./article-item"
import { AudioItem } from "./audio-item"
import { EntryItemWrapper } from "./item-wrapper"
import { NotificationItem } from "./notification-item"
import { PictureItem } from "./picture-item"
import { SocialMediaItem } from "./social-media-item"
import type { UniversalItemProps } from "./types"
import { VideoItem } from "./video-item"

const unreadOnlyAtom = atomWithStorage<boolean>(
buildStorageNS("entry-unreadonly"),
Expand All @@ -50,38 +42,6 @@ export function EntryColumn() {
const entries = useEntriesByView()
const { entriesIds } = entries

let Item: FC<UniversalItemProps>

switch (activeList?.view) {
case FeedViewType.Articles: {
Item = ArticleItem
break
}
case FeedViewType.SocialMedia: {
Item = SocialMediaItem
break
}
case FeedViewType.Pictures: {
Item = PictureItem
break
}
case FeedViewType.Videos: {
Item = VideoItem
break
}
case FeedViewType.Audios: {
Item = AudioItem
break
}
case FeedViewType.Notifications: {
Item = NotificationItem
break
}
default: {
Item = ArticleItem
}
}

const handleRangeChange = useEventCallback(
debounce(
async ({ startIndex }: ListRange) => {
Expand Down Expand Up @@ -134,12 +94,10 @@ export function EntryColumn() {
key={entryId}
entryId={entryId}
view={activeList?.view}
>
<Item entryId={entryId} />
</EntryItemWrapper>
/>
)
},
[Item, activeList?.view],
[activeList?.view],
),
}

Expand Down
55 changes: 52 additions & 3 deletions src/renderer/src/components/entry-column/item-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import { useAsRead } from "@renderer/hooks/useAsRead"
import { useBizQuery } from "@renderer/hooks/useBizQuery"
import { useEntryActions, useRead } from "@renderer/hooks/useEntryActions"
import { views } from "@renderer/lib/constants"
import { FeedViewType } from "@renderer/lib/enum"
import { showNativeMenu } from "@renderer/lib/native-menu"
import { cn } from "@renderer/lib/utils"
import { Queries } from "@renderer/queries"
import { feedActions, useFeedStore } from "@renderer/store"
import { useEntry } from "@renderer/store/entry"
import type { FC } from "react"

import { ReactVirtuosoItemPlaceholder } from "../ui/placeholder"
import { ArticleItem } from "./article-item"
import { AudioItem } from "./audio-item"
import { NotificationItem } from "./notification-item"
import { PictureItem } from "./picture-item"
import { SocialMediaItem } from "./social-media-item"
import type { UniversalItemProps } from "./types"
import { VideoItem } from "./video-item"

export function EntryItemWrapper({
children,
entryId,
view,
}: {
entryId: string
children: React.ReactNode
view?: number
}) {
const entry = useEntry(entryId)
Expand All @@ -23,6 +32,14 @@ export function EntryItemWrapper({
entry,
})

const translation = useBizQuery(Queries.ai.translation({
id: entry.entries.id,
language: entry.settings?.translation,
fields: view ? views[view].translation : "",
}), {
enabled: !!entry.settings?.translation,
})

const activeEntry = useFeedStore((state) => state.activeEntry)

const asRead = useAsRead(entry)
Expand All @@ -32,6 +49,38 @@ export function EntryItemWrapper({
// NOTE: prevent 0 height element, react virtuoso will not stop render any more
if (!entry) return <ReactVirtuosoItemPlaceholder />

let Item: FC<UniversalItemProps>

switch (view) {
case FeedViewType.Articles: {
Item = ArticleItem
break
}
case FeedViewType.SocialMedia: {
Item = SocialMediaItem
break
}
case FeedViewType.Pictures: {
Item = PictureItem
break
}
case FeedViewType.Videos: {
Item = VideoItem
break
}
case FeedViewType.Audios: {
Item = AudioItem
break
}
case FeedViewType.Notifications: {
Item = NotificationItem
break
}
default: {
Item = ArticleItem
}
}

return (
<div className={cn(!views[view || 0].wideMode && "pb-3")}>
<div
Expand Down Expand Up @@ -66,7 +115,7 @@ export function EntryItemWrapper({
)
}}
>
{children}
<Item entryId={entryId} translation={translation.data} />
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useEntry } from "@renderer/store/entry"
import { ReactVirtuosoItemPlaceholder } from "../ui/placeholder"
import type { UniversalItemProps } from "./types"

export function NotificationItem({ entryId, entryPreview }: UniversalItemProps) {
export function NotificationItem({ entryId, entryPreview, translation }: UniversalItemProps) {
const entry = useEntry(entryId) || entryPreview
if (!entry) return <ReactVirtuosoItemPlaceholder />
return (
Expand All @@ -26,7 +26,7 @@ export function NotificationItem({ entryId, entryPreview }: UniversalItemProps)
</span>
</div>
<div className={cn("relative my-0.5", !!entry.collections && "pr-4")}>
{entry.entries.title}
{translation?.title || entry.entries.title}
{!!entry.collections && (
<i className="i-mingcute-star-fill absolute right-0 top-0.5 text-orange-400" />
)}
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/components/entry-column/picture-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useEntry } from "@renderer/store/entry"
import { usePreviewImages } from "../ui/image/hooks"
import type { UniversalItemProps } from "./types"

export function PictureItem({ entryId, entryPreview }: UniversalItemProps) {
export function PictureItem({ entryId, entryPreview, translation }: UniversalItemProps) {
const entry = useEntry(entryId) || entryPreview
const previewImage = usePreviewImages()
if (!entry) return <ReactVirtuosoItemPlaceholder />
Expand Down Expand Up @@ -37,7 +37,7 @@ export function PictureItem({ entryId, entryPreview }: UniversalItemProps) {
!!entry.collections && "pr-4",
)}
>
{entry.entries.title}
{translation?.title || entry.entries.title}
{!!entry.collections && (
<i className="i-mingcute-star-fill absolute right-0 top-0.5 text-orange-400" />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useEntry } from "@renderer/store/entry"
import { ReactVirtuosoItemPlaceholder } from "../ui/placeholder"
import type { UniversalItemProps } from "./types"

export function SocialMediaItem({ entryId, entryPreview }: UniversalItemProps) {
export function SocialMediaItem({ entryId, entryPreview, translation }: UniversalItemProps) {
const entry = useEntry(entryId) || entryPreview

// NOTE: prevent 0 height element, react virtuoso will not stop render any more
Expand All @@ -30,7 +30,7 @@ export function SocialMediaItem({ entryId, entryPreview }: UniversalItemProps) {
</span>
</div>
<div className={cn("relative mt-0.5", !!entry.collections && "pr-4")}>
{entry.entries.description}
{translation?.description || entry.entries.description}
{!!entry.collections && (
<i className="i-mingcute-star-fill absolute right-0 top-0.5 text-orange-400" />
)}
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/src/components/entry-column/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ export type UniversalItemProps = {
entryPreview?: EntryModel | {
feeds: FeedModel
}
translation?: {
title?: string
description?: string
} | null
}
4 changes: 2 additions & 2 deletions src/renderer/src/components/entry-column/video-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useMemo, useRef, useState } from "react"
import { ReactVirtuosoItemPlaceholder } from "../ui/placeholder"
import type { UniversalItemProps } from "./types"

export function VideoItem({ entryId, entryPreview }: UniversalItemProps) {
export function VideoItem({ entryId, entryPreview, translation }: UniversalItemProps) {
const entry = useEntry(entryId) || entryPreview

const iframeSrc = useMemo(() => urlToIframe(entry.entries.url), [entry.entries.url])
Expand Down Expand Up @@ -52,7 +52,7 @@ export function VideoItem({ entryId, entryPreview }: UniversalItemProps) {
</div>
<div className="flex-1 px-2 pb-3 pt-1 text-sm">
<div className={cn("relative mb-0.5 mt-1 truncate font-medium", !!entry.collections && "pr-4")}>
{entry.entries.title}
{translation?.title || entry.entries.title}
{!!entry.collections && (
<i className="i-mingcute-star-fill absolute right-0 top-0.5 text-orange-400" />
)}
Expand Down
23 changes: 21 additions & 2 deletions src/renderer/src/hono.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@ import * as hono_utils_http_status from 'hono/utils/http-status';
import * as hono from 'hono';

declare const routes: hono_hono_base.HonoBase<hono.Env, {
"/ai/translation": {
$get: {
input: {
query: {
id: string;
language: "en" | "ja" | "zh-CN" | "zh-TW";
fields: string;
};
};
output: {
code: 0;
data?: {
description?: string | undefined;
title?: string | undefined;
} | undefined;
};
outputFormat: "json";
status: 200;
};
};
} & {
"/actions": {
$get: {
input: {};
Expand Down Expand Up @@ -373,7 +394,6 @@ declare const routes: hono_hono_base.HonoBase<hono.Env, {
feedIdList?: string[] | undefined;
publishedAfter?: string | undefined;
collected?: boolean | undefined;
withContent?: boolean | undefined;
};
};
output: {
Expand All @@ -393,7 +413,6 @@ declare const routes: hono_hono_base.HonoBase<hono.Env, {
publishedAt: string;
images: string[] | null;
categories: string[] | null;
content?: string | null | undefined;
enclosures?: {
url: string;
length?: number | undefined;
Expand Down
6 changes: 6 additions & 0 deletions src/renderer/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,42 @@ export const views = [
name: "Articles",
icon: <i className="i-mingcute-news-fill" />,
className: "text-amber-700",
translation: "title,description",
},
{
name: "Social Media",
icon: <i className="i-mingcute-twitter-fill" />,
className: "text-sky-600",
wideMode: true,
translation: "description",
},
{
name: "Pictures",
icon: <i className="i-mingcute-pic-fill" />,
className: "text-green-600",
gridMode: true,
wideMode: true,
translation: "title",
},
{
name: "Videos",
icon: <i className="i-mingcute-youtube-fill" />,
className: "text-red-600",
gridMode: true,
wideMode: true,
translation: "title",
},
{
name: "Audios",
icon: <i className="i-mingcute-headphone-fill" />,
className: "text-purple-600",
translation: "title",
},
{
name: "Notifications",
icon: <i className="i-mingcute-notification-fill" />,
className: "text-yellow-600",
translation: "title",
},
]

Expand Down
Loading

0 comments on commit 8101112

Please sign in to comment.