mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
web/roomlist,timeline: memoize rooms and messages
This commit is contained in:
parent
52b4e2d6d1
commit
aae6e7496c
3 changed files with 44 additions and 14 deletions
|
@ -153,10 +153,14 @@ export class RoomStateStore {
|
||||||
} else if (memEvt.relation_type === "m.replace" && memEvt.relates_to) {
|
} else if (memEvt.relation_type === "m.replace" && memEvt.relates_to) {
|
||||||
const editTarget = this.eventsByID.get(memEvt.relates_to)
|
const editTarget = this.eventsByID.get(memEvt.relates_to)
|
||||||
if (editTarget?.last_edit_rowid === memEvt.rowid && !editTarget.last_edit) {
|
if (editTarget?.last_edit_rowid === memEvt.rowid && !editTarget.last_edit) {
|
||||||
editTarget.last_edit = memEvt
|
this.eventsByRowID.set(editTarget.rowid, {
|
||||||
editTarget.orig_content = editTarget.content
|
...editTarget,
|
||||||
editTarget.content = memEvt.content["m.new_content"]
|
last_edit: memEvt,
|
||||||
editTarget.local_content = memEvt.local_content
|
orig_content: editTarget.content,
|
||||||
|
content: memEvt.content["m.new_content"],
|
||||||
|
local_content: memEvt.local_content,
|
||||||
|
})
|
||||||
|
this.eventSubs.get(editTarget.event_id)?.notify()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.eventsByRowID.set(memEvt.rowid, memEvt)
|
this.eventsByRowID.set(memEvt.rowid, memEvt)
|
||||||
|
|
|
@ -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 { use } from "react"
|
import { memo, use, useLayoutEffect, useRef, useState } from "react"
|
||||||
import { getMediaURL } from "@/api/media.ts"
|
import { getMediaURL } from "@/api/media.ts"
|
||||||
import type { RoomListEntry } from "@/api/statestore"
|
import type { RoomListEntry } from "@/api/statestore"
|
||||||
import type { MemDBEvent, MemberEventContent } from "@/api/types"
|
import type { MemDBEvent, MemberEventContent } from "@/api/types"
|
||||||
|
@ -26,7 +26,7 @@ export interface RoomListEntryProps {
|
||||||
hidden: boolean
|
hidden: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
function usePreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent): [string, string] {
|
function usePreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent | null): [string, string] {
|
||||||
if (!evt) {
|
if (!evt) {
|
||||||
return ["", ""]
|
return ["", ""]
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ function usePreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent): [string
|
||||||
return ["", ""]
|
return ["", ""]
|
||||||
}
|
}
|
||||||
|
|
||||||
const Entry = ({ room, setActiveRoom, isActive, hidden }: RoomListEntryProps) => {
|
interface InnerProps {
|
||||||
|
room: RoomListEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
const EntryInner = ({ room }: InnerProps) => {
|
||||||
const [previewText, croppedPreviewText] = usePreviewText(room.preview_event, room.preview_sender)
|
const [previewText, croppedPreviewText] = usePreviewText(room.preview_event, room.preview_sender)
|
||||||
return <div
|
return <>
|
||||||
className={`room-entry ${isActive ? "active" : ""} ${hidden ? "hidden" : ""}`}
|
|
||||||
onClick={setActiveRoom}
|
|
||||||
data-room-id={room.room_id}
|
|
||||||
>
|
|
||||||
<div className="room-entry-left">
|
<div className="room-entry-left">
|
||||||
<img loading="lazy" className="avatar room-avatar" src={getMediaURL(room.avatar)} alt=""/>
|
<img loading="lazy" className="avatar room-avatar" src={getMediaURL(room.avatar)} alt=""/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,7 +68,33 @@ const Entry = ({ room, setActiveRoom, isActive, hidden }: RoomListEntryProps) =>
|
||||||
{room.unread_messages || room.unread_notifications || room.unread_highlights}
|
{room.unread_messages || room.unread_notifications || room.unread_highlights}
|
||||||
</div>
|
</div>
|
||||||
</div> : null}
|
</div> : null}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const Entry = ({ room, setActiveRoom, isActive, hidden }: RoomListEntryProps) => {
|
||||||
|
const [isVisible, setVisible] = useState(false)
|
||||||
|
const divRef = useRef<HTMLDivElement>(null)
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const div = divRef.current
|
||||||
|
if (!div) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const listener = (evt: unknown) => {
|
||||||
|
if (!(evt as ContentVisibilityAutoStateChangeEvent).skipped) {
|
||||||
|
setVisible(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div.addEventListener("contentvisibilityautostatechange", listener)
|
||||||
|
return () => div.removeEventListener("contentvisibilityautostatechange", listener)
|
||||||
|
}, [])
|
||||||
|
return <div
|
||||||
|
ref={divRef}
|
||||||
|
className={`room-entry ${isActive ? "active" : ""} ${hidden ? "hidden" : ""}`}
|
||||||
|
onClick={setActiveRoom}
|
||||||
|
data-room-id={room.room_id}
|
||||||
|
>
|
||||||
|
{isVisible ? <EntryInner room={room}/> : null}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Entry
|
export default memo(Entry)
|
||||||
|
|
|
@ -136,4 +136,4 @@ const TimelineEvent = ({ room, evt, prevEvt, setReplyToRef }: TimelineEventProps
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TimelineEvent
|
export default React.memo(TimelineEvent)
|
||||||
|
|
Loading…
Add table
Reference in a new issue