feat: show shorts in home activities

This commit is contained in:
DIYgod 2023-09-14 23:18:30 +08:00
parent 5ca4d3fb7f
commit a459ada1d3
No known key found for this signature in database
6 changed files with 270 additions and 124 deletions

View File

@ -0,0 +1,30 @@
import { Metadata } from "next"
import { Hydrate, dehydrate } from "@tanstack/react-query"
import { HomeFeed } from "~/components/home/HomeFeed"
import { APP_NAME } from "~/lib/env"
import getQueryClient from "~/lib/query-client"
import { prefetchGetFeed } from "~/queries/home.server"
export const metadata: Metadata = {
title: `Shorts - ${APP_NAME}`,
}
export default async function LatestActivities() {
const queryClient = getQueryClient()
await prefetchGetFeed(
{
type: "shorts",
},
queryClient,
)
const dehydratedState = dehydrate(queryClient)
return (
<Hydrate state={dehydratedState}>
<HomeFeed type="shorts" />
</Hydrate>
)
}

View File

@ -3,6 +3,7 @@ import { notFound } from "next/navigation"
import { Hydrate, dehydrate } from "@tanstack/react-query"
import PageContent from "~/components/common/PageContent"
import PostCover from "~/components/home/PostCover"
import PostModal from "~/components/home/PostModal"
import { PostFooter } from "~/components/site/PostFooter"
import PostMeta from "~/components/site/PostMeta"
@ -56,6 +57,12 @@ export default async function SiteModal({
}
const onlyContent = isOnlyContent()
const type = page?.metadata?.content?.tags?.[0]
const images = page.metadata?.content?.attachments
?.filter((attachment) => attachment.name === "image")
.map((img) => img.address || "")
.filter(Boolean)
return (
<PostModal handle={site?.handle}>
<div className="pb-16">
@ -71,36 +78,57 @@ export default async function SiteModal({
)}
>
<article>
<div>
{page?.metadata?.content?.tags?.includes("post") ? (
<h2 className="xlog-post-title text-4xl font-bold leading-tight text-center">
{page.metadata?.content?.title}
</h2>
) : (
<h2 className="xlog-post-title text-xl font-bold page-title text-center">
{page?.metadata?.content?.title}
</h2>
)}
{page?.metadata?.content?.tags?.includes("post") && (
<PostMeta
{type === "short" ? (
<div className="space-y-3">
<PostCover
uniqueKey={`short-${page.characterId}-${page.noteId}`}
images={images}
title={page.metadata?.content?.title}
className="rounded-lg w-full"
/>
{page?.metadata?.content?.title && (
<h2 className="xlog-post-title text-xl font-bold page-title text-center">
{page?.metadata?.content?.title}
</h2>
)}
<div className="xlog-post-content prose">
{page?.metadata?.content?.content}
</div>
</div>
) : (
<>
<div>
{page?.metadata?.content?.tags?.includes("post") ? (
<h2 className="xlog-post-title text-4xl font-bold leading-tight text-center">
{page.metadata?.content?.title}
</h2>
) : (
<h2 className="xlog-post-title text-xl font-bold page-title text-center">
{page?.metadata?.content?.title}
</h2>
)}
{page?.metadata?.content?.tags?.includes("post") && (
<PostMeta
page={page}
site={site}
summary={summary}
translated={{
"AI-generated summary": t("AI-generated summary"),
}}
/>
)}
</div>
<PageContent
className="mt-10"
content={page?.metadata?.content?.content}
toc={false}
page={page}
site={site}
summary={summary}
translated={{
"AI-generated summary": t("AI-generated summary"),
}}
withActions={false}
onlyContent={onlyContent}
/>
)}
</div>
<PageContent
className="mt-10"
content={page?.metadata?.content?.content}
toc={false}
page={page}
site={site}
withActions={false}
onlyContent={onlyContent}
/>
</>
)}
</article>
<Hydrate state={dehydratedState}>
{page?.metadata && (

View File

@ -82,13 +82,15 @@ const Card = ({
className={cn(
"px-3 py-2 w-full min-w-0 flex flex-col text-sm",
isShort
? "h-auto sm:h-[82px]"
: "space-y-2 sm:px-5 sm:py-4 h-auto sm:h-[166px]",
? "space-y-2 h-auto sm:h-[84px]" // 8 * 2 + 8 + 40 + 20
: "space-y-2 sm:px-5 sm:py-4 h-auto sm:h-[163px]", // 16 * 2 + 8 * 2 + 75 + 20 + 20
)}
>
<div
className={cn(
isShort ? "line-clamp-2" : "space-y-2 line-clamp-3 h-[76px]",
isShort
? "line-clamp-2 max-h-10"
: "space-y-2 line-clamp-3 h-[75px]",
)}
>
{comment && (
@ -133,95 +135,93 @@ const Card = ({
</div>
)}
</div>
<div className="xlog-post-meta text-zinc-400 flex items-center text-[13px] h-[26px] truncate space-x-2">
{isPortfolio ? (
<>
<Tooltip
label={`${platform?.name || platform}`}
className="text-sm"
>
<span className="inline-flex items-center space-x-[6px]">
{platform?.icon && (
<Image
src={platform?.icon}
alt={platform?.name}
width={16}
height={16}
/>
)}
<span>{t("Portfolio")}</span>
</span>
</Tooltip>
{!!post.stat?.portfolio?.videoViewsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--youtube-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.videoViewsCount}
/>
</span>
)}
{!!post.stat?.portfolio?.audoListensCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--headphone-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.audoListensCount}
/>
</span>
)}
{!!post.stat?.portfolio?.projectStarsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--star-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.projectStarsCount}
/>
</span>
)}
{!!post.stat?.portfolio?.textViewsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--eye-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat.portfolio.textViewsCount} />
</span>
)}
{!!post.stat?.portfolio?.commentsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--comment-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat.portfolio.commentsCount} />
</span>
)}
</>
) : (
<>
{!!post.metadata?.content?.tags?.[1] && (
<span
className="xlog-post-tags hover:text-zinc-600 hover:bg-zinc-200 border transition-colors text-zinc-500 inline-flex items-center bg-zinc-100 rounded-full px-2 py-[1.5px] truncate text-xs sm:text-[13px]"
onClick={(e) => {
e.preventDefault()
router.push(`/tag/${post.metadata?.content?.tags?.[1]}`)
}}
{!isShort && (
<div className="xlog-post-meta text-zinc-400 flex items-center text-[13px] truncate space-x-2">
{isPortfolio ? (
<>
<Tooltip
label={`${platform?.name || platform}`}
className="text-sm"
>
<i className="icon-[mingcute--tag-line] mr-[2px]" />
{post.metadata?.content?.tags?.[1]}
</span>
)}
{isShort && !!post.stat?.viewCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--eye-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat?.viewCount} />
</span>
)}
{!isShort && !!post.stat?.viewDetailCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--eye-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat?.viewDetailCount} />
</span>
)}
{post.stat?.commentsCount ? (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--comment-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat.commentsCount} />
</span>
) : (
!isShort && (
<span className="inline-flex items-center space-x-[6px]">
{platform?.icon && (
<Image
src={platform?.icon}
alt={platform?.name}
width={16}
height={16}
/>
)}
<span>{t("Portfolio")}</span>
</span>
</Tooltip>
{!!post.stat?.portfolio?.videoViewsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--youtube-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.videoViewsCount}
/>
</span>
)}
{!!post.stat?.portfolio?.audoListensCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--headphone-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.audoListensCount}
/>
</span>
)}
{!!post.stat?.portfolio?.projectStarsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--star-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.projectStarsCount}
/>
</span>
)}
{!!post.stat?.portfolio?.textViewsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--eye-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.textViewsCount}
/>
</span>
)}
{!!post.stat?.portfolio?.commentsCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--comment-line] mr-[2px] text-base" />
<FormattedNumber
value={post.stat.portfolio.commentsCount}
/>
</span>
)}
</>
) : (
<>
{!!post.metadata?.content?.tags?.[1] && (
<span
className="xlog-post-tags hover:text-zinc-600 hover:bg-zinc-200 border transition-colors text-zinc-500 inline-flex items-center bg-zinc-100 rounded-full px-2 py-[1.5px] truncate text-xs sm:text-[13px] h-5"
onClick={(e) => {
e.preventDefault()
router.push(`/tag/${post.metadata?.content?.tags?.[1]}`)
}}
>
<i className="icon-[mingcute--tag-line] mr-[2px]" />
{post.metadata?.content?.tags?.[1]}
</span>
)}
{!isShort && !!post.stat?.viewDetailCount && (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--eye-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat?.viewDetailCount} />
</span>
)}
{post.stat?.commentsCount ? (
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--comment-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat.commentsCount} />
</span>
) : (
<span className="xlog-post-word-count sm:inline-flex items-center hidden">
<i className="icon-[mingcute--sandglass-line] mr-[2px] text-sm" />
<span
@ -232,12 +232,17 @@ const Card = ({
{post.metadata?.content?.readingTime} {t("min")}
</span>
</span>
)
)}
</>
)}
</>
)}
</div>
)}
<div
className={cn(
"flex items-center space-x-1 text-xs sm:text-sm overflow-hidden",
isShort && !character && "!mt-1",
)}
</div>
<div className="flex items-center space-x-1 text-xs sm:text-sm overflow-hidden">
>
{character && (
<>
<CharacterFloatCard siteId={character?.handle}>
@ -269,6 +274,14 @@ const Card = ({
<span className="text-zinc-400 hidden sm:inline-block">·</span>
</>
)}
{!!post.stat?.viewCount && (
<span className="xlog-post-meta text-zinc-400 flex items-center text-[13px] truncate space-x-2">
<span className="xlog-post-views inline-flex items-center">
<i className="icon-[mingcute--eye-line] mr-[2px] text-base" />
<FormattedNumber value={post.stat?.viewCount} />
</span>
</span>
)}
{!isShort && (
<time
dateTime={date.formatToISO(

View File

@ -20,6 +20,11 @@ export const HomeActivitiesTabs = () => {
href: "/",
active: pathname === "/",
},
{
text: "Shorts",
href: "/shorts",
active: pathname === "/shorts",
},
{
text: "Latest",
href: "/latest",

View File

@ -233,6 +233,7 @@ export const HomeFeed = ({ type }: { type?: FeedType }) => {
}`
}
isBlank={isMobileLayout}
isShort={type === "shorts"}
/>
)
}}

View File

@ -21,6 +21,7 @@ export type FeedType =
| "tag"
| "comments"
| "featured"
| "shorts"
export type SearchType = "latest" | "hottest"
@ -267,6 +268,71 @@ export async function getFeed({
}
break
}
case "shorts": {
const result = await client
.query(
gql`
query getNotes($filter: [Int!], $limit: Int) {
notes(
where: {
characterId: {
notIn: $filter
},
deleted: {
equals: false,
},
metadata: {
AND: [{
content: {
path: "sources",
array_contains: "xlog"
}
}, {
content: {
path: "tags",
array_starts_with: "short"
}
}]
},
},
orderBy: [{ createdAt: desc }],
take: $limit,
${cursorQuery}
) {
${resultFields}
stat {
viewCount
}
}
}
`,
{
filter: filter.latest,
limit,
},
)
.toPromise()
const list = await Promise.all(
result?.data?.notes.map((page: NoteEntity) =>
expandCrossbellNote({
note: page,
useScore: true,
useHTML,
}),
),
)
resultAll = {
list,
cursor: list?.length
? `${list[list.length - 1]?.characterId}_${list[list.length - 1]
?.noteId}`
: undefined,
count: list?.length || 0,
}
break
}
case "following": {
if (!characterId) {
return {
@ -806,6 +872,9 @@ export async function getFeed({
case "portfolio":
limit = -1
break
case "short":
limit = -1
break
}
const pass =
countCharacters(post?.metadata?.content?.content || "") > limit &&
@ -835,7 +904,7 @@ export async function getFeed({
})
resultAll.list = resultAll.list.concat(next.list)
resultAll.cursor = next.cursor
resultAll.count = next.count
resultAll.count = resultAll.list.length
}
return resultAll