Skip to content

Commit

Permalink
feat: display feed certification in discover result
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Sep 13, 2024
1 parent 1852d1e commit 425b8c3
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 146 deletions.
9 changes: 9 additions & 0 deletions src/hono.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5283,6 +5283,15 @@ declare const _routes: hono_hono_base.HonoBase<
errorMessage: string | null
errorAt: string | null
ownerUserId: string | null
owner: {
name: string | null
id: string
email: string
emailVerified: string | null
image: string | null
handle: string | null
createdAt: string
} | null
}
entries?:
| {
Expand Down
73 changes: 73 additions & 0 deletions src/renderer/src/components/feed-certification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useWhoami } from "@renderer/atoms/user"
import { Avatar, AvatarFallback, AvatarImage } from "@renderer/components/ui/avatar"
import {
Tooltip,
TooltipContent,
TooltipPortal,
TooltipTrigger,
} from "@renderer/components/ui/tooltip"
import { cn } from "@renderer/lib/utils"
import type { FeedModel } from "@renderer/models"
import { usePresentUserProfileModal } from "@renderer/modules/profile/hooks"
import { useTranslation } from "react-i18next"

export const FeedCertification = ({ feed, className }: { feed: FeedModel; className?: string }) => {
const me = useWhoami()
const presentUserProfile = usePresentUserProfileModal("drawer")
const { t } = useTranslation()

return (
feed.ownerUserId &&
(feed.ownerUserId === me?.id ? (
<Tooltip delayDuration={300}>
<TooltipTrigger asChild>
<i className={cn("i-mgc-certificate-cute-fi ml-1.5 shrink-0 text-accent", className)} />
</TooltipTrigger>

<TooltipPortal>
<TooltipContent className="px-4 py-2">
<div className="flex items-center text-base font-semibold">
<i className="i-mgc-certificate-cute-fi mr-2 shrink-0 text-accent" />
{t("feed_item.claimed_feed")}
</div>
<div>{t("feed_item.claimed_by_you")}</div>
</TooltipContent>
</TooltipPortal>
</Tooltip>
) : (
<Tooltip delayDuration={300}>
<TooltipTrigger asChild>
<i
className={cn("i-mgc-certificate-cute-fi ml-1.5 shrink-0 text-amber-500", className)}
/>
</TooltipTrigger>

<TooltipPortal>
<TooltipContent className="px-4 py-2">
<div className="flex items-center text-base font-semibold">
<i className="i-mgc-certificate-cute-fi mr-2 shrink-0 text-amber-500" />
{t("feed_item.claimed_feed")}
</div>
<div className="mt-1 flex items-center gap-1.5">
<span>{t("feed_item.claimed_by_owner")}</span>
{feed.owner ? (
<Avatar
className="inline-flex aspect-square size-5 rounded-full"
onClick={(e) => {
e.stopPropagation()
presentUserProfile(feed.owner!.id)
}}
>
<AvatarImage src={feed.owner.image || undefined} />
<AvatarFallback>{feed.owner.name?.slice(0, 2)}</AvatarFallback>
</Avatar>
) : (
<span>{t("feed_item.claimed_by_unknown")}</span>
)}
</div>
</TooltipContent>
</TooltipPortal>
</Tooltip>
))
)
}
6 changes: 5 additions & 1 deletion src/renderer/src/components/feed-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FeedIcon } from "@renderer/components/feed-icon"
import { cn } from "@renderer/lib/utils"
import type { FeedModel } from "@renderer/models"

import { FeedCertification } from "./feed-certification"
import { EllipsisHorizontalTextWithTooltip } from "./ui/typography"

export function FollowSummary({
Expand All @@ -28,7 +29,10 @@ export function FollowSummary({
size={32}
/>
<div className="truncate text-base font-semibold leading-tight">
{feed.title}
<div className="flex items-center gap-1">
{feed.title}
<FeedCertification feed={feed} />
</div>
<EllipsisHorizontalTextWithTooltip className="truncate text-xs font-normal text-zinc-500">
{feed.description}
</EllipsisHorizontalTextWithTooltip>
Expand Down
178 changes: 88 additions & 90 deletions src/renderer/src/modules/discover/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,99 +144,97 @@ export function DiscoverForm({ type }: { type: string }) {
{mutation.data?.length > 1 && "s"}
</div>
<div className="space-y-6 text-sm">
{mutation.data
?.sort((a, b) => (b.subscriptionCount ?? 0) - (a.subscriptionCount ?? 0))
.map((item) => (
<Card
data-feed-id={item.feed.id}
key={item.feed.url || item.docs}
className="select-text"
>
<CardHeader>
<FollowSummary className="max-w-[462px]" feed={item.feed} docs={item.docs} />
</CardHeader>
{item.docs ? (
<CardFooter>
<a href={item.docs} target="_blank" rel="noreferrer">
<Button>View Docs</Button>
</a>
</CardFooter>
) : (
<>
<CardContent>
{!!item.entries?.length && (
<div className="grid grid-cols-4 gap-4">
{item.entries
.filter((e) => !!e)
.map((entry) => {
const assertEntry = entry
return (
<a
key={assertEntry.id}
href={assertEntry.url || void 0}
target="_blank"
className="flex min-w-0 flex-1 flex-col items-center gap-1"
rel="noreferrer"
>
{assertEntry.media?.[0] ? (
<Media
src={assertEntry.media?.[0].url}
type={assertEntry.media?.[0].type}
previewImageUrl={assertEntry.media?.[0].preview_image_url}
className="aspect-square w-full"
/>
) : (
<div className="flex aspect-square w-full overflow-hidden rounded bg-stone-100 p-2 text-xs leading-tight text-zinc-500">
{assertEntry.title}
</div>
)}
<div className="line-clamp-2 w-full text-xs leading-tight">
{mutation.data.map((item) => (
<Card
data-feed-id={item.feed.id}
key={item.feed.url || item.docs}
className="select-text"
>
<CardHeader>
<FollowSummary className="max-w-[462px]" feed={item.feed} docs={item.docs} />
</CardHeader>
{item.docs ? (
<CardFooter>
<a href={item.docs} target="_blank" rel="noreferrer">
<Button>View Docs</Button>
</a>
</CardFooter>
) : (
<>
<CardContent>
{!!item.entries?.length && (
<div className="grid grid-cols-4 gap-4">
{item.entries
.filter((e) => !!e)
.map((entry) => {
const assertEntry = entry
return (
<a
key={assertEntry.id}
href={assertEntry.url || void 0}
target="_blank"
className="flex min-w-0 flex-1 flex-col items-center gap-1"
rel="noreferrer"
>
{assertEntry.media?.[0] ? (
<Media
src={assertEntry.media?.[0].url}
type={assertEntry.media?.[0].type}
previewImageUrl={assertEntry.media?.[0].preview_image_url}
className="aspect-square w-full"
/>
) : (
<div className="flex aspect-square w-full overflow-hidden rounded bg-stone-100 p-2 text-xs leading-tight text-zinc-500">
{assertEntry.title}
</div>
</a>
)
})}
</div>
)}
</CardContent>
<CardFooter>
{item.isSubscribed ? (
<Button variant="outline" disabled>
Followed
</Button>
) : (
<Button
onClick={() => {
present({
title: "Add Feed",
content: ({ dismiss }) => (
<FeedForm
asWidget
url={item.feed.url}
id={item.feed.id}
defaultValues={{
view: getSidebarActiveView().toString(),
}}
onSuccess={dismiss}
/>
),
})
}}
>
Follow
</Button>
)}
<div className="ml-6 text-zinc-500">
<span className="font-medium text-zinc-800 dark:text-zinc-200">
{item.subscriptionCount}
</span>{" "}
Followers
)}
<div className="line-clamp-2 w-full text-xs leading-tight">
{assertEntry.title}
</div>
</a>
)
})}
</div>
</CardFooter>
</>
)}
</Card>
))}
)}
</CardContent>
<CardFooter>
{item.isSubscribed ? (
<Button variant="outline" disabled>
Followed
</Button>
) : (
<Button
onClick={() => {
present({
title: "Add Feed",
content: ({ dismiss }) => (
<FeedForm
asWidget
url={item.feed.url}
id={item.feed.id}
defaultValues={{
view: getSidebarActiveView().toString(),
}}
onSuccess={dismiss}
/>
),
})
}}
>
Follow
</Button>
)}
<div className="ml-6 text-zinc-500">
<span className="font-medium text-zinc-800 dark:text-zinc-200">
{item.subscriptionCount}
</span>{" "}
Followers
</div>
</CardFooter>
</>
)}
</Card>
))}
</div>
</div>
)}
Expand Down
57 changes: 2 additions & 55 deletions src/renderer/src/modules/feed-column/item.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { getMainContainerElement } from "@renderer/atoms/dom"
import { useWhoami } from "@renderer/atoms/user"
import { FeedCertification } from "@renderer/components/feed-certification"
import { FeedIcon } from "@renderer/components/feed-icon"
import { OouiUserAnonymous } from "@renderer/components/icons/OouiUserAnonymous"
import { Avatar, AvatarFallback, AvatarImage } from "@renderer/components/ui/avatar"
import {
Tooltip,
TooltipContent,
Expand All @@ -24,7 +23,6 @@ import dayjs from "dayjs"
import { memo, useCallback } from "react"
import { useTranslation } from "react-i18next"

import { usePresentUserProfileModal } from "../profile/hooks"
import { UnreadNumber } from "./unread-number"

interface FeedItemProps {
Expand Down Expand Up @@ -61,8 +59,6 @@ const FeedItemImpl = ({ view, feedId, className, showUnreadCount = true }: FeedI
const feed = useFeedById(feedId)

const { items } = useFeedActions({ feedId, view })
const me = useWhoami()
const presentUserProfile = usePresentUserProfileModal("drawer")

if (!feed) return null

Expand Down Expand Up @@ -122,56 +118,7 @@ const FeedItemImpl = ({ view, feedId, className, showUnreadCount = true }: FeedI
>
{getPreferredTitle(feed)}
</div>
{feed.ownerUserId &&
(feed.ownerUserId === me?.id ? (
<Tooltip delayDuration={300}>
<TooltipTrigger asChild>
<i className="i-mgc-certificate-cute-fi ml-1.5 shrink-0 text-[15px] text-accent" />
</TooltipTrigger>

<TooltipPortal>
<TooltipContent className="px-4 py-2">
<div className="flex items-center text-base font-semibold">
<i className="i-mgc-certificate-cute-fi mr-2 shrink-0 text-accent" />
{t("feed_item.claimed_feed")}
</div>
<div>{t("feed_item.claimed_by_you")}</div>
</TooltipContent>
</TooltipPortal>
</Tooltip>
) : (
<Tooltip delayDuration={300}>
<TooltipTrigger asChild>
<i className="i-mgc-certificate-cute-fi ml-1.5 shrink-0 text-[15px] text-amber-500" />
</TooltipTrigger>

<TooltipPortal>
<TooltipContent className="px-4 py-2">
<div className="flex items-center text-base font-semibold">
<i className="i-mgc-certificate-cute-fi mr-2 shrink-0 text-amber-500" />
{t("feed_item.claimed_feed")}
</div>
<div className="mt-1 flex items-center gap-1.5">
<span>{t("feed_item.claimed_by_owner")}</span>
{feed.owner ? (
<Avatar
className="inline-flex aspect-square size-5 rounded-full"
onClick={(e) => {
e.stopPropagation()
presentUserProfile(feed.owner!.id)
}}
>
<AvatarImage src={feed.owner.image || undefined} />
<AvatarFallback>{feed.owner.name?.slice(0, 2)}</AvatarFallback>
</Avatar>
) : (
<span>{t("feed_item.claimed_by_unknown")}</span>
)}
</div>
</TooltipContent>
</TooltipPortal>
</Tooltip>
))}
<FeedCertification feed={feed} className="text-[15px]" />
{feed.errorAt && (
<Tooltip delayDuration={300}>
<TooltipTrigger asChild>
Expand Down

0 comments on commit 425b8c3

Please sign in to comment.