diff --git a/web/src/api/statestore/room.ts b/web/src/api/statestore/room.ts
index 77b1d34..482bd14 100644
--- a/web/src/api/statestore/room.ts
+++ b/web/src/api/statestore/room.ts
@@ -153,10 +153,14 @@ export class RoomStateStore {
} else if (memEvt.relation_type === "m.replace" && memEvt.relates_to) {
const editTarget = this.eventsByID.get(memEvt.relates_to)
if (editTarget?.last_edit_rowid === memEvt.rowid && !editTarget.last_edit) {
- editTarget.last_edit = memEvt
- editTarget.orig_content = editTarget.content
- editTarget.content = memEvt.content["m.new_content"]
- editTarget.local_content = memEvt.local_content
+ this.eventsByRowID.set(editTarget.rowid, {
+ ...editTarget,
+ last_edit: memEvt,
+ 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)
diff --git a/web/src/ui/roomlist/Entry.tsx b/web/src/ui/roomlist/Entry.tsx
index 584d342..4074e6f 100644
--- a/web/src/ui/roomlist/Entry.tsx
+++ b/web/src/ui/roomlist/Entry.tsx
@@ -13,7 +13,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-import { use } from "react"
+import { memo, use, useLayoutEffect, useRef, useState } from "react"
import { getMediaURL } from "@/api/media.ts"
import type { RoomListEntry } from "@/api/statestore"
import type { MemDBEvent, MemberEventContent } from "@/api/types"
@@ -26,7 +26,7 @@ export interface RoomListEntryProps {
hidden: boolean
}
-function usePreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent): [string, string] {
+function usePreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent | null): [string, string] {
if (!evt) {
return ["", ""]
}
@@ -46,13 +46,13 @@ function usePreviewText(evt?: MemDBEvent, senderMemberEvt?: MemDBEvent): [string
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)
- return
+ return <>
@@ -68,7 +68,33 @@ const Entry = ({ room, setActiveRoom, isActive, hidden }: RoomListEntryProps) =>
{room.unread_messages || room.unread_notifications || room.unread_highlights}
: null}
+ >
+}
+
+const Entry = ({ room, setActiveRoom, isActive, hidden }: RoomListEntryProps) => {
+ const [isVisible, setVisible] = useState(false)
+ const divRef = useRef(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
+ {isVisible ? : null}
}
-export default Entry
+export default memo(Entry)
diff --git a/web/src/ui/timeline/TimelineEvent.tsx b/web/src/ui/timeline/TimelineEvent.tsx
index 401ae4e..01238dc 100644
--- a/web/src/ui/timeline/TimelineEvent.tsx
+++ b/web/src/ui/timeline/TimelineEvent.tsx
@@ -136,4 +136,4 @@ const TimelineEvent = ({ room, evt, prevEvt, setReplyToRef }: TimelineEventProps
>
}
-export default TimelineEvent
+export default React.memo(TimelineEvent)