feat: markdown link supports open share feed link directly (#4811)
* feat: markdown link supports open share feed link directly * docs: update changelog * fix: revert stopPropagation * fix: revert stopPropagation * fix: revert stopPropagation
This commit is contained in:
parent
420c6e9683
commit
f03e81b8fc
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
## Shiny new things
|
||||
|
||||
- markdown link supports open share feed link directly in the app
|
||||
|
||||
## Improvements
|
||||
|
||||
## No longer broken
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@ import {
|
|||
TooltipTrigger,
|
||||
} from "@follow/components/ui/tooltip/index.jsx"
|
||||
import { useCorrectZIndex } from "@follow/components/ui/z-index/ctx.js"
|
||||
import { cn, stopPropagation } from "@follow/utils"
|
||||
import { env } from "@follow/shared/env.desktop"
|
||||
import { feedSyncServices } from "@follow/store/feed/store"
|
||||
import { cn, parseSafeUrl, stopPropagation } from "@follow/utils"
|
||||
import type { MouseEvent } from "react"
|
||||
import { use, useCallback } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { toast } from "sonner"
|
||||
|
||||
import { navigateEntry } from "~/hooks/biz/useNavigateEntry"
|
||||
import { copyToClipboard } from "~/lib/clipboard"
|
||||
|
||||
import { MarkdownRenderActionContext } from "../context"
|
||||
|
|
@ -21,6 +25,7 @@ export const MarkdownLink: Component<LinkProps> = (props) => {
|
|||
const { t } = useTranslation()
|
||||
|
||||
const populatedFullHref = transformUrl(props.href)
|
||||
const shareFeedInfo = parseShareFeedInfo(populatedFullHref)
|
||||
|
||||
const handleCopyLink = useCallback(async () => {
|
||||
try {
|
||||
|
|
@ -34,6 +39,25 @@ export const MarkdownLink: Component<LinkProps> = (props) => {
|
|||
}
|
||||
}, [populatedFullHref, t])
|
||||
|
||||
const handleClickLink = useCallback(
|
||||
async (event: MouseEvent<HTMLAnchorElement>) => {
|
||||
stopPropagation(event)
|
||||
|
||||
if (!shareFeedInfo) {
|
||||
return
|
||||
}
|
||||
event.preventDefault()
|
||||
|
||||
const view = await resolveShareFeedView(shareFeedInfo)
|
||||
navigateEntry({
|
||||
feedId: shareFeedInfo.id,
|
||||
entryId: null,
|
||||
view,
|
||||
})
|
||||
},
|
||||
[shareFeedInfo],
|
||||
)
|
||||
|
||||
const parseTimeStamp = isAudio(populatedFullHref)
|
||||
const zIndex = useCorrectZIndex(0)
|
||||
if (parseTimeStamp) {
|
||||
|
|
@ -58,7 +82,7 @@ export const MarkdownLink: Component<LinkProps> = (props) => {
|
|||
title={props.title}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
onClick={stopPropagation}
|
||||
onClick={handleClickLink}
|
||||
>
|
||||
{props.children}
|
||||
|
||||
|
|
@ -93,3 +117,46 @@ export const MarkdownLink: Component<LinkProps> = (props) => {
|
|||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
const parseShareFeedInfo = (href?: string) => {
|
||||
if (!href) return null
|
||||
|
||||
const baseUrl = parseSafeUrl(env.VITE_WEB_URL)
|
||||
if (!baseUrl) return null
|
||||
|
||||
let parsedUrl: URL
|
||||
try {
|
||||
parsedUrl = new URL(href, baseUrl)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
|
||||
if (parsedUrl.host !== baseUrl.host) return null
|
||||
|
||||
const pathParts = parsedUrl.pathname.split("/").filter(Boolean)
|
||||
if (pathParts.length !== 3 || pathParts[0] !== "share" || pathParts[1] !== "feeds") {
|
||||
return null
|
||||
}
|
||||
|
||||
const viewParam = parsedUrl.searchParams.get("view")
|
||||
const view = viewParam ? Number.parseInt(viewParam, 10) : undefined
|
||||
|
||||
return {
|
||||
id: pathParts[2]!,
|
||||
view: Number.isNaN(view) ? undefined : view,
|
||||
}
|
||||
}
|
||||
|
||||
const resolveShareFeedView = async (info: { id: string; view?: number }) => {
|
||||
if (typeof info.view === "number") {
|
||||
return info.view
|
||||
}
|
||||
|
||||
const data = await feedSyncServices.fetchFeedById({ id: info.id }).catch(() => {})
|
||||
const analyticsView = data?.analytics?.view
|
||||
if (typeof analyticsView === "number") {
|
||||
return analyticsView
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue