From e0c263eb132a28f29a34b1cdad8abbb3979010ed Mon Sep 17 00:00:00 2001 From: Innei Date: Tue, 8 Oct 2024 17:14:59 +0800 Subject: [PATCH 1/7] init Signed-off-by: Innei --- apps/renderer/package.json | 1 + apps/renderer/src/api/trending.ts | 11 + apps/renderer/src/components/icons/crown.tsx | 17 + apps/renderer/src/components/icons/users.tsx | 19 ++ .../ui/modal/stacked/custom-modal.tsx | 57 +++- apps/renderer/src/hooks/biz/useFollow.tsx | 27 ++ apps/renderer/src/models/index.ts | 119 +++++++ apps/renderer/src/modules/trending/index.tsx | 303 ++++++++++++++++++ .../(layer)/(subview)/discover/index.tsx | 5 +- .../providers/extension-expose-provider.tsx | 20 +- pnpm-lock.yaml | 32 ++ 11 files changed, 590 insertions(+), 21 deletions(-) create mode 100644 apps/renderer/src/api/trending.ts create mode 100644 apps/renderer/src/components/icons/crown.tsx create mode 100644 apps/renderer/src/components/icons/users.tsx create mode 100644 apps/renderer/src/hooks/biz/useFollow.tsx create mode 100644 apps/renderer/src/modules/trending/index.tsx diff --git a/apps/renderer/package.json b/apps/renderer/package.json index a96edd51cc..f8eca97c6d 100644 --- a/apps/renderer/package.json +++ b/apps/renderer/package.json @@ -46,6 +46,7 @@ "@tanstack/react-query-persist-client": "5.56.2", "@use-gesture/react": "10.3.1", "@yornaath/batshit": "0.10.1", + "camelcase-keys": "9.1.3", "class-variance-authority": "0.7.0", "click-to-react-component": "1.1.0", "clsx": "2.1.1", diff --git a/apps/renderer/src/api/trending.ts b/apps/renderer/src/api/trending.ts new file mode 100644 index 0000000000..8f3e51a300 --- /dev/null +++ b/apps/renderer/src/api/trending.ts @@ -0,0 +1,11 @@ +import camelcaseKeys from "camelcase-keys" + +import { apiFetch } from "~/lib/api-fetch" +import type { Models } from "~/models" + +const v1ApiPrefix = "/v1" +export const getTrendingAggregates = () => { + return apiFetch(`${v1ApiPrefix}/trendings`).then((data) => + camelcaseKeys(data as any, { deep: true }), + ) +} diff --git a/apps/renderer/src/components/icons/crown.tsx b/apps/renderer/src/components/icons/crown.tsx new file mode 100644 index 0000000000..defb1262ac --- /dev/null +++ b/apps/renderer/src/components/icons/crown.tsx @@ -0,0 +1,17 @@ +import type { SVGProps } from "react" +import React from "react" + +export function IconoirBrightCrown(props: SVGProps) { + return ( + + + + ) +} diff --git a/apps/renderer/src/components/icons/users.tsx b/apps/renderer/src/components/icons/users.tsx new file mode 100644 index 0000000000..dbbc0a63b8 --- /dev/null +++ b/apps/renderer/src/components/icons/users.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from "react" +import React from "react" + +export function PhUsersBold(props: SVGProps) { + return ( + + + + ) +} diff --git a/apps/renderer/src/components/ui/modal/stacked/custom-modal.tsx b/apps/renderer/src/components/ui/modal/stacked/custom-modal.tsx index c1ab28d61d..5dc2cb0db6 100644 --- a/apps/renderer/src/components/ui/modal/stacked/custom-modal.tsx +++ b/apps/renderer/src/components/ui/modal/stacked/custom-modal.tsx @@ -1,8 +1,8 @@ -import type { PropsWithChildren } from "react" -import { useState } from "react" +import { m, useAnimationControls } from "framer-motion" +import type { FC, PropsWithChildren } from "react" +import { useEffect, useState } from "react" -import { m } from "~/components/common/Motion" -import { stopPropagation } from "~/lib/dom" +import { nextFrame, stopPropagation } from "~/lib/dom" import { cn } from "~/lib/utils" import { ModalClose } from "./components" @@ -61,3 +61,52 @@ SlideUpModal.class = (className: string) => { ) } + +const modalVariant = { + enter: { + x: 0, + opacity: 1, + }, + initial: { + x: 700, + opacity: 0.9, + }, + exit: { + x: 750, + opacity: 0, + }, +} +export const DrawerModalLayout: FC = ({ children }) => { + const { dismiss } = useCurrentModal() + const controller = useAnimationControls() + useEffect(() => { + nextFrame(() => controller.start("enter")) + }, [controller]) + + return ( +
+ + {children} + +
+ ) +} diff --git a/apps/renderer/src/hooks/biz/useFollow.tsx b/apps/renderer/src/hooks/biz/useFollow.tsx new file mode 100644 index 0000000000..5606182b5a --- /dev/null +++ b/apps/renderer/src/hooks/biz/useFollow.tsx @@ -0,0 +1,27 @@ +import { t } from "i18next" +import { useCallback } from "react" + +import { useModalStack } from "~/components/ui/modal/stacked" +import { FeedForm } from "~/modules/discover/feed-form" +import { ListForm } from "~/modules/discover/list-form" + +export const useFollow = () => { + const { present } = useModalStack() + + return useCallback( + (options?: { isList: boolean; id?: string; url?: string }) => { + present({ + title: options?.isList + ? t("sidebar.feed_actions.edit_list") + : t("sidebar.feed_actions.edit_feed"), + content: ({ dismiss }) => + options?.isList ? ( + + ) : ( + + ), + }) + }, + [present], + ) +} diff --git a/apps/renderer/src/models/index.ts b/apps/renderer/src/models/index.ts index 51f739d012..738346ec97 100644 --- a/apps/renderer/src/models/index.ts +++ b/apps/renderer/src/models/index.ts @@ -1 +1,120 @@ export * from "./types" + +/* eslint-disable @typescript-eslint/no-namespace */ +export namespace Models { + export interface TrendingList { + id: string + title: string + description: string + image: string + view: number + fee: number + timelineUpdatedAt: string + ownerUserId: string + subscriberCount: number + } + + export interface TrendingFeed { + id: string + url: string + title: string + description: string + siteUrl: string + image: string + checkedAt: string + lastModified: string + ttl: number + subscriberCount: number + ownerUserId: string + } + + export interface TrendingAggregates { + trendingFeeds: TrendingFeed[] + trendingLists: TrendingList[] + trendingEntries: TrendingEntry[] + trendingUsers: User[] + } + + export interface TrendingEntry { + id: string + feedId: string + title: string + url: string + content: string + description: string + guid: string + author: string + insertedAt: string + publishedAt: string + readCount: number + } + + export interface List { + id: string + feedIds: string[] + title: string + description: string + image: string + view: number + fee: number + timelineUpdatedAt: string + ownerUserId: string + } + export interface Entry { + id: string + feedId: string + title: string + url: string + content: string + description: string + guid: string + author: string + authorUrl: string + authorAvatar: string + insertedAt: string + publishedAt: string + media: any[] + } + + export interface UserSession { + user: { + createdAt: string + email: string + emailVerified: string | null + handle: string + id: string + image: string + name: string + } + } + export interface FeedModal { + id: string + url: string + title: string + description: string + siteUrl: string + image: string + checkedAt: string + lastModifiedHeader: string + etagHeader: string + ttl: number + ownerUserId: string + } + + export interface User { + id: string + name: string + handle: string + image: string + } + + export interface Comment { + id: number + createdAt: string + updatedAt: string + deletedAt: string | null + userId: string + entryId: string + content: string + } +} diff --git a/apps/renderer/src/modules/trending/index.tsx b/apps/renderer/src/modules/trending/index.tsx new file mode 100644 index 0000000000..6548a378cc --- /dev/null +++ b/apps/renderer/src/modules/trending/index.tsx @@ -0,0 +1,303 @@ +import { Button } from "@headlessui/react" +import { useQuery } from "@tanstack/react-query" +import { m } from "framer-motion" +import type { FC } from "react" + +import { getTrendingAggregates } from "~/api/trending" +import { FeedIcon } from "~/components/feed-icon" +import { IconoirBrightCrown } from "~/components/icons/crown" +import { PhUsersBold } from "~/components/icons/users" +import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar" +import { LoadingCircle } from "~/components/ui/loading" +import { useModalStack } from "~/components/ui/modal" +import { DrawerModalLayout } from "~/components/ui/modal/stacked/custom-modal" +import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip" +import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography" +import { useFollow } from "~/hooks/biz/useFollow" +import { stopPropagation } from "~/lib/dom" +import { cn } from "~/lib/utils" +import type { Models } from "~/models" + +import { usePresentUserProfileModal } from "../profile/hooks" + +export const Trend = () => { + const { present } = useModalStack() + return ( + + Trending + + { + present({ + title: "Trending", + content: TrendContent, + CustomModalComponent: DrawerModalLayout, + }) + }} + className={cn( + "box-content flex size-6 items-center justify-center rounded-full p-1 text-accent", + "duration-200 hover:shadow-none", + "cursor-pointer", + "absolute bottom-0 right-2", + )} + initial={{ + scale: 0, + }} + animate={{ + scale: 1, + }} + whileTap={{ + scale: 0.92, + }} + > + + + + + ) +} +const TrendContent = () => { + const { data } = useQuery({ + queryKey: ["trending"], + queryFn: () => { + return getTrendingAggregates() + }, + }) + + if (!data) + return ( +
+ +
+ ) + return ( +
+
+ + Trending +
+
+ + + + + +
+
+ ) +} +const TrendingLists: FC<{ + data: Models.TrendingList[] +}> = ({ data }) => { + const follow = useFollow() + return ( +
+

Trending Lists

+ +
    + {data.map((item) => ( +
  • + +
  • + ))} +
+
+ ) +} + +const UserCount = ({ count }: { count: number }) => { + return ( + + + {count} + + ) +} + +interface TopUserAvatarProps { + user: Models.User + position: string +} + +const TopUserAvatar: React.FC = ({ user, position }) => ( +
+ + + {user.name?.slice(0, 2)} + + + {user.name && ( + + {user.name} + + )} +
+) + +const TrendingUsers: FC<{ data: Models.User[] }> = ({ data }) => { + const profile = usePresentUserProfileModal("dialog") + return ( +
+

Trending Users

+
+
+ +
+ {/* Top 3 users */} + {data.slice(0, 3).map((user, index: number) => ( + + ))} +
+ + {data.length > 3 && ( +
    + {data.slice(3).map((user) => ( +
  • + + + {user.name} +
  • + ))} +
+ )} +
+ ) +} + +const TrendingFeeds = ({ data }: { data: Models.TrendingFeed[] }) => { + const follow = useFollow() + return ( +
+

Trending Feeds

+ +
    + {data.map((feed) => { + return ( +
  • + +
    + +
    +
    +
    {feed.title}
    +
    +
    + +
    + + + +
    +
  • + ) + })} +
+
+ ) +} + +const TrendingEntries = ({ data }: { data: Models.TrendingEntry[] }) => { + const filteredData = data.filter((entry) => !entry.url.startsWith("https://x.com")) + return ( +
+

Trending Entries

+ +
    + {filteredData.map((entry) => { + return ( +
  • + + {entry.title} + + + + {entry.readCount} + +
  • + ) + })} +
+
+ ) +} diff --git a/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx b/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx index 1b65112527..e172348c25 100644 --- a/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx +++ b/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx @@ -9,6 +9,7 @@ import { DiscoverInboxList } from "~/modules/discover/inbox-list-form" import { Recommendations } from "~/modules/discover/recommendations" import { DiscoverRSS3 } from "~/modules/discover/rss3-form" import { DiscoverUser } from "~/modules/discover/user-form" +import { Trend } from "~/modules/trending" import { useSubViewTitle } from "../hooks" @@ -64,12 +65,14 @@ export function Component() { }) }} > - + {tabs.map((tab) => ( {t(tab.name)} ))} + + {tabs.map((tab) => ( diff --git a/apps/renderer/src/providers/extension-expose-provider.tsx b/apps/renderer/src/providers/extension-expose-provider.tsx index ee071d38fd..2cb503dba9 100644 --- a/apps/renderer/src/providers/extension-expose-provider.tsx +++ b/apps/renderer/src/providers/extension-expose-provider.tsx @@ -7,8 +7,7 @@ import { toast } from "sonner" import { getGeneralSettings } from "~/atoms/settings/general" import { getUISettings } from "~/atoms/settings/ui" import { useModalStack } from "~/components/ui/modal" -import { FeedForm } from "~/modules/discover/feed-form" -import { ListForm } from "~/modules/discover/list-form" +import { useFollow } from "~/hooks/biz/useFollow" import { usePresentUserProfileModal } from "~/modules/profile/hooks" export const ExtensionExposeProvider = () => { @@ -31,27 +30,16 @@ export const ExtensionExposeProvider = () => { const { t } = useTranslation() + const follow = useFollow() const presentUserProfile = usePresentUserProfileModal("dialog") useEffect(() => { registerGlobalContext({ - follow(options) { - present({ - title: options?.isList - ? t("sidebar.feed_actions.edit_list") - : t("sidebar.feed_actions.edit_feed"), - content: ({ dismiss }) => - options?.isList ? ( - - ) : ( - - ), - }) - }, + follow, profile(id, variant) { presentUserProfile(id, variant) }, }) - }, [present, presentUserProfile, t]) + }, [follow, present, presentUserProfile, t]) return null } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a7b3c165c..8662b1fef0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -429,6 +429,9 @@ importers: '@yornaath/batshit': specifier: 0.10.1 version: 0.10.1 + camelcase-keys: + specifier: 9.1.3 + version: 9.1.3 class-variance-authority: specifier: 0.7.0 version: 0.7.0 @@ -4136,6 +4139,14 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camelcase-keys@9.1.3: + resolution: {integrity: sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==} + engines: {node: '>=16'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} @@ -6306,6 +6317,10 @@ packages: resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} engines: {node: '>=6'} + map-obj@5.0.0: + resolution: {integrity: sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} @@ -7396,6 +7411,10 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} + quick-lru@6.1.2: + resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==} + engines: {node: '>=12'} + raf-schd@4.0.3: resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} @@ -13159,6 +13178,15 @@ snapshots: camelcase-css@2.0.1: {} + camelcase-keys@9.1.3: + dependencies: + camelcase: 8.0.0 + map-obj: 5.0.0 + quick-lru: 6.1.2 + type-fest: 4.26.1 + + camelcase@8.0.0: {} + caniuse-api@3.0.0: dependencies: browserslist: 4.23.3 @@ -15742,6 +15770,8 @@ snapshots: dependencies: p-defer: 1.0.0 + map-obj@5.0.0: {} + markdown-table@3.0.3: {} masonic@4.0.1(react@18.3.1): @@ -17025,6 +17055,8 @@ snapshots: quick-lru@5.1.1: {} + quick-lru@6.1.2: {} + raf-schd@4.0.3: {} random-path@0.1.2: From 6b2bfdb10629eb6c1a8345150e0dc221e949caf9 Mon Sep 17 00:00:00 2001 From: Innei Date: Tue, 8 Oct 2024 17:30:25 +0800 Subject: [PATCH 2/7] update Signed-off-by: Innei --- apps/renderer/src/models/index.ts | 91 ++------------------ apps/renderer/src/modules/trending/index.tsx | 60 +++++++------ icons/mgc/trending_up_cute_re.svg | 4 + 3 files changed, 42 insertions(+), 113 deletions(-) create mode 100644 icons/mgc/trending_up_cute_re.svg diff --git a/apps/renderer/src/models/index.ts b/apps/renderer/src/models/index.ts index 738346ec97..9a907fee85 100644 --- a/apps/renderer/src/models/index.ts +++ b/apps/renderer/src/models/index.ts @@ -1,3 +1,7 @@ +import type { User } from "@auth/core/types" + +import type { FeedModel, ListModelPoplutedFeeds } from "./types" + export * from "./types" /* eslint-disable @typescript-eslint/no-namespace */ @@ -14,23 +18,9 @@ export namespace Models { subscriberCount: number } - export interface TrendingFeed { - id: string - url: string - title: string - description: string - siteUrl: string - image: string - checkedAt: string - lastModified: string - ttl: number - subscriberCount: number - ownerUserId: string - } - export interface TrendingAggregates { - trendingFeeds: TrendingFeed[] - trendingLists: TrendingList[] + trendingFeeds: FeedModel[] + trendingLists: ListModelPoplutedFeeds[] trendingEntries: TrendingEntry[] trendingUsers: User[] } @@ -48,73 +38,4 @@ export namespace Models { publishedAt: string readCount: number } - - export interface List { - id: string - feedIds: string[] - title: string - description: string - image: string - view: number - fee: number - timelineUpdatedAt: string - ownerUserId: string - } - export interface Entry { - id: string - feedId: string - title: string - url: string - content: string - description: string - guid: string - author: string - authorUrl: string - authorAvatar: string - insertedAt: string - publishedAt: string - media: any[] - } - - export interface UserSession { - user: { - createdAt: string - email: string - emailVerified: string | null - handle: string - id: string - image: string - name: string - } - } - export interface FeedModal { - id: string - url: string - title: string - description: string - siteUrl: string - image: string - checkedAt: string - lastModifiedHeader: string - etagHeader: string - ttl: number - ownerUserId: string - } - - export interface User { - id: string - name: string - handle: string - image: string - } - - export interface Comment { - id: number - createdAt: string - updatedAt: string - deletedAt: string | null - userId: string - entryId: string - content: string - } } diff --git a/apps/renderer/src/modules/trending/index.tsx b/apps/renderer/src/modules/trending/index.tsx index 6548a378cc..4e882faf8d 100644 --- a/apps/renderer/src/modules/trending/index.tsx +++ b/apps/renderer/src/modules/trending/index.tsx @@ -1,4 +1,4 @@ -import { Button } from "@headlessui/react" +import type { User } from "@auth/core/types" import { useQuery } from "@tanstack/react-query" import { m } from "framer-motion" import type { FC } from "react" @@ -8,7 +8,8 @@ import { FeedIcon } from "~/components/feed-icon" import { IconoirBrightCrown } from "~/components/icons/crown" import { PhUsersBold } from "~/components/icons/users" import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar" -import { LoadingCircle } from "~/components/ui/loading" +import { Button } from "~/components/ui/button" +import { LoadingWithIcon } from "~/components/ui/loading" import { useModalStack } from "~/components/ui/modal" import { DrawerModalLayout } from "~/components/ui/modal/stacked/custom-modal" import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip" @@ -16,7 +17,7 @@ import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography" import { useFollow } from "~/hooks/biz/useFollow" import { stopPropagation } from "~/lib/dom" import { cn } from "~/lib/utils" -import type { Models } from "~/models" +import type { FeedModel, Models } from "~/models" import { usePresentUserProfileModal } from "../profile/hooks" @@ -38,7 +39,7 @@ export const Trend = () => { className={cn( "box-content flex size-6 items-center justify-center rounded-full p-1 text-accent", "duration-200 hover:shadow-none", - "cursor-pointer", + "absolute bottom-0 right-2", )} initial={{ @@ -51,7 +52,7 @@ export const Trend = () => { scale: 0.92, }} > - + @@ -68,7 +69,10 @@ const TrendContent = () => { if (!data) return (
- + } + size="large" + />
) return ( @@ -101,7 +105,7 @@ const TrendingLists: FC<{ @@ -137,26 +143,26 @@ const UserCount = ({ count }: { count: number }) => { } interface TopUserAvatarProps { - user: Models.User + user: User position: string } const TopUserAvatar: React.FC = ({ user, position }) => (
- + {user.name?.slice(0, 2)} {user.name && ( - + {user.name} )}
) -const TrendingUsers: FC<{ data: Models.User[] }> = ({ data }) => { +const TrendingUsers: FC<{ data: User[] }> = ({ data }) => { const profile = usePresentUserProfileModal("dialog") return (
@@ -165,11 +171,10 @@ const TrendingUsers: FC<{ data: Models.User[] }> = ({ data }) => {
- {/* Top 3 users */} + {data.slice(0, 3).map((user, index: number) => ( - - {user.name} ))} @@ -217,7 +221,7 @@ const TrendingUsers: FC<{ data: Models.User[] }> = ({ data }) => { ) } -const TrendingFeeds = ({ data }: { data: Models.TrendingFeed[] }) => { +const TrendingFeeds = ({ data }: { data: FeedModel[] }) => { const follow = useFollow() return (
@@ -238,22 +242,22 @@ const TrendingFeeds = ({ data }: { data: Models.TrendingFeed[] }) => { href={`/feed/${feed.id}`} className="flex grow items-center gap-2 py-1" > -
- +
+
-
{feed.title}
+
{feed.title}
- + @@ -148,7 +133,8 @@ interface TopUserAvatarProps { } const TopUserAvatar: React.FC = ({ user, position }) => ( -
+
+
{user.name?.slice(0, 2)} @@ -168,7 +154,7 @@ const TrendingUsers: FC<{ data: User[] }> = ({ data }) => {

Trending Users

-
+
@@ -201,12 +187,13 @@ const TrendingUsers: FC<{ data: User[] }> = ({ data }) => {
  • -
    + -
    +
    ) } @@ -193,7 +198,7 @@ const TrendingUsers: FC<{ data: User[] }> = ({ data }) => { profile(user.id) }} > -
    +
    {user.name?.slice(0, 2)} From 6e7acfd93f5f4a8b1107016b1d2358f84a9eb0dc Mon Sep 17 00:00:00 2001 From: Innei Date: Wed, 9 Oct 2024 12:58:28 +0800 Subject: [PATCH 6/7] update i18n Signed-off-by: Innei --- apps/renderer/src/modules/trending/index.tsx | 33 ++++++++++++++------ locales/app/en.json | 6 +++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/apps/renderer/src/modules/trending/index.tsx b/apps/renderer/src/modules/trending/index.tsx index f54e640288..43453c75b6 100644 --- a/apps/renderer/src/modules/trending/index.tsx +++ b/apps/renderer/src/modules/trending/index.tsx @@ -1,6 +1,7 @@ import type { User } from "@auth/core/types" import { useQuery } from "@tanstack/react-query" import type { FC } from "react" +import { useTranslation } from "react-i18next" import { getTrendingAggregates } from "~/api/trending" import { FeedIcon } from "~/components/feed-icon" @@ -9,7 +10,7 @@ import { PhUsersBold } from "~/components/icons/users" import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar" import { ActionButton, Button } from "~/components/ui/button" import { LoadingWithIcon } from "~/components/ui/loading" -import { useModalStack } from "~/components/ui/modal" +import { useCurrentModal, useModalStack } from "~/components/ui/modal" import { DrawerModalLayout } from "~/components/ui/modal/stacked/custom-modal" import { ScrollArea } from "~/components/ui/scroll-area" import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip" @@ -23,9 +24,10 @@ import { usePresentUserProfileModal } from "../profile/hooks" export const Trend = () => { const { present } = useModalStack() + const { t } = useTranslation() return ( - Trending + {t("words.trending")} { @@ -37,7 +39,6 @@ export const Trend = () => { }} className={cn( "size-6 text-accent duration-200 hover:shadow-none", - "absolute bottom-1 right-3", )} > @@ -55,6 +56,8 @@ const TrendContent = () => { }, }) + const { t } = useTranslation() + const { dismiss } = useCurrentModal() if (!data) return (
    @@ -66,14 +69,21 @@ const TrendContent = () => { ) return (
    -
    +
    - Trending + {t("words.trending")}
    + + + @@ -88,9 +98,10 @@ const TrendingLists: FC<{ data: Models.TrendingList[] }> = ({ data }) => { const follow = useFollow() + const { t } = useTranslation() return (
    -

    Trending Lists

    +

    {t("trending.list")}

      {data.map((item) => ( @@ -155,9 +166,10 @@ const TopUserAvatar: React.FC = ({ user, position }) => ( const TrendingUsers: FC<{ data: User[] }> = ({ data }) => { const profile = usePresentUserProfileModal("dialog") + const { t } = useTranslation() return (
      -

      Trending Users

      +

      {t("trending.user")}

      @@ -215,9 +227,10 @@ const TrendingUsers: FC<{ data: User[] }> = ({ data }) => { const TrendingFeeds = ({ data }: { data: FeedModel[] }) => { const follow = useFollow() + const { t } = useTranslation() return (
      -

      Trending Feeds

      +

      {t("trending.feed")}

        {data.map((feed) => { @@ -254,7 +267,7 @@ const TrendingFeeds = ({ data }: { data: FeedModel[] }) => { follow({ isList: false, id: feed.id }) }} > - Follow + {t("feed_form.follow")}
      diff --git a/locales/app/en.json b/locales/app/en.json index 13be4a464b..606afbd7ab 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -247,6 +247,10 @@ "tip_modal.tip_support": "⭐ Tip to show your support!", "tip_modal.tip_title": "Tip Power", "tip_modal.unclaimed_feed": "No one has claimed this feed yet. The received Power will be securely held in the blockchain contract until it is claimed.", + "trending.entry": "Trending Entries", + "trending.feed": "Trending Feeds", + "trending.list": "Trending Lists", + "trending.user": "Trending Users", "user_button.account": "Account", "user_button.achievement": "Achievements", "user_button.download_desktop_app": "Download Desktop app", @@ -259,7 +263,6 @@ "user_profile.loading": "Loading", "user_profile.share": "Share", "user_profile.toggle_item_style": "Toggle Item Style", - "uu": "Mark as readdddd?", "words.achievement": "Achievements", "words.add": "Add", "words.browser": "Browser", @@ -281,6 +284,7 @@ "words.rsshub": "RSSHub", "words.search": "Search", "words.starred": "Starred", + "words.trending": "Trending", "words.undo": "Undo", "words.unread": "Unread", "words.user": "User", From 2606b43ca8cf65da5d6fda59854d4dc9f2ce2e38 Mon Sep 17 00:00:00 2001 From: Innei Date: Wed, 9 Oct 2024 05:05:26 +0000 Subject: [PATCH 7/7] chore: auto-fix linting and formatting issues --- apps/renderer/src/components/icons/crown.tsx | 2 +- apps/renderer/src/components/icons/users.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/renderer/src/components/icons/crown.tsx b/apps/renderer/src/components/icons/crown.tsx index defb1262ac..0bf2fbb10e 100644 --- a/apps/renderer/src/components/icons/crown.tsx +++ b/apps/renderer/src/components/icons/crown.tsx @@ -11,7 +11,7 @@ export function IconoirBrightCrown(props: SVGProps) { strokeLinejoin="round" strokeWidth="1.5" d="M22 12h1M12 2V1m0 22v-1m8-2l-1-1m1-15l-1 1M4 20l1-1M4 4l1 1m-4 7h1m14.8 3.5l1.2-7l-4.2 2.1L12 8.5l-1.8 2.1L6 8.5l1.2 7z" - /> + /> ) } diff --git a/apps/renderer/src/components/icons/users.tsx b/apps/renderer/src/components/icons/users.tsx index dbbc0a63b8..e36c6d9aa5 100644 --- a/apps/renderer/src/components/icons/users.tsx +++ b/apps/renderer/src/components/icons/users.tsx @@ -13,7 +13,7 @@ export function PhUsersBold(props: SVGProps) { + /> ) }