Skip to content

Commit

Permalink
web: switch to first matching space when opening room
Browse files Browse the repository at this point in the history
Fixes #582
  • Loading branch information
tulir committed Jan 3, 2025
1 parent 39cb5f2 commit 5d25d83
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 13 deletions.
18 changes: 17 additions & 1 deletion web/src/api/statestore/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
} from "../types"
import { InvitedRoomStore } from "./invitedroom.ts"
import { RoomStateStore } from "./room.ts"
import { DirectChatSpace, RoomListFilter, SpaceEdgeStore, SpaceOrphansSpace, UnreadsSpace } from "./space.ts"
import { DirectChatSpace, RoomListFilter, Space, SpaceEdgeStore, SpaceOrphansSpace, UnreadsSpace } from "./space.ts"

export interface RoomListEntry {
room_id: RoomID
Expand Down Expand Up @@ -128,6 +128,22 @@ export class StateStore {
return null
}

findMatchingSpace(room: RoomListEntry): Space | null {
if (this.spaceOrphans.include(room)) {
return this.spaceOrphans
}
for (const spaceID of this.topLevelSpaces.current) {
const space = this.spaceEdges.get(spaceID)
if (space?.include(room)) {
return space
}
}
if (this.directChatsSpace.include(room)) {
return this.directChatsSpace
}
return null
}

get roomListFilterFunc(): ((entry: RoomListEntry) => boolean) | null {
if (!this.currentRoomListFilter && !this.currentRoomListQuery) {
return null
Expand Down
32 changes: 24 additions & 8 deletions web/src/ui/MainScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,17 @@ class ContextFields implements MainScreenContextFields {
}
}

setActiveRoom = (roomID: RoomID | null, previewMeta?: Partial<RoomPreviewProps>, pushState = true) => {
setActiveRoom = (
roomID: RoomID | null,
previewMeta?: Partial<RoomPreviewProps>,
toSpace?: RoomListFilter,
pushState = true,
) => {
console.log("Switching to room", roomID)
if (roomID) {
const room = this.client.store.rooms.get(roomID)
if (room) {
this.#setActiveRoom(room, pushState)
this.#setActiveRoom(room, toSpace, pushState)
} else {
this.#setPreviewRoom(roomID, pushState, previewMeta)
}
Expand Down Expand Up @@ -151,10 +156,21 @@ class ContextFields implements MainScreenContextFields {
return room.preferences.room_window_title.replace("$room", name!)
}

#setActiveRoom(room: RoomStateStore, pushState: boolean) {
#setActiveRoom(room: RoomStateStore, space: RoomListFilter | undefined | null, pushState: boolean) {
window.activeRoom = room
this.directSetActiveRoom(room)
this.directSetRightPanel(null)
if (!space && this.client.store.currentRoomListFilter) {
const roomListEntry = this.client.store.roomListEntries.get(room.roomID)
if (roomListEntry && !this.client.store.currentRoomListFilter.include(roomListEntry)) {
space = this.client.store.findMatchingSpace(roomListEntry)
}
}
if (space && space !== this.client.store.currentRoomListFilter) {
console.log("Switching to space", space?.id)
this.directSetSpace(space)
this.client.store.currentRoomListFilter = space
}
this.rightPanelStack = []
this.client.store.activeRoomID = room.roomID
this.client.store.activeRoomIsPreview = false
Expand All @@ -168,7 +184,7 @@ class ContextFields implements MainScreenContextFields {
.querySelector(`div.room-entry[data-room-id="${CSS.escape(room.roomID)}"]`)
?.scrollIntoView({ block: "nearest" })
if (pushState) {
history.pushState({ room_id: room.roomID, space_id: history.state?.space_id }, "")
history.pushState({ room_id: room.roomID, space_id: space?.id ?? history.state?.space_id }, "")
}
let roomNameForTitle = room.meta.current.name
if (roomNameForTitle && roomNameForTitle.length > 48) {
Expand Down Expand Up @@ -217,7 +233,7 @@ class ContextFields implements MainScreenContextFields {

const SYNC_ERROR_HIDE_DELAY = 30 * 1000

const handleURLHash = (client: Client) => {
const handleURLHash = (client: Client, context: MainScreenContextFields) => {
if (!location.hash.startsWith("#/uri/")) {
if (location.search) {
const currentETag = (
Expand Down Expand Up @@ -268,7 +284,7 @@ const handleURLHash = (client: Client) => {
// TODO loading indicator or something for this?
client.rpc.resolveAlias(uri.identifier).then(
res => {
window.mainScreenContext.setActiveRoom(res.room_id, {
context.setActiveRoom(res.room_id, {
alias: uri.identifier,
via: res.servers.slice(0, 3),
})
Expand Down Expand Up @@ -321,13 +337,13 @@ const MainScreen = () => {
context.setActiveRoom(roomID, {
alias: ensureString(evt.state?.source_alias) || undefined,
via: ensureStringArray(evt.state?.source_via),
}, false)
}, undefined, false)
}
context.setRightPanel(evt.state?.right_panel ?? null, false)
}
window.addEventListener("popstate", listener)
const initHandle = () => {
const state = handleURLHash(client)
const state = handleURLHash(client, context)
listener({ state } as PopStateEvent)
}
let cancel = () => {}
Expand Down
4 changes: 2 additions & 2 deletions web/src/ui/MainScreenContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import { createContext } from "react"
import React, { createContext } from "react"
import { RoomListFilter } from "@/api/statestore"
import type { RoomID } from "@/api/types"
import type { RightPanelProps } from "./rightpanel/RightPanel.tsx"
import type { RoomPreviewProps } from "./roomview/RoomPreview.tsx"

export interface MainScreenContextFields {
setActiveRoom: (roomID: RoomID | null, previewMeta?: Partial<RoomPreviewProps>) => void
setActiveRoom: (roomID: RoomID | null, previewMeta?: Partial<RoomPreviewProps>, toSpace?: RoomListFilter) => void
setSpace: (space: RoomListFilter | null, pushState?: boolean) => void
clickRoom: (evt: React.MouseEvent) => void
clearActiveRoom: () => void
Expand Down
3 changes: 1 addition & 2 deletions web/src/ui/roomlist/RoomList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ const RoomList = ({ activeRoomID, space }: RoomListProps) => {
for (let i = client.store.roomList.current.length - 1; i >= 0; i--) {
const entry = client.store.roomList.current[i]
if (entry[wantedField] > 0 && space.include(entry)) {
mainScreen.setActiveRoom(entry.room_id)
mainScreen.setSpace(space)
mainScreen.setActiveRoom(entry.room_id, undefined, space)
evt.stopPropagation()
break
}
Expand Down

0 comments on commit 5d25d83

Please sign in to comment.