mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-19 18:13:41 -05:00
web/modal: don't capture input in context menu modal
This commit is contained in:
parent
f83b914af0
commit
08a1712850
5 changed files with 38 additions and 15 deletions
|
@ -13,7 +13,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// 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/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import React, { JSX, useCallback, useLayoutEffect, useReducer, useRef } from "react"
|
import React, { JSX, useCallback, useEffect, useLayoutEffect, useReducer, useRef } from "react"
|
||||||
import { ModalCloseContext, ModalContext, ModalState } from "./contexts.ts"
|
import { ModalCloseContext, ModalContext, ModalState } from "./contexts.ts"
|
||||||
|
|
||||||
const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
@ -40,7 +40,7 @@ const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
evt.stopPropagation()
|
evt.stopPropagation()
|
||||||
}
|
}
|
||||||
const openModal = useCallback((newState: ModalState) => {
|
const openModal = useCallback((newState: ModalState) => {
|
||||||
if (!history.state?.modal) {
|
if (!history.state?.modal && newState.captureInput !== false) {
|
||||||
history.pushState({ ...(history.state ?? {}), modal: true }, "")
|
history.pushState({ ...(history.state ?? {}), modal: true }, "")
|
||||||
}
|
}
|
||||||
setState(newState)
|
setState(newState)
|
||||||
|
@ -50,6 +50,9 @@ const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
}, [state])
|
||||||
|
useEffect(() => {
|
||||||
|
window.closeModal = onClickWrapper
|
||||||
const listener = (evt: PopStateEvent) => {
|
const listener = (evt: PopStateEvent) => {
|
||||||
if (!evt.state?.modal) {
|
if (!evt.state?.modal) {
|
||||||
setState(null)
|
setState(null)
|
||||||
|
@ -57,7 +60,7 @@ const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
}
|
}
|
||||||
window.addEventListener("popstate", listener)
|
window.addEventListener("popstate", listener)
|
||||||
return () => window.removeEventListener("popstate", listener)
|
return () => window.removeEventListener("popstate", listener)
|
||||||
}, [state])
|
}, [])
|
||||||
let modal: JSX.Element | null = null
|
let modal: JSX.Element | null = null
|
||||||
if (state) {
|
if (state) {
|
||||||
let content = <ModalCloseContext value={onClickWrapper}>{state.content}</ModalCloseContext>
|
let content = <ModalCloseContext value={onClickWrapper}>{state.content}</ModalCloseContext>
|
||||||
|
@ -68,15 +71,19 @@ const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
modal = <div
|
if (state.captureInput !== false) {
|
||||||
className={`overlay modal ${state.dimmed ? "dimmed" : ""}`}
|
modal = <div
|
||||||
onClick={onClickWrapper}
|
className={`overlay modal ${state.dimmed ? "dimmed" : ""}`}
|
||||||
onKeyDown={onKeyWrapper}
|
onClick={onClickWrapper}
|
||||||
tabIndex={-1}
|
onKeyDown={onKeyWrapper}
|
||||||
ref={wrapperRef}
|
tabIndex={-1}
|
||||||
>
|
ref={wrapperRef}
|
||||||
{content}
|
>
|
||||||
</div>
|
{content}
|
||||||
|
</div>
|
||||||
|
} else {
|
||||||
|
modal = content
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return <ModalContext value={openModal}>
|
return <ModalContext value={openModal}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -32,6 +32,7 @@ export interface ModalState {
|
||||||
boxClass?: string
|
boxClass?: string
|
||||||
innerBoxClass?: string
|
innerBoxClass?: string
|
||||||
onClose?: () => void
|
onClose?: () => void
|
||||||
|
captureInput?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type openModal = (state: ModalState) => void
|
type openModal = (state: ModalState) => void
|
||||||
|
|
|
@ -107,9 +107,21 @@ const TimelineEvent = ({ evt, prevEvt, disableMenu, smallReplies }: TimelineEven
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mouseEvt.preventDefault()
|
mouseEvt.preventDefault()
|
||||||
openModal({
|
if (window.hackyOpenEventContextMenu === evt.event_id) {
|
||||||
content: <EventFixedMenu evt={evt} roomCtx={roomCtx} />,
|
window.closeModal()
|
||||||
})
|
window.hackyOpenEventContextMenu = undefined
|
||||||
|
} else {
|
||||||
|
openModal({
|
||||||
|
content: <EventFixedMenu evt={evt} roomCtx={roomCtx} />,
|
||||||
|
captureInput: false,
|
||||||
|
onClose: () => {
|
||||||
|
if (window.hackyOpenEventContextMenu === evt.event_id) {
|
||||||
|
window.hackyOpenEventContextMenu = undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
window.hackyOpenEventContextMenu = evt.event_id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const memberEvt = useRoomMember(client, roomCtx.store, evt.sender)
|
const memberEvt = useRoomMember(client, roomCtx.store, evt.sender)
|
||||||
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
|
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
|
||||||
|
|
|
@ -28,6 +28,7 @@ div.event-fixed-menu {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
justify-content: right;
|
justify-content: right;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
> button {
|
> button {
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
|
|
2
web/src/vite-env.d.ts
vendored
2
web/src/vite-env.d.ts
vendored
|
@ -14,5 +14,7 @@ declare global {
|
||||||
mainScreenContext: MainScreenContextFields
|
mainScreenContext: MainScreenContextFields
|
||||||
openLightbox: (params: { src: string, alt: string }) => void
|
openLightbox: (params: { src: string, alt: string }) => void
|
||||||
gcSettings: GCSettings
|
gcSettings: GCSettings
|
||||||
|
hackyOpenEventContextMenu?: string
|
||||||
|
closeModal: () => void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue