forked from Mirrors/gomuks
web: merge event dispatcher hooks
This commit is contained in:
parent
11a8aac398
commit
a114b23b88
6 changed files with 15 additions and 26 deletions
|
@ -22,14 +22,14 @@ import MainScreen from "./ui/MainScreen.tsx"
|
||||||
import { LoginScreen, VerificationScreen } from "./ui/login"
|
import { LoginScreen, VerificationScreen } from "./ui/login"
|
||||||
import { LightboxWrapper } from "./ui/modal/Lightbox.tsx"
|
import { LightboxWrapper } from "./ui/modal/Lightbox.tsx"
|
||||||
import { ModalWrapper } from "./ui/modal/Modal.tsx"
|
import { ModalWrapper } from "./ui/modal/Modal.tsx"
|
||||||
import { useCachedEventAsState } from "./util/eventdispatcher.ts"
|
import { useEventAsState } from "./util/eventdispatcher.ts"
|
||||||
|
|
||||||
const client = new Client(new WSClient("_gomuks/websocket"))
|
const client = new Client(new WSClient("_gomuks/websocket"))
|
||||||
window.client = client
|
window.client = client
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const connState = useCachedEventAsState(client.rpc.connect)
|
const connState = useEventAsState(client.rpc.connect)
|
||||||
const clientState = useCachedEventAsState(client.state)
|
const clientState = useEventAsState(client.state)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Notification.requestPermission()
|
Notification.requestPermission()
|
||||||
.then(permission => console.log("Notification permission:", permission))
|
.then(permission => console.log("Notification permission:", permission))
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
import { use, useRef } from "react"
|
import { use, useRef } from "react"
|
||||||
import { getAvatarURL } from "@/api/media.ts"
|
import { getAvatarURL } from "@/api/media.ts"
|
||||||
import { RoomStateStore } from "@/api/statestore"
|
import { RoomStateStore } from "@/api/statestore"
|
||||||
import { useNonNullEventAsState } from "@/util/eventdispatcher.ts"
|
import { useEventAsState } from "@/util/eventdispatcher.ts"
|
||||||
import MessageComposer from "./composer/MessageComposer.tsx"
|
import MessageComposer from "./composer/MessageComposer.tsx"
|
||||||
import { LightboxContext } from "./modal/Lightbox.tsx"
|
import { LightboxContext } from "./modal/Lightbox.tsx"
|
||||||
import { RoomContext, RoomContextData } from "./roomcontext.ts"
|
import { RoomContext, RoomContextData } from "./roomcontext.ts"
|
||||||
|
@ -30,7 +30,7 @@ interface RoomViewProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RoomHeader = ({ room, clearActiveRoom }: RoomViewProps) => {
|
const RoomHeader = ({ room, clearActiveRoom }: RoomViewProps) => {
|
||||||
const roomMeta = useNonNullEventAsState(room.meta)
|
const roomMeta = useEventAsState(room.meta)
|
||||||
const avatarSourceID = roomMeta.lazy_load_summary?.heroes?.length === 1
|
const avatarSourceID = roomMeta.lazy_load_summary?.heroes?.length === 1
|
||||||
? roomMeta.lazy_load_summary.heroes[0] : room.roomID
|
? roomMeta.lazy_load_summary.heroes[0] : room.roomID
|
||||||
return <div className="room-header">
|
return <div className="room-header">
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// 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, { use, useCallback, useRef, useState } from "react"
|
import React, { use, useCallback, useRef, useState } from "react"
|
||||||
import type { RoomID } from "@/api/types"
|
import type { RoomID } from "@/api/types"
|
||||||
import { useNonNullEventAsState } from "@/util/eventdispatcher.ts"
|
import { useEventAsState } from "@/util/eventdispatcher.ts"
|
||||||
import toSearchableString from "@/util/searchablestring.ts"
|
import toSearchableString from "@/util/searchablestring.ts"
|
||||||
import ClientContext from "../ClientContext.ts"
|
import ClientContext from "../ClientContext.ts"
|
||||||
import Entry from "./Entry.tsx"
|
import Entry from "./Entry.tsx"
|
||||||
|
@ -27,7 +27,7 @@ interface RoomListProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RoomList = ({ setActiveRoom, activeRoomID }: RoomListProps) => {
|
const RoomList = ({ setActiveRoom, activeRoomID }: RoomListProps) => {
|
||||||
const roomList = useNonNullEventAsState(use(ClientContext)!.store.roomList)
|
const roomList = useEventAsState(use(ClientContext)!.store.roomList)
|
||||||
const roomFilterRef = useRef<HTMLInputElement>(null)
|
const roomFilterRef = useRef<HTMLInputElement>(null)
|
||||||
const [roomFilter, setRoomFilter] = useState("")
|
const [roomFilter, setRoomFilter] = useState("")
|
||||||
const [realRoomFilter, setRealRoomFilter] = useState("")
|
const [realRoomFilter, setRealRoomFilter] = useState("")
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
import { CSSProperties, use, useCallback, useRef } from "react"
|
import { CSSProperties, use, useCallback, useRef } from "react"
|
||||||
import { MemDBEvent } from "@/api/types"
|
import { MemDBEvent } from "@/api/types"
|
||||||
import { emojiToReactionContent } from "@/util/emoji"
|
import { emojiToReactionContent } from "@/util/emoji"
|
||||||
import { useNonNullEventAsState } from "@/util/eventdispatcher.ts"
|
import { useEventAsState } from "@/util/eventdispatcher.ts"
|
||||||
import ClientContext from "../../ClientContext.ts"
|
import ClientContext from "../../ClientContext.ts"
|
||||||
import EmojiPicker from "../../emojipicker/EmojiPicker.tsx"
|
import EmojiPicker from "../../emojipicker/EmojiPicker.tsx"
|
||||||
import { ModalContext } from "../../modal/Modal.tsx"
|
import { ModalContext } from "../../modal/Modal.tsx"
|
||||||
|
@ -83,7 +83,7 @@ const EventMenu = ({ evt, setForceOpen }: EventHoverMenuProps) => {
|
||||||
onClose: () => setForceOpen(false),
|
onClose: () => setForceOpen(false),
|
||||||
})
|
})
|
||||||
}, [evt, roomCtx, setForceOpen, openModal])
|
}, [evt, roomCtx, setForceOpen, openModal])
|
||||||
const isEditing = useNonNullEventAsState(roomCtx.isEditing)
|
const isEditing = useEventAsState(roomCtx.isEditing)
|
||||||
return <div className="event-hover-menu" ref={contextMenuRef}>
|
return <div className="event-hover-menu" ref={contextMenuRef}>
|
||||||
<button onClick={onClickReact}><ReactIcon/></button>
|
<button onClick={onClickReact}><ReactIcon/></button>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -13,22 +13,11 @@
|
||||||
//
|
//
|
||||||
// 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 { useEffect, useState, useSyncExternalStore } from "react"
|
import { useSyncExternalStore } from "react"
|
||||||
|
|
||||||
export function useEventAsState<T>(dispatcher?: EventDispatcher<T>): T | null {
|
export function useEventAsState<T>(dispatcher: NonNullCachedEventDispatcher<T>): T
|
||||||
const [state, setState] = useState<T | null>(null)
|
export function useEventAsState<T>(dispatcher: CachedEventDispatcher<T>): T | null
|
||||||
useEffect(() => dispatcher && dispatcher.listen(setState), [dispatcher])
|
export function useEventAsState<T>(dispatcher: CachedEventDispatcher<T>): T | null {
|
||||||
return state
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useCachedEventAsState<T>(dispatcher: CachedEventDispatcher<T>): T | null {
|
|
||||||
return useSyncExternalStore(
|
|
||||||
dispatcher.listenChange,
|
|
||||||
() => dispatcher.current,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useNonNullEventAsState<T>(dispatcher: NonNullCachedEventDispatcher<T>): T {
|
|
||||||
return useSyncExternalStore(
|
return useSyncExternalStore(
|
||||||
dispatcher.listenChange,
|
dispatcher.listenChange,
|
||||||
() => dispatcher.current,
|
() => dispatcher.current,
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
//
|
//
|
||||||
// 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 { NonNullCachedEventDispatcher, useNonNullEventAsState } from "@/util/eventdispatcher.ts"
|
import { NonNullCachedEventDispatcher, useEventAsState } from "@/util/eventdispatcher.ts"
|
||||||
|
|
||||||
export const focused = new NonNullCachedEventDispatcher(document.hasFocus())
|
export const focused = new NonNullCachedEventDispatcher(document.hasFocus())
|
||||||
window.addEventListener("focus", () => focused.emit(true))
|
window.addEventListener("focus", () => focused.emit(true))
|
||||||
window.addEventListener("blur", () => focused.emit(false))
|
window.addEventListener("blur", () => focused.emit(false))
|
||||||
|
|
||||||
export default function useFocus() {
|
export default function useFocus() {
|
||||||
return useNonNullEventAsState(focused)
|
return useEventAsState(focused)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue