forked from Mirrors/gomuks
web/main: add support for back button
This commit is contained in:
parent
678743703c
commit
1a2833ed53
4 changed files with 56 additions and 8 deletions
|
@ -81,7 +81,7 @@ export class StateStore {
|
||||||
readonly localPreferenceCache: Preferences = getLocalStoragePreferences("global_prefs", this.preferenceSub.notify)
|
readonly localPreferenceCache: Preferences = getLocalStoragePreferences("global_prefs", this.preferenceSub.notify)
|
||||||
serverPreferenceCache: Preferences = {}
|
serverPreferenceCache: Preferences = {}
|
||||||
switchRoom?: (roomID: RoomID | null) => void
|
switchRoom?: (roomID: RoomID | null) => void
|
||||||
activeRoomID?: RoomID
|
activeRoomID: RoomID | null = null
|
||||||
imageAuthToken?: string
|
imageAuthToken?: string
|
||||||
|
|
||||||
getFilteredRoomList(): RoomListEntry[] {
|
getFilteredRoomList(): RoomListEntry[] {
|
||||||
|
@ -397,6 +397,6 @@ export class StateStore {
|
||||||
this.#watchedRoomEmojiPacks = null
|
this.#watchedRoomEmojiPacks = null
|
||||||
this.#personalEmojiPack = null
|
this.#personalEmojiPack = null
|
||||||
this.serverPreferenceCache = {}
|
this.serverPreferenceCache = {}
|
||||||
this.activeRoomID = undefined
|
this.activeRoomID = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,13 +62,13 @@ class ContextFields implements MainScreenContextFields {
|
||||||
client.store.switchRoom = this.setActiveRoom
|
client.store.switchRoom = this.setActiveRoom
|
||||||
}
|
}
|
||||||
|
|
||||||
setActiveRoom = (roomID: RoomID | null) => {
|
setActiveRoom = (roomID: RoomID | null, pushState = true) => {
|
||||||
console.log("Switching to room", roomID)
|
console.log("Switching to room", roomID)
|
||||||
const room = (roomID && this.client.store.rooms.get(roomID)) || null
|
const room = (roomID && this.client.store.rooms.get(roomID)) || null
|
||||||
window.activeRoom = room
|
window.activeRoom = room
|
||||||
this.directSetActiveRoom(room)
|
this.directSetActiveRoom(room)
|
||||||
this.setRightPanel(null)
|
this.setRightPanel(null)
|
||||||
this.client.store.activeRoomID = room?.roomID
|
this.client.store.activeRoomID = room?.roomID ?? null
|
||||||
this.keybindings.activeRoom = room
|
this.keybindings.activeRoom = room
|
||||||
if (room) {
|
if (room) {
|
||||||
room.lastOpened = Date.now()
|
room.lastOpened = Date.now()
|
||||||
|
@ -80,6 +80,9 @@ class ContextFields implements MainScreenContextFields {
|
||||||
.querySelector(`div.room-entry[data-room-id="${CSS.escape(room.roomID)}"]`)
|
.querySelector(`div.room-entry[data-room-id="${CSS.escape(room.roomID)}"]`)
|
||||||
?.scrollIntoView({ block: "nearest" })
|
?.scrollIntoView({ block: "nearest" })
|
||||||
}
|
}
|
||||||
|
if (pushState) {
|
||||||
|
history.pushState({ room_id: roomID }, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clickRoom = (evt: React.MouseEvent) => {
|
clickRoom = (evt: React.MouseEvent) => {
|
||||||
|
@ -120,6 +123,16 @@ const MainScreen = () => {
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
window.mainScreenContext = context
|
window.mainScreenContext = context
|
||||||
}, [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])
|
useEffect(() => context.keybindings.listen(), [context])
|
||||||
useInsertionEffect(() => {
|
useInsertionEffect(() => {
|
||||||
const styleTags = document.createElement("style")
|
const styleTags = document.createElement("style")
|
||||||
|
|
|
@ -44,18 +44,34 @@ export const LightboxWrapper = ({ children }: { children: React.ReactNode }) =>
|
||||||
if (!target.src) {
|
if (!target.src) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setParams({
|
params = {
|
||||||
src: target.src,
|
src: target.src,
|
||||||
alt: target.alt,
|
alt: target.alt,
|
||||||
})
|
}
|
||||||
|
setParams(params)
|
||||||
} else {
|
} else {
|
||||||
setParams(params as LightboxParams)
|
setParams(params as LightboxParams)
|
||||||
}
|
}
|
||||||
|
history.pushState({ ...(history.state ?? {}), lightbox: params }, "")
|
||||||
}, [])
|
}, [])
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
window.openLightbox = onOpen
|
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])
|
}, [onOpen])
|
||||||
const onClose = useCallback(() => setParams(null), [])
|
const onClose = useCallback(() => {
|
||||||
|
setParams(null)
|
||||||
|
if (params?.src && history.state?.lightbox?.src === params?.src) {
|
||||||
|
history.back()
|
||||||
|
}
|
||||||
|
}, [params])
|
||||||
return <>
|
return <>
|
||||||
<LightboxContext value={onOpen}>
|
<LightboxContext value={onOpen}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -41,18 +41,37 @@ export const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setState(null)
|
setState(null)
|
||||||
|
if (history.state?.modal) {
|
||||||
|
history.back()
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
const onKeyWrapper = useCallback((evt: React.KeyboardEvent<HTMLDivElement>) => {
|
const onKeyWrapper = useCallback((evt: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (evt.key === "Escape") {
|
if (evt.key === "Escape") {
|
||||||
setState(null)
|
setState(null)
|
||||||
|
if (history.state?.modal) {
|
||||||
|
history.back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
evt.stopPropagation()
|
evt.stopPropagation()
|
||||||
}, [])
|
}, [])
|
||||||
|
const openModal = useCallback((newState: ModalState) => {
|
||||||
|
if (!history.state?.modal) {
|
||||||
|
history.pushState({ ...(history.state ?? {}), modal: true }, "")
|
||||||
|
}
|
||||||
|
setState(newState)
|
||||||
|
}, [])
|
||||||
const wrapperRef = useRef<HTMLDivElement>(null)
|
const wrapperRef = useRef<HTMLDivElement>(null)
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (wrapperRef.current && (!document.activeElement || !wrapperRef.current.contains(document.activeElement))) {
|
if (wrapperRef.current && (!document.activeElement || !wrapperRef.current.contains(document.activeElement))) {
|
||||||
wrapperRef.current.focus()
|
wrapperRef.current.focus()
|
||||||
}
|
}
|
||||||
|
const listener = (evt: PopStateEvent) => {
|
||||||
|
if (!evt.state?.modal) {
|
||||||
|
setState(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener("popstate", listener)
|
||||||
|
return () => window.removeEventListener("popstate", listener)
|
||||||
}, [state])
|
}, [state])
|
||||||
let modal: JSX.Element | null = null
|
let modal: JSX.Element | null = null
|
||||||
if (state) {
|
if (state) {
|
||||||
|
@ -74,7 +93,7 @@ export const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
return <ModalContext value={setState}>
|
return <ModalContext value={openModal}>
|
||||||
{children}
|
{children}
|
||||||
{modal}
|
{modal}
|
||||||
</ModalContext>
|
</ModalContext>
|
||||||
|
|
Loading…
Add table
Reference in a new issue