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)