mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
web/all: move some things out of layout effects
This commit is contained in:
parent
132a7dce15
commit
b01b3f0e32
6 changed files with 21 additions and 20 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 { useEffect, useLayoutEffect, useMemo } from "react"
|
import { useEffect, useMemo } from "react"
|
||||||
import { ScaleLoader } from "react-spinners"
|
import { ScaleLoader } from "react-spinners"
|
||||||
import Client from "./api/client.ts"
|
import Client from "./api/client.ts"
|
||||||
import RPCClient from "./api/rpc.ts"
|
import RPCClient from "./api/rpc.ts"
|
||||||
|
@ -36,10 +36,10 @@ function App() {
|
||||||
const client = useMemo(() => new Client(makeRPCClient()), [])
|
const client = useMemo(() => new Client(makeRPCClient()), [])
|
||||||
const connState = useEventAsState(client.rpc.connect)
|
const connState = useEventAsState(client.rpc.connect)
|
||||||
const clientState = useEventAsState(client.state)
|
const clientState = useEventAsState(client.state)
|
||||||
useLayoutEffect(() => {
|
useEffect(() => {
|
||||||
window.client = client
|
window.client = client
|
||||||
|
client.start()
|
||||||
}, [client])
|
}, [client])
|
||||||
useEffect(() => client.start(), [client])
|
|
||||||
|
|
||||||
const afterConnectError = Boolean(connState?.error && connState.reconnecting && clientState?.is_verified)
|
const afterConnectError = Boolean(connState?.error && connState.reconnecting && clientState?.is_verified)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -92,6 +92,7 @@ export class RoomStateStore {
|
||||||
readonly meta: NonNullCachedEventDispatcher<DBRoom>
|
readonly meta: NonNullCachedEventDispatcher<DBRoom>
|
||||||
timeline: TimelineRowTuple[] = []
|
timeline: TimelineRowTuple[] = []
|
||||||
timelineCache: (MemDBEvent | null)[] = []
|
timelineCache: (MemDBEvent | null)[] = []
|
||||||
|
editTargets: EventRowID[] = []
|
||||||
state: Map<EventType, Map<string, EventRowID>> = new Map()
|
state: Map<EventType, Map<string, EventRowID>> = new Map()
|
||||||
stateLoaded = false
|
stateLoaded = false
|
||||||
typing: UserID[] = []
|
typing: UserID[] = []
|
||||||
|
@ -134,16 +135,25 @@ export class RoomStateStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateTimelineCache() {
|
#updateTimelineCache() {
|
||||||
|
const ownMessages: EventRowID[] = []
|
||||||
this.timelineCache = this.timeline.map(rt => {
|
this.timelineCache = this.timeline.map(rt => {
|
||||||
const evt = this.eventsByRowID.get(rt.event_rowid)
|
const evt = this.eventsByRowID.get(rt.event_rowid)
|
||||||
if (!evt) {
|
if (!evt) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
evt.timeline_rowid = rt.timeline_rowid
|
evt.timeline_rowid = rt.timeline_rowid
|
||||||
|
if (
|
||||||
|
evt.sender === this.parent.userID
|
||||||
|
&& evt.type === "m.room.message"
|
||||||
|
&& evt.relation_type !== "m.replace"
|
||||||
|
) {
|
||||||
|
ownMessages.push(evt.rowid)
|
||||||
|
}
|
||||||
return evt
|
return evt
|
||||||
}).concat(this.pendingEvents
|
}).concat(this.pendingEvents
|
||||||
.map(rowID => this.eventsByRowID.get(rowID))
|
.map(rowID => this.eventsByRowID.get(rowID))
|
||||||
.filter(evt => !!evt))
|
.filter(evt => !!evt))
|
||||||
|
this.editTargets = ownMessages
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyTimelineSubscribers() {
|
notifyTimelineSubscribers() {
|
||||||
|
|
|
@ -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 { JSX, use, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react"
|
import { JSX, use, useEffect, useMemo, useReducer, useRef, useState } from "react"
|
||||||
import { SyncLoader } from "react-spinners"
|
import { SyncLoader } from "react-spinners"
|
||||||
import Client from "@/api/client.ts"
|
import Client from "@/api/client.ts"
|
||||||
import { RoomStateStore } from "@/api/statestore"
|
import { RoomStateStore } from "@/api/statestore"
|
||||||
|
@ -280,10 +280,8 @@ const MainScreen = () => {
|
||||||
() => new ContextFields(directSetRightPanel, directSetActiveRoom, client),
|
() => new ContextFields(directSetRightPanel, directSetActiveRoom, client),
|
||||||
[client],
|
[client],
|
||||||
)
|
)
|
||||||
useLayoutEffect(() => {
|
|
||||||
window.mainScreenContext = context
|
|
||||||
}, [context])
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
window.mainScreenContext = context
|
||||||
const listener = (evt: PopStateEvent) => {
|
const listener = (evt: PopStateEvent) => {
|
||||||
skipNextTransitionRef.current = evt.hasUAVisualTransition
|
skipNextTransitionRef.current = evt.hasUAVisualTransition
|
||||||
const roomID = evt.state?.room_id ?? null
|
const roomID = evt.state?.room_id ?? null
|
||||||
|
|
|
@ -310,18 +310,18 @@ const MessageComposer = () => {
|
||||||
}
|
}
|
||||||
} else if (fullKey === "ArrowUp" && inp.selectionStart === 0 && inp.selectionEnd === 0) {
|
} else if (fullKey === "ArrowUp" && inp.selectionStart === 0 && inp.selectionEnd === 0) {
|
||||||
const currentlyEditing = editing
|
const currentlyEditing = editing
|
||||||
? roomCtx.ownMessages.indexOf(editing.rowid)
|
? room.editTargets.indexOf(editing.rowid)
|
||||||
: roomCtx.ownMessages.length
|
: room.editTargets.length
|
||||||
const prevEventToEditID = roomCtx.ownMessages[currentlyEditing - 1]
|
const prevEventToEditID = room.editTargets[currentlyEditing - 1]
|
||||||
const prevEventToEdit = prevEventToEditID ? room.eventsByRowID.get(prevEventToEditID) : undefined
|
const prevEventToEdit = prevEventToEditID ? room.eventsByRowID.get(prevEventToEditID) : undefined
|
||||||
if (prevEventToEdit) {
|
if (prevEventToEdit) {
|
||||||
roomCtx.setEditing(prevEventToEdit)
|
roomCtx.setEditing(prevEventToEdit)
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
} else if (editing && fullKey === "ArrowDown" && inp.selectionStart === state.text.length) {
|
} else if (editing && fullKey === "ArrowDown" && inp.selectionStart === state.text.length) {
|
||||||
const currentlyEditingIdx = roomCtx.ownMessages.indexOf(editing.rowid)
|
const currentlyEditingIdx = room.editTargets.indexOf(editing.rowid)
|
||||||
const nextEventToEdit = currentlyEditingIdx
|
const nextEventToEdit = currentlyEditingIdx
|
||||||
? room.eventsByRowID.get(roomCtx.ownMessages[currentlyEditingIdx + 1]) : undefined
|
? room.eventsByRowID.get(room.editTargets[currentlyEditingIdx + 1]) : undefined
|
||||||
roomCtx.setEditing(nextEventToEdit ?? null)
|
roomCtx.setEditing(nextEventToEdit ?? null)
|
||||||
// This timeout is very hacky and probably doesn't work in every case
|
// This timeout is very hacky and probably doesn't work in every case
|
||||||
setTimeout(() => inp.setSelectionRange(0, 0), 0)
|
setTimeout(() => inp.setSelectionRange(0, 0), 0)
|
||||||
|
|
|
@ -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 { RefObject, createContext, createRef, use } from "react"
|
import { RefObject, createContext, createRef, use } from "react"
|
||||||
import { RoomStateStore } from "@/api/statestore"
|
import { RoomStateStore } from "@/api/statestore"
|
||||||
import { EventID, EventRowID, MemDBEvent } from "@/api/types"
|
import { EventID, MemDBEvent } from "@/api/types"
|
||||||
import { NonNullCachedEventDispatcher } from "@/util/eventdispatcher.ts"
|
import { NonNullCachedEventDispatcher } from "@/util/eventdispatcher.ts"
|
||||||
import { escapeMarkdown } from "@/util/markdown.ts"
|
import { escapeMarkdown } from "@/util/markdown.ts"
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ export class RoomContextData {
|
||||||
public setEditing: (evt: MemDBEvent | null) => void = noop("setEditing")
|
public setEditing: (evt: MemDBEvent | null) => void = noop("setEditing")
|
||||||
public insertText: (text: string) => void = noop("insertText")
|
public insertText: (text: string) => void = noop("insertText")
|
||||||
public readonly isEditing = new NonNullCachedEventDispatcher<boolean>(false)
|
public readonly isEditing = new NonNullCachedEventDispatcher<boolean>(false)
|
||||||
public ownMessages: EventRowID[] = []
|
|
||||||
public scrolledToBottom = true
|
public scrolledToBottom = true
|
||||||
|
|
||||||
constructor(public store: RoomStateStore) {}
|
constructor(public store: RoomStateStore) {}
|
||||||
|
|
|
@ -67,12 +67,6 @@ const TimelineView = () => {
|
||||||
timelineViewRef.current.scrollTop += timelineViewRef.current.scrollHeight - oldScrollHeight.current
|
timelineViewRef.current.scrollTop += timelineViewRef.current.scrollHeight - oldScrollHeight.current
|
||||||
}
|
}
|
||||||
prevOldestTimelineRow.current = timeline[0]?.timeline_rowid ?? 0
|
prevOldestTimelineRow.current = timeline[0]?.timeline_rowid ?? 0
|
||||||
roomCtx.ownMessages = timeline
|
|
||||||
.filter(evt => evt !== null
|
|
||||||
&& evt.sender === client.userID
|
|
||||||
&& evt.type === "m.room.message"
|
|
||||||
&& evt.relation_type !== "m.replace")
|
|
||||||
.map(evt => evt!.rowid)
|
|
||||||
}, [client.userID, roomCtx, timeline])
|
}, [client.userID, roomCtx, timeline])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newestEvent = timeline[timeline.length - 1]
|
const newestEvent = timeline[timeline.length - 1]
|
||||||
|
|
Loading…
Add table
Reference in a new issue