Skip to content

Commit

Permalink
feat: Implement basic recommended room handling
Browse files Browse the repository at this point in the history
  • Loading branch information
criss8X committed Nov 11, 2024
1 parent ff25f3d commit 79f0c14
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 9 deletions.
15 changes: 8 additions & 7 deletions src/containers/NavigationSection/NavigationSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,25 @@ import CreateSpaceModal from "@/components/CreateSpaceModal"
import useGlobalHotkey from "@/hooks/util/useGlobalHotkey"
import {Heading, Text} from "@/components/ui/typography"
import useSpaceDetail from "@/hooks/matrix/useSpaceDetail"
import useActiveSpaceIdStore from "@/hooks/matrix/useActiveSpaceIdStore"

export const DASHBOARD_SPACE_ID = "dashboard_space_id"

const NavigationSection: FC<{className?: string; onLogOut: () => void}> = ({
className,
onLogOut,
}) => {
const [spaceSelected, setSpaceSelected] = useState(DASHBOARD_SPACE_ID)
const {activeSpaceId, setActiveSpaceId} = useActiveSpaceIdStore()
const {spaces: spacesState, onCreateSpace, uploadSpaceAvatar} = useSpaces()
const {userDataState, userData, onRefreshData} = useUserData()
const {isSmall} = useBreakpoint()
const [isCreateRoomModalOpen, setIsCreateRoomModalOpen] = useState(false)
const {activeRoomId, setActiveRoomId} = useActiveRoomIdStore()
const [modalCreateSpaceOpen, setModalCreateSpaceIsOpen] = useState(false)
const {name} = useSpaceDetail(spaceSelected)
const {name} = useSpaceDetail(activeSpaceId)

const {isSectionsLoading, sections, onCreateRoom} =
useRoomNavigator(spaceSelected)
useRoomNavigator(activeSpaceId)

useGlobalHotkey({key: "S", ctrl: true, shift: true}, () =>
setModalCreateSpaceIsOpen(true)
Expand Down Expand Up @@ -91,8 +92,8 @@ const NavigationSection: FC<{className?: string; onLogOut: () => void}> = ({
{spaces => (
<SpacesNavigation
spaces={spaces}
selectedSpace={spaceSelected}
onSelectedSpaceChange={setSpaceSelected}
selectedSpace={activeSpaceId}
onSelectedSpaceChange={setActiveSpaceId}
onCreateSpace={() => setModalCreateSpaceIsOpen(true)}
/>
)}
Expand All @@ -104,7 +105,7 @@ const NavigationSection: FC<{className?: string; onLogOut: () => void}> = ({
<div className="flex size-full flex-col border-r border-r-neutral-300 bg-neutral-100 dark:border-r-neutral-700 dark:bg-neutral-900">
<div className="border-b border-neutral-300 px-2.5 py-1.5 dark:border-neutral-700">
<Heading level="h5">
{spaceSelected === DASHBOARD_SPACE_ID ? "Dashboard" : name}
{activeSpaceId === DASHBOARD_SPACE_ID ? "Dashboard" : name}
</Heading>
</div>

Expand All @@ -116,7 +117,7 @@ const NavigationSection: FC<{className?: string; onLogOut: () => void}> = ({
roomSelected={activeRoomId ?? undefined}
onRoomSelected={setActiveRoomId}
sections={sections}
isDashboardActive={spaceSelected === undefined}
isDashboardActive={activeSpaceId === undefined}
isLoading={isSectionsLoading}
onCreateRoom={() => setIsCreateRoomModalOpen(true)}
/>
Expand Down
54 changes: 52 additions & 2 deletions src/containers/RoomContainer/hooks/useActiveRoom.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import useActiveRoomIdStore from "@/hooks/matrix/useActiveRoomIdStore"
import {useCallback, useEffect, useState} from "react"
import {KnownMembership} from "matrix-js-sdk/lib/@types/membership"
import {type MatrixClient, Room, RoomMemberEvent} from "matrix-js-sdk"
import {JoinRule, type MatrixClient, Room, RoomMemberEvent} from "matrix-js-sdk"
import useEventListener from "@/hooks/matrix/useEventListener"
import useMatrixClient from "@/hooks/matrix/useMatrixClient"
import useValueState, {ValueState} from "@/hooks/util/useValueState"
Expand All @@ -14,6 +14,9 @@ import {getImageUrl, getRoomTopic} from "@/utils/matrix"
import {isDirectRoom} from "@/utils/rooms"
import {getOwnersIdWithPowerLevels} from "@/utils/members"
import {strCapitalize} from "@/utils/util"
import useActiveSpaceIdStore from "@/hooks/matrix/useActiveSpaceIdStore"
import {DASHBOARD_SPACE_ID} from "@/containers/NavigationSection/SpacesNavigation"
import {IHierarchyRoom} from "matrix-js-sdk/lib/@types/spaces"

export enum RoomState {
Idle,
Expand Down Expand Up @@ -95,10 +98,24 @@ async function getRoomOwners(room: Room): Promise<RoomDetailOwner[] | null> {
return owners.length === 0 ? null : owners
}

export function validateHierarchyRoom(foundedRoom: IHierarchyRoom): void {
if (foundedRoom.room_type === "m.space") {
throw new RoomInvitedError("You cannot access the same parent space.")
}

if (
foundedRoom.join_rule !== JoinRule.Public &&
!foundedRoom.guest_can_join
) {
throw new RoomInvitedError("This room does not allow anyone to join.")
}
}

const useActiveRoom = (): UseActiveRoomReturnType => {
const client = useMatrixClient()
const [roomState, setRoomState] = useState(RoomState.Idle)
const {activeRoomId, clearActiveRoomId} = useActiveRoomIdStore()
const {activeSpaceId} = useActiveSpaceIdStore()

const [roomInvitedDetail, setRoomInvitedDetail] =
useValueState<RoomDetailPreview>()
Expand Down Expand Up @@ -135,6 +152,39 @@ const useActiveRoom = (): UseActiveRoomReturnType => {

const room = client.getRoom(activeRoomId)

if (activeSpaceId !== DASHBOARD_SPACE_ID && room === null) {
const space = client.getRoom(activeSpaceId)

setRoomInvitedDetailScope(async () => {
if (space === null) {
throw new RoomInvitedError("You not have access to this space.")
}

const hierarchy = await client.getRoomHierarchy(space.roomId)

const foundedRoom = hierarchy.rooms.find(
hierarchyRoom => hierarchyRoom.room_id === activeRoomId
)

if (foundedRoom === undefined) {
throw new RoomInvitedError(
"You do not have access to the room or it does not exist."
)
}

validateHierarchyRoom(foundedRoom)

return {
name: foundedRoom.name ?? foundedRoom.room_id,
topic: foundedRoom.topic,
avatarUrl: getImageUrl(foundedRoom.avatar_url, client),
detailChips: [],
}
})

return
}

setRoomInvitedDetailScope(async () => {
if (room === null) {
throw new RoomInvitedError("You not have access to this room.")
Expand All @@ -151,7 +201,7 @@ const useActiveRoom = (): UseActiveRoomReturnType => {
owners: owners ?? undefined,
}
})
}, [activeRoomId, client, setRoomInvitedDetailScope])
}, [activeRoomId, activeSpaceId, client, setRoomInvitedDetailScope])

useEffect(() => {
if (client === null || activeRoomId === null) {
Expand Down
20 changes: 20 additions & 0 deletions src/hooks/matrix/useActiveSpaceIdStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {DASHBOARD_SPACE_ID} from "@/containers/NavigationSection/SpacesNavigation"
import {create} from "zustand"

type ActiveSpaceIdStore = {
activeSpaceId: string
clearActiveSpaceId: () => void
setActiveSpaceId: (spaceId: string) => void
}

const useActiveSpaceIdStore = create<ActiveSpaceIdStore>(set => ({
activeSpaceId: DASHBOARD_SPACE_ID,
clearActiveSpaceId() {
set(_state => ({activeSpaceId: DASHBOARD_SPACE_ID}))
},
setActiveSpaceId(spaceId) {
set(_state => ({activeSpaceId: spaceId}))
},
}))

export default useActiveSpaceIdStore

0 comments on commit 79f0c14

Please sign in to comment.