Enable easy linking of short-form content and ensure navigation to this content is possible when clicking on the short-form content card.
This commit is contained in:
parent
b51d9afc76
commit
8da18cc360
|
|
@ -11,8 +11,17 @@ import { useGetSite } from "~/queries/site"
|
|||
import { Time } from "../common/Time"
|
||||
import PostCover from "../home/PostCover"
|
||||
import { Avatar } from "./Avatar"
|
||||
import { UniLink } from "./UniLink"
|
||||
|
||||
interface Props {
|
||||
slug: string
|
||||
handle: string
|
||||
url: string
|
||||
}
|
||||
|
||||
const XLogShorts: FC<Props> = ({ slug, handle, url }) => {
|
||||
const [isExpanded, setIsExpanded] = React.useState(false)
|
||||
|
||||
const XLogShorts: FC<{ slug: string; handle: string }> = ({ slug, handle }) => {
|
||||
const locale = useLocale() as Language
|
||||
// https://xlog.app/site/lca/JOoXQKAtZYYFrnzntDlJ6?content_type=shorts
|
||||
const site = useGetSite(handle)
|
||||
|
|
@ -30,21 +39,31 @@ const XLogShorts: FC<{ slug: string; handle: string }> = ({ slug, handle }) => {
|
|||
.filter(Boolean)
|
||||
|
||||
const isMobile = isMobileDevice()
|
||||
const [isExpanded, setIsExpanded] = React.useState(false)
|
||||
const isShort = !!page.data?.metadata?.content?.tags?.includes("short")
|
||||
|
||||
const toggleExpand = useCallback(() => {
|
||||
setIsExpanded((prev) => !prev)
|
||||
}, [])
|
||||
const toggleExpand = useCallback(
|
||||
(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
||||
e.stopPropagation()
|
||||
setIsExpanded((prev) => !prev)
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
const handleRedirect = useCallback(() => {
|
||||
window.open(url, "_blank")
|
||||
}, [url])
|
||||
|
||||
if (page.isLoading) return <div>Loading...</div>
|
||||
|
||||
if (!isShort) return <UniLink href={url}>{url}</UniLink>
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={toggleExpand}
|
||||
onClick={handleRedirect}
|
||||
className={cn(
|
||||
"flex flex-col md:flex-row w-full bg-zinc-50 rounded-xl p-4 gap-x-4 hover:cursor-pointer",
|
||||
isExpanded ? "sm:h-[350px]" : "sm:h-[150px]",
|
||||
"transition-height duration-500 ease-in-out",
|
||||
"transition-all duration-500 ease-in-out",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
|
@ -52,7 +71,7 @@ const XLogShorts: FC<{ slug: string; handle: string }> = ({ slug, handle }) => {
|
|||
className={cn(
|
||||
"w-full h-full mb-2 sm:mb-0 align-middle flex items-center justify-center",
|
||||
isExpanded ? "sm:w-[350px]" : "sm:w-[150px]",
|
||||
"transition-width duration-500 ease-in-out",
|
||||
"transition-all duration-500 ease-in-out",
|
||||
)}
|
||||
>
|
||||
<PostCover
|
||||
|
|
@ -71,7 +90,11 @@ const XLogShorts: FC<{ slug: string; handle: string }> = ({ slug, handle }) => {
|
|||
</div>
|
||||
)}
|
||||
<div className="prose overflow-y-auto">
|
||||
<p className={`line-clamp-${isExpanded || isMobile ? 6 : 1}`}>
|
||||
<p
|
||||
className={
|
||||
isExpanded || isMobile ? "line-clamp-6" : "line-clamp-1"
|
||||
}
|
||||
>
|
||||
{page.data?.metadata?.content?.content}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -111,11 +134,12 @@ const XLogShorts: FC<{ slug: string; handle: string }> = ({ slug, handle }) => {
|
|||
|
||||
<i
|
||||
className={cn(
|
||||
"i-mingcute-arrows-down-line text-xl ml-[2px] text-accent",
|
||||
"i-mingcute-arrows-down-line text-xl ml-[2px] text-accent hover:cursor-pointer",
|
||||
isExpanded ? "rotate-180" : "rotate-0",
|
||||
"transition-transform duration-500 ease-in-out",
|
||||
"hidden sm:inline-block",
|
||||
)}
|
||||
onClick={toggleExpand}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,54 +1,41 @@
|
|||
import { match } from "path-to-regexp"
|
||||
|
||||
import type { Transformer } from "../rehype-embed"
|
||||
import { isHostIncludes } from "./utils"
|
||||
|
||||
function getParamsFromShortsURL(url: URL) {
|
||||
let slug = ""
|
||||
let handle = ""
|
||||
|
||||
// https://caspian-3030.xlog.app/AtOAglnMV_N6xslDbfhz4?ct=shorts
|
||||
let matched = match<{ slug: string }>("/:slug")(url.pathname)
|
||||
|
||||
if (matched) {
|
||||
slug = matched.params.slug
|
||||
handle = url.host.split(".")[0]
|
||||
} else {
|
||||
// https://xlog.app/site/caspian-3030/AtOAglnMV_N6xslDbfhz4?ct=shorts
|
||||
matched = match<{ slug: string; handle: string }>("/site/:handle/:slug")(
|
||||
url.pathname,
|
||||
)
|
||||
|
||||
if (!matched) return undefined
|
||||
|
||||
slug = matched?.params.slug || ""
|
||||
// @ts-ignore
|
||||
handle = matched?.params.handle || ""
|
||||
}
|
||||
|
||||
return { slug, handle }
|
||||
}
|
||||
|
||||
export const XLogShortsTransformer: Transformer = {
|
||||
name: "XLogShorts",
|
||||
shouldTransform(url) {
|
||||
// There are two patterns for xlog shorts url
|
||||
|
||||
const { host, pathname, searchParams } = url
|
||||
const hasShortsParam = searchParams.get("ct") === "shorts"
|
||||
|
||||
/**
|
||||
* content type param is required
|
||||
* @example ?ct=shorts
|
||||
* */
|
||||
if (!hasShortsParam) return false
|
||||
|
||||
// https://xlog.app/site/caspian-3030/AtOAglnMV_N6xslDbfhz4?ct=shorts
|
||||
if (isHostIncludes("xlog.app", host) && pathname.startsWith("/site/")) {
|
||||
return true
|
||||
}
|
||||
|
||||
// https://caspian-3030.xlog.app/AtOAglnMV_N6xslDbfhz4?ct=shorts
|
||||
return /^[a-z0-9-]+\.xlog\.app/.test(host)
|
||||
return !!getParamsFromShortsURL(url)
|
||||
},
|
||||
getHTML(url) {
|
||||
let slug = ""
|
||||
let handle = ""
|
||||
const { slug, handle } = getParamsFromShortsURL(url)!
|
||||
|
||||
// import { match } from "path-to-regexp"
|
||||
// https://caspian-3030.xlog.app/AtOAglnMV_N6xslDbfhz4?ct=shorts
|
||||
let matched = match<{ slug: string }>("/:slug")(url.pathname)
|
||||
|
||||
if (matched) {
|
||||
slug = matched.params.slug
|
||||
handle = url.host.split(".")[0]
|
||||
} else {
|
||||
// https://xlog.app/site/caspian-3030/AtOAglnMV_N6xslDbfhz4?ct=shorts
|
||||
matched = match<{ slug: string; handle: string }>("/site/:handle/:slug")(
|
||||
url.pathname,
|
||||
)
|
||||
|
||||
if (!matched) return
|
||||
|
||||
slug = matched?.params.slug || ""
|
||||
// @ts-ignore
|
||||
handle = matched?.params.handle || ""
|
||||
}
|
||||
|
||||
return `<xlog-shorts slug="${slug}" handle="${handle}"/>`
|
||||
return `<xlog-shorts slug="${slug}" handle="${handle}" url="${url.toString()}"/>`
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue