chore: online user count
This commit is contained in:
parent
3d45e4609c
commit
ad2278f5ba
5 changed files with 106 additions and 9 deletions
|
@ -1,14 +1,11 @@
|
|||
import { type ReactNode, type FC } from 'react'
|
||||
import useResizable from '@/hooks/useResizable'
|
||||
import useBreakpoint from '@/hooks/useBreakpoint'
|
||||
|
||||
export interface AppContainerProps {
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
const AppContainer: FC<AppContainerProps> = ({ children }) => {
|
||||
const { breakpoint } = useBreakpoint()
|
||||
console.log(breakpoint)
|
||||
|
||||
const { size, ref } = useResizable({
|
||||
initSize: Math.max(375, window.innerWidth / 5),
|
||||
maxSize: Math.max(750, window.innerWidth / 3),
|
||||
|
|
|
@ -4,9 +4,13 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/Avatar'
|
|||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/HoverCard'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { getSiteInfo } from '@/utils'
|
||||
import { useRemeshDomain, useRemeshQuery } from 'remesh-react'
|
||||
import RoomDomain from '@/domain/Room'
|
||||
|
||||
const Header: FC = () => {
|
||||
const siteInfo = getSiteInfo()
|
||||
const roomDomain = useRemeshDomain(RoomDomain())
|
||||
const peerList = useRemeshQuery(roomDomain.query.PeerListQuery())
|
||||
|
||||
return (
|
||||
<div className="z-10 grid h-12 grid-flow-col items-center justify-between gap-x-4 rounded-t-xl bg-white px-4 backdrop-blur-lg">
|
||||
|
@ -41,7 +45,7 @@ const Header: FC = () => {
|
|||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
<div className="text-sm text-slate-500">Online 99</div>
|
||||
<div className="text-sm text-slate-500">Online {peerList.length}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -41,6 +41,19 @@ const RoomDomain = Remesh.domain({
|
|||
const peerRoom = domain.getExtern(PeerRoomExtern)
|
||||
peerRoom.joinRoom(hostRoomId)
|
||||
|
||||
const PeersListState = domain.state<string[]>({
|
||||
name: 'Room.PeersListState',
|
||||
default: [peerRoom.selfId]
|
||||
})
|
||||
|
||||
const MessageListQuery = messageListDomain.query.ListQuery
|
||||
const PeerListQuery = domain.query({
|
||||
name: 'Room.PeerListQuery',
|
||||
impl: ({ get }) => {
|
||||
return get(PeersListState())
|
||||
}
|
||||
})
|
||||
|
||||
const SendTextMessageCommand = domain.command({
|
||||
name: 'RoomSendTextMessageCommand',
|
||||
impl: ({ get }, message: string) => {
|
||||
|
@ -113,6 +126,21 @@ const RoomDomain = Remesh.domain({
|
|||
name: 'RoomSendHateMessageEvent'
|
||||
})
|
||||
|
||||
const JoinRoomEvent = domain.event<string>({
|
||||
name: 'RoomJoinRoomEvent'
|
||||
})
|
||||
|
||||
const LeaveRoomEvent = domain.event<string>({
|
||||
name: 'RoomLeaveRoomEvent'
|
||||
})
|
||||
|
||||
const SyncPeersListCommand = domain.command({
|
||||
name: 'RoomSyncPeersListCommand',
|
||||
impl: (_, list: string[]) => {
|
||||
return [PeersListState().new(list)]
|
||||
}
|
||||
})
|
||||
|
||||
domain.effect({
|
||||
name: 'RoomSendTextMessageEffect',
|
||||
impl: ({ fromEvent }) => {
|
||||
|
@ -200,11 +228,40 @@ const RoomDomain = Remesh.domain({
|
|||
}
|
||||
})
|
||||
|
||||
domain.effect({
|
||||
name: 'RoomOnJoinRoomEffect',
|
||||
impl: ({ get }) => {
|
||||
const onJoinRoom$ = callbackToObservable<string>(peerRoom.onJoinRoom.bind(peerRoom))
|
||||
return onJoinRoom$.pipe(
|
||||
map((peerId) => {
|
||||
return [SyncPeersListCommand([...get(PeersListState()), peerId]), JoinRoomEvent(peerId)]
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
domain.effect({
|
||||
name: 'RoomOnLeaveRoomEffect',
|
||||
impl: ({ get }) => {
|
||||
const onLeaveRoom$ = callbackToObservable<string>(peerRoom.onLeaveRoom.bind(peerRoom))
|
||||
return onLeaveRoom$.pipe(
|
||||
map((peerId) => {
|
||||
return [SyncPeersListCommand(get(PeersListState()).filter((id) => id !== peerId)), LeaveRoomEvent(peerId)]
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
return {
|
||||
query: {
|
||||
PeerListQuery,
|
||||
MessageListQuery
|
||||
},
|
||||
event: {
|
||||
SendTextMessageEvent,
|
||||
SendLikeMessageEvent,
|
||||
SendHateMessageEvent
|
||||
SendHateMessageEvent,
|
||||
JoinRoomEvent,
|
||||
LeaveRoomEvent
|
||||
},
|
||||
command: {
|
||||
SendTextMessageCommand,
|
||||
|
|
|
@ -4,14 +4,19 @@ import { type Promisable } from 'type-fest'
|
|||
export type PeerMessage = object | Blob | ArrayBuffer | ArrayBufferView
|
||||
|
||||
export interface PeerRoom {
|
||||
readonly selfId: string
|
||||
joinRoom: (roomId: string) => Promise<any>
|
||||
sendMessage: <T extends PeerMessage>(message: T) => Promise<any>
|
||||
onMessage: <T extends PeerMessage>(callback: (message: T) => void) => Promisable<void>
|
||||
leaveRoom: () => Promisable<void>
|
||||
onJoinRoom: (callback: (id: string) => void) => Promisable<void>
|
||||
onLeaveRoom: (callback: (id: string) => void) => Promisable<void>
|
||||
getRoomPeers: () => string[]
|
||||
}
|
||||
|
||||
export const PeerRoomExtern = Remesh.extern<PeerRoom>({
|
||||
default: {
|
||||
selfId: '',
|
||||
joinRoom: async () => {
|
||||
throw new Error('"joinRoom" not implemented.')
|
||||
},
|
||||
|
@ -23,6 +28,15 @@ export const PeerRoomExtern = Remesh.extern<PeerRoom>({
|
|||
},
|
||||
leaveRoom: () => {
|
||||
throw new Error('"leaveRoom" not implemented.')
|
||||
},
|
||||
onJoinRoom: () => {
|
||||
throw new Error('"onJoinRoom" not implemented.')
|
||||
},
|
||||
onLeaveRoom: () => {
|
||||
throw new Error('"onLeaveRoom" not implemented.')
|
||||
},
|
||||
getRoomPeers: () => {
|
||||
throw new Error('"getRoomPeers" not implemented.')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { type DataPayload, type Room, joinRoom } from 'trystero'
|
||||
import { type DataPayload, type Room, joinRoom, selfId } from 'trystero'
|
||||
|
||||
// import { joinRoom } from 'trystero/firebase'
|
||||
import { PeerRoomExtern, type PeerMessage } from '@/domain/externs/PeerRoom'
|
||||
|
@ -11,17 +11,21 @@ export interface Config {
|
|||
class PeerRoom {
|
||||
readonly appId: string
|
||||
room: Room | null
|
||||
readonly selfId: string
|
||||
constructor(config: Config) {
|
||||
this.appId = config.appId
|
||||
this.room = null
|
||||
this.selfId = selfId
|
||||
}
|
||||
|
||||
async joinRoom(roomId: string) {
|
||||
this.room = joinRoom({ appId: this.appId }, roomId)
|
||||
|
||||
this.room?.onPeerJoin((peerId) => console.log(`${peerId} joined`))
|
||||
this.room?.onPeerJoin((peerId) => {
|
||||
console.log(`${peerId} joined`)
|
||||
console.log(this.room?.getPeers())
|
||||
})
|
||||
this.room?.onPeerLeave((peerId) => console.log(`${peerId} leaved`))
|
||||
console.log(this.room.getPeers())
|
||||
|
||||
return this.room
|
||||
}
|
||||
|
@ -42,6 +46,27 @@ class PeerRoom {
|
|||
on((message) => callback(message as T))
|
||||
}
|
||||
|
||||
onJoinRoom(callback: (id: string) => void) {
|
||||
if (!this.room) {
|
||||
throw new Error('Room not joined')
|
||||
}
|
||||
this.room.onPeerJoin((peerId) => callback(peerId))
|
||||
}
|
||||
|
||||
onLeaveRoom(callback: (id: string) => void) {
|
||||
if (!this.room) {
|
||||
throw new Error('Room not joined')
|
||||
}
|
||||
this.room.onPeerLeave((peerId) => callback(peerId))
|
||||
}
|
||||
|
||||
getRoomPeers() {
|
||||
if (!this.room) {
|
||||
throw new Error('Room not joined')
|
||||
}
|
||||
return Object.keys(this.room.getPeers()).map((id) => id)
|
||||
}
|
||||
|
||||
async leaveRoom() {
|
||||
return await this.room?.leave()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue