Skip to content

Commit

Permalink
feat: render social media with full text
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Sep 5, 2024
1 parent 18de381 commit 1531d2b
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 29 deletions.
2 changes: 2 additions & 0 deletions src/hono.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2752,6 +2752,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, {
data?: {
description?: string | undefined;
title?: string | undefined;
content?: string | undefined;
} | undefined;
};
outputFormat: "json" | "text";
Expand Down Expand Up @@ -3304,6 +3305,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, {
collected?: boolean | undefined;
isCollection?: boolean | undefined;
isArchived?: boolean | undefined;
withContent?: boolean | undefined;
};
};
output: {
Expand Down
9 changes: 5 additions & 4 deletions src/renderer/src/components/ui/markdown/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,24 @@ export const HTML = <A extends keyof JSX.IntrinsicElements = "div">(
as: A

accessory?: React.ReactNode
noMedia?: boolean
} & JSX.IntrinsicElements[A] &
Partial<{
renderInlineStyle: boolean
}>,
) => {
const { children, renderInlineStyle, as = "div", accessory, ...rest } = props
const [remarkOptions, setRemarkOptions] = useState({ renderInlineStyle })
const { children, renderInlineStyle, as = "div", accessory, noMedia, ...rest } = props
const [remarkOptions, setRemarkOptions] = useState({ renderInlineStyle, noMedia })
const [shouldForceReMountKey, setShouldForceReMountKey] = useState(0)

useEffect(() => {
setRemarkOptions((options) => {
if (renderInlineStyle === options.renderInlineStyle) return options

setShouldForceReMountKey((key) => key + 1)
return { ...options, renderInlineStyle }
return { ...options, renderInlineStyle, noMedia }
})
}, [renderInlineStyle])
}, [renderInlineStyle, noMedia])

const [refElement, setRefElement] = useState<HTMLElement | null>(null)

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/constants/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const views = [
className: "text-sky-600 dark:text-sky-500",
peerClassName: "peer-checked:text-sky-600 peer-checked:dark:text-sky-500",
wideMode: true,
translation: "description",
translation: "content",
view: FeedViewType.SocialMedia,
},
{
Expand Down
34 changes: 20 additions & 14 deletions src/renderer/src/lib/parse-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,32 @@ export const parseHtml = (
content: string,
options?: Partial<{
renderInlineStyle: boolean
noMedia?: boolean
}>,
) => {
const file = new VFile(content)
const { renderInlineStyle = false } = options || {}
const { renderInlineStyle = false, noMedia = false } = options || {}

const pipeline = unified()
.use(rehypeParse, { fragment: true })
.use(rehypeSanitize, {
...defaultSchema,
tagNames: [...defaultSchema.tagNames!, "video", "style"],
attributes: {
...defaultSchema.attributes,

"*": renderInlineStyle ?
[...defaultSchema.attributes!["*"], "style", "class"] :
defaultSchema.attributes!["*"],

"video": ["src", "poster"],
},
})
.use(rehypeSanitize, noMedia ?
{
...defaultSchema,
tagNames: defaultSchema.tagNames?.filter((tag) => tag !== "img" && tag !== "picture"),
} :
{
...defaultSchema,
tagNames: [...defaultSchema.tagNames!, "video", "style"],
attributes: {
...defaultSchema.attributes,

"*": renderInlineStyle ?
[...defaultSchema.attributes!["*"], "style", "class"] :
defaultSchema.attributes!["*"],

"video": ["src", "poster"],
},
})

.use(rehypeInferDescriptionMeta)
.use(rehypeStringify)
Expand Down
8 changes: 6 additions & 2 deletions src/renderer/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ export function getEntriesParams({
const params: {
feedId?: string
feedIdList?: string[]
collected?: boolean
isCollection?: boolean
withContent?: boolean
} = {}
if (id === FEED_COLLECTION_LIST) {
params.collected = true
params.isCollection = true
} else if (id && id !== ROUTE_FEED_PENDING) {
params.feedIdList = `${id}`.split(",")
}
if (view === FeedViewType.SocialMedia) {
params.withContent = true
}
return {
view,
...params,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const SocialMediaItem: EntryListItemFC = ({
// NOTE: prevent 0 height element, react virtuoso will not stop render any more
if (!entry || !feed) return <ReactVirtuosoItemPlaceholder />

const content = entry.entries.content || entry.entries.description

return (
<div

Expand All @@ -52,7 +54,7 @@ export const SocialMediaItem: EntryListItemFC = ({
<div
className={cn(
"-mt-0.5 flex-1 text-sm",
entry.entries.description && "line-clamp-5",
content && "line-clamp-[10]",
)}
>
<div className="w-[calc(100%-10rem)] space-x-1">
Expand All @@ -69,8 +71,9 @@ export const SocialMediaItem: EntryListItemFC = ({
)}
>
<EntryTranslation
source={entry.entries.description}
target={translation?.description}
source={content}
target={translation?.content}
isHTML
/>
{!!entry.collections && <StarIcon />}
</div>
Expand Down
48 changes: 43 additions & 5 deletions src/renderer/src/modules/entry-column/translation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as HoverCard from "@radix-ui/react-hover-card"
import { HTML } from "@renderer/components/ui/markdown"
import { ScrollArea } from "@renderer/components/ui/scroll-area"
import { tooltipStyle } from "@renderer/components/ui/tooltip/styles"
import { useMeasure } from "@renderer/hooks/common"
Expand All @@ -11,7 +12,8 @@ export const EntryTranslation: Component<{
side?: "top" | "bottom"

useOverlay?: boolean
}> = ({ source, target, className, side, useOverlay }) => {
isHTML?: boolean
}> = ({ source, target, className, side, useOverlay, isHTML }) => {
let nextTarget = target
if (source === target) {
nextTarget = undefined
Expand All @@ -20,13 +22,31 @@ export const EntryTranslation: Component<{
const [ref, bounds] = useMeasure({ debounce: 60 })

if (!nextTarget && source) {
return <div className={className}>{source}</div>
return isHTML ?
(
<HTML
as="div"
className={cn("prose dark:prose-invert", className)}
noMedia
>
{source}
</HTML>
) :
<div className={className}>{source}</div>
}
return (
<HoverCard.Root>
<HoverCard.Trigger className={className} ref={ref}>
<i className="i-mgc-translate-2-cute-re mr-1 align-middle" />
<span className="align-middle">{nextTarget}</span>
{isHTML ? (
<HTML
as="span"
className="align-middle"
noMedia
>
{nextTarget}
</HTML>
) : <span className="align-middle">{nextTarget}</span>}
</HoverCard.Trigger>
<HoverCard.Portal>
<HoverCard.Content
Expand All @@ -49,11 +69,29 @@ export const EntryTranslation: Component<{
)}
viewportClassName="max-h-[12ch]"
>
<span className="align-middle">{source}</span>
{isHTML ? (
<HTML
as="span"
className="align-middle"
noMedia
>
{source}
</HTML>
) : <span className="align-middle">{source}</span>}
</ScrollArea.ScrollArea>
</div>
) : (
<span className={cn(tooltipStyle.content)}>{source}</span>
isHTML ?
(
<HTML
as="span"
className={cn(tooltipStyle.content)}
noMedia
>
{source}
</HTML>
) :
<span className={cn(tooltipStyle.content)}>{source}</span>
)}
</HoverCard.Content>
</HoverCard.Portal>
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/modules/entry-column/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type UniversalItemProps = {
translation?: {
title?: string
description?: string
content?: string
} | null
}

Expand Down

0 comments on commit 1531d2b

Please sign in to comment.