1
0
Fork 0
forked from Mirrors/gomuks

web/all: move some things out of layout effects

This commit is contained in:
Tulir Asokan 2024-12-22 15:20:09 +02:00
parent 132a7dce15
commit b01b3f0e32
6 changed files with 21 additions and 20 deletions

View file

@ -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(() => {

View file

@ -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() {

View file

@ -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

View file

@ -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)

View file

@ -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) {}

View file

@ -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]