1
0
Fork 0
forked from Mirrors/gomuks

web/main: add support for back button

This commit is contained in:
Tulir Asokan 2024-12-04 01:22:16 +02:00
parent 678743703c
commit 1a2833ed53
4 changed files with 56 additions and 8 deletions

View file

@ -81,7 +81,7 @@ export class StateStore {
readonly localPreferenceCache: Preferences = getLocalStoragePreferences("global_prefs", this.preferenceSub.notify)
serverPreferenceCache: Preferences = {}
switchRoom?: (roomID: RoomID | null) => void
activeRoomID?: RoomID
activeRoomID: RoomID | null = null
imageAuthToken?: string
getFilteredRoomList(): RoomListEntry[] {
@ -397,6 +397,6 @@ export class StateStore {
this.#watchedRoomEmojiPacks = null
this.#personalEmojiPack = null
this.serverPreferenceCache = {}
this.activeRoomID = undefined
this.activeRoomID = null
}
}

View file

@ -62,13 +62,13 @@ class ContextFields implements MainScreenContextFields {
client.store.switchRoom = this.setActiveRoom
}
setActiveRoom = (roomID: RoomID | null) => {
setActiveRoom = (roomID: RoomID | null, pushState = true) => {
console.log("Switching to room", roomID)
const room = (roomID && this.client.store.rooms.get(roomID)) || null
window.activeRoom = room
this.directSetActiveRoom(room)
this.setRightPanel(null)
this.client.store.activeRoomID = room?.roomID
this.client.store.activeRoomID = room?.roomID ?? null
this.keybindings.activeRoom = room
if (room) {
room.lastOpened = Date.now()
@ -80,6 +80,9 @@ class ContextFields implements MainScreenContextFields {
.querySelector(`div.room-entry[data-room-id="${CSS.escape(room.roomID)}"]`)
?.scrollIntoView({ block: "nearest" })
}
if (pushState) {
history.pushState({ room_id: roomID }, "")
}
}
clickRoom = (evt: React.MouseEvent) => {
@ -120,6 +123,16 @@ const MainScreen = () => {
useLayoutEffect(() => {
window.mainScreenContext = context
}, [context])
useEffect(() => {
const listener = (evt: PopStateEvent) => {
const roomID = evt.state?.room_id ?? null
if (roomID !== client.store.activeRoomID) {
context.setActiveRoom(roomID, false)
}
}
window.addEventListener("popstate", listener)
return () => window.removeEventListener("popstate", listener)
}, [context, client])
useEffect(() => context.keybindings.listen(), [context])
useInsertionEffect(() => {
const styleTags = document.createElement("style")

View file

@ -44,18 +44,34 @@ export const LightboxWrapper = ({ children }: { children: React.ReactNode }) =>
if (!target.src) {
return
}
setParams({
params = {
src: target.src,
alt: target.alt,
})
}
setParams(params)
} else {
setParams(params as LightboxParams)
}
history.pushState({ ...(history.state ?? {}), lightbox: params }, "")
}, [])
useLayoutEffect(() => {
window.openLightbox = onOpen
const listener = (evt: PopStateEvent) => {
if (evt.state?.lightbox) {
setParams(evt.state.lightbox)
} else {
setParams(null)
}
}
window.addEventListener("popstate", listener)
return () => window.removeEventListener("popstate", listener)
}, [onOpen])
const onClose = useCallback(() => setParams(null), [])
const onClose = useCallback(() => {
setParams(null)
if (params?.src && history.state?.lightbox?.src === params?.src) {
history.back()
}
}, [params])
return <>
<LightboxContext value={onOpen}>
{children}

View file

@ -41,18 +41,37 @@ export const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
return
}
setState(null)
if (history.state?.modal) {
history.back()
}
}, [])
const onKeyWrapper = useCallback((evt: React.KeyboardEvent<HTMLDivElement>) => {
if (evt.key === "Escape") {
setState(null)
if (history.state?.modal) {
history.back()
}
}
evt.stopPropagation()
}, [])
const openModal = useCallback((newState: ModalState) => {
if (!history.state?.modal) {
history.pushState({ ...(history.state ?? {}), modal: true }, "")
}
setState(newState)
}, [])
const wrapperRef = useRef<HTMLDivElement>(null)
useLayoutEffect(() => {
if (wrapperRef.current && (!document.activeElement || !wrapperRef.current.contains(document.activeElement))) {
wrapperRef.current.focus()
}
const listener = (evt: PopStateEvent) => {
if (!evt.state?.modal) {
setState(null)
}
}
window.addEventListener("popstate", listener)
return () => window.removeEventListener("popstate", listener)
}, [state])
let modal: JSX.Element | null = null
if (state) {
@ -74,7 +93,7 @@ export const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
{content}
</div>
}
return <ModalContext value={setState}>
return <ModalContext value={openModal}>
{children}
{modal}
</ModalContext>