Skip to content

Commit 4426fa6

Browse files
committed
feat: add activity rooms
Signed-off-by: Innei <[email protected]>
1 parent 212aa05 commit 4426fa6

File tree

7 files changed

+127
-23
lines changed

7 files changed

+127
-23
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"@milkdown/react": "7.3.3",
5555
"@milkdown/transformer": "7.3.3",
5656
"@milkdown/utils": "7.3.3",
57-
"@mx-space/api-client": "1.8.0-alpha.4",
57+
"@mx-space/api-client": "1.8.0-alpha.6",
5858
"@prosemirror-adapter/react": "0.2.6",
5959
"@radix-ui/react-dialog": "1.0.5",
6060
"@radix-ui/react-label": "2.0.2",

pnpm-lock.yaml

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/layout/footer/FooterInfo.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ const FooterBottom = async () => {
181181
Stay hungry. Stay foolish.
182182
</span>
183183
</p>
184-
<p>
184+
<div>
185185
<PoweredBy className="my-3 block md:my-0 md:inline" />
186186
{icp && (
187187
<>
@@ -206,7 +206,7 @@ const FooterBottom = async () => {
206206
</span>
207207
</>
208208
)} */}
209-
</p>
209+
</div>
210210
</div>
211211
)
212212
}

src/components/layout/footer/GatewayCount.tsx

+111-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use client'
22

3+
import { useQuery } from '@tanstack/react-query'
4+
35
import { useOnlineCount } from '~/atoms'
46
import { useSocketIsConnect } from '~/atoms/hooks'
57
import { ImpressionView } from '~/components/common/ImpressionTracker'
@@ -8,14 +10,18 @@ import { FloatPopover } from '~/components/ui/float-popover'
810
import { NumberSmoothTransition } from '~/components/ui/number-transition/NumberSmoothTransition'
911
import { TrackerAction } from '~/constants/tracker'
1012
import { usePageIsActive } from '~/hooks/common/use-is-active'
13+
import { apiClient } from '~/lib/request'
14+
import { routeBuilder, Routes } from '~/lib/route-builder'
1115

12-
export const GatewayCount = () => {
16+
const Help = () => {
1317
return (
1418
<FloatPopover
1519
as="span"
16-
TriggerComponent={GatewayCountTrigger}
20+
triggerElement={
21+
<i className="icon-[mingcute--question-line] cursor-help" />
22+
}
1723
type="tooltip"
18-
wrapperClassName="cursor-help"
24+
asChild
1925
>
2026
<div className="space-y-2 leading-relaxed">
2127
<p className="flex items-center space-x-1 opacity-80">
@@ -77,18 +83,112 @@ const ConnectedIndicator = () => {
7783
)
7884
}
7985

80-
const GatewayCountTrigger = () => {
86+
export const GatewayCount = () => {
8187
const isActive = usePageIsActive()
8288
const count = useOnlineCount()
8389

8490
if (!isActive) return null
8591
return (
86-
<span key={count}>
87-
正在被{' '}
88-
<span>
89-
<NumberSmoothTransition>{count}</NumberSmoothTransition>
90-
</span>{' '}
91-
人看爆
92-
</span>
92+
<div className="inline-flex items-center gap-2">
93+
<FloatPopover
94+
asChild
95+
placement="top"
96+
offset={10}
97+
triggerElement={
98+
<span key={count} className="cursor-pointer">
99+
正在被{' '}
100+
<span>
101+
<NumberSmoothTransition>{count}</NumberSmoothTransition>
102+
</span>{' '}
103+
人看爆
104+
</span>
105+
}
106+
>
107+
<RoomsInfo />
108+
</FloatPopover>
109+
<Help />
110+
</div>
111+
)
112+
}
113+
114+
const RoomsInfo = () => {
115+
const { data } = useQuery({
116+
queryKey: ['rooms'],
117+
refetchOnMount: true,
118+
queryFn: () => {
119+
return apiClient.activity
120+
.getRoomsInfo()
121+
.then((res) => res.$serialized)
122+
.then((data) => {
123+
const result = [] as {
124+
path: string
125+
title: string
126+
count: number
127+
}[]
128+
129+
const morphArticleIdToRoomName = (id: string) => `article_${id}`
130+
data.objects.notes.forEach((note) => {
131+
result.push({
132+
path: routeBuilder(Routes.Note, {
133+
id: note.nid,
134+
}),
135+
title: note.title,
136+
count: data.roomCount[morphArticleIdToRoomName(note.id)],
137+
})
138+
})
139+
140+
data.objects.posts.forEach((post) => {
141+
result.push({
142+
path: routeBuilder(Routes.Post, {
143+
category: post.category.slug,
144+
slug: post.slug,
145+
}),
146+
title: post.title,
147+
count: data.roomCount[morphArticleIdToRoomName(post.id)],
148+
})
149+
})
150+
151+
data.objects.pages.forEach((page) => {
152+
result.push({
153+
path: routeBuilder(Routes.Page, {
154+
slug: page.slug,
155+
}),
156+
title: page.title,
157+
count: data.roomCount[morphArticleIdToRoomName(page.id)],
158+
})
159+
})
160+
161+
return result.sort((a, b) => b.count - a.count)
162+
})
163+
},
164+
})
165+
166+
if (!data) return <div className="loading loading-spinner" />
167+
if (data.length === 0)
168+
return <div className="text-gray-500">还没有人在偷偷观察哦~</div>
169+
return (
170+
<div className="max-w-[80vw] lg:max-w-[400px]">
171+
<div className="mb-2 text-sm font-medium">下面的内容正在被看爆:</div>
172+
<ul className="flex flex-col justify-between gap-2">
173+
{data.map((room) => (
174+
<li key={room.path} className="flex items-center justify-between">
175+
<a
176+
target="_blank"
177+
href={room.path}
178+
className="hover:underline"
179+
rel="noreferrer"
180+
>
181+
{room.title}
182+
</a>
183+
{!!room.count && (
184+
<span className="ml-5 inline-flex items-center text-sm text-gray-500">
185+
<i className="icon-[mingcute--user-visible-line]" />{' '}
186+
{room.count}
187+
</span>
188+
)}
189+
</li>
190+
))}
191+
</ul>
192+
</div>
93193
)
94194
}

src/components/modules/activity/Presence.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import { useIsDark } from '~/hooks/common/use-is-dark'
3535
import { useReadPercent } from '~/hooks/shared/use-read-percent'
3636
import { getColorScheme, stringToHue } from '~/lib/color'
3737
import { formatSeconds } from '~/lib/datetime'
38-
import { debounce } from '~/lib/lodash'
38+
import { debounce, uniq } from '~/lib/lodash'
3939
import { apiClient } from '~/lib/request'
4040
import { springScrollTo } from '~/lib/scroller'
4141
import {
@@ -142,7 +142,7 @@ const ReadPresenceTimeline = () => {
142142
return (
143143
<RootPortal>
144144
<div className="group fixed bottom-20 left-0 top-20 z-[3]">
145-
{activityPresenceIdsCurrentRoom.map((identity) => {
145+
{uniq(activityPresenceIdsCurrentRoom).map((identity) => {
146146
return (
147147
<TimelineItem
148148
key={identity}

src/components/modules/post/PostItem.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export const PostItem = memo<{ data: PostModel }>(function PostItem({ data }) {
3030

3131
<PostPinIcon pin={!!data.pin} id={data.id} />
3232
</h2>
33-
<main className="relative mt-8 space-y-2">
33+
<div className="relative mt-8 space-y-2">
3434
{!!data.summary && (
35-
<p className="break-all leading-relaxed text-gray-900 dark:text-zinc-50">
35+
<p className="mb-4 break-all rounded-md px-4 py-2 text-sm leading-relaxed text-gray-900 ring-1 ring-accent/10 dark:text-zinc-50">
3636
摘要: {data.summary}
3737
</p>
3838
)}
@@ -50,7 +50,7 @@ export const PostItem = memo<{ data: PostModel }>(function PostItem({ data }) {
5050
{displayText}
5151
</p>
5252
</div>
53-
</main>
53+
</div>
5454

5555
<div className="post-meta-bar mt-2 flex select-none flex-wrap items-center justify-end gap-4 text-base-content/60">
5656
<PostMetaBar meta={data} />

src/lib/lodash.ts

+4
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,7 @@ export function get(target: object, path: string) {
168168
}
169169
return result
170170
}
171+
172+
export const uniq = <T>(arr: T[]): T[] => {
173+
return Array.from(new Set(arr))
174+
}

0 commit comments

Comments
 (0)