Move to virtua

This commit is contained in:
David Langley 2025-05-09 09:25:14 +01:00
parent ce68db5c20
commit 9e65d4254d
3 changed files with 30 additions and 34 deletions

View File

@ -157,6 +157,7 @@
"temporal-polyfill": "^0.3.0",
"ua-parser-js": "^1.0.2",
"uuid": "^11.0.0",
"virtua": "^0.41.0",
"what-input": "^5.2.10"
},
"devDependencies": {

View File

@ -7,7 +7,8 @@ Please see LICENSE files in the repository root for full details.
import { Form } from "@vector-im/compound-web";
import React, { useCallback, useRef, type JSX } from "react";
import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
import { Virtualizer, VirtualizerHandle } from "virtua";
// import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
import { Flex } from "../../../utils/Flex";
import {
@ -29,9 +30,9 @@ interface IProps {
const MemberListView: React.FC<IProps> = (props: IProps) => {
const vm = useMemberListViewModel(props.roomId);
const totalRows = vm.members.length;
const ref = useRef<VirtuosoHandle | null>(null);
const ref = useRef<VirtualizerHandle | null>(null);
const scrollRef = useRef<HTMLDivElement | null>(null);
const [focusedIndex, setFocusedIndex] = React.useState(-1);
const listRef = useRef<HTMLButtonElement | null>(null);
const getRowComponent = (item: MemberWithSeparator, focused: boolean): JSX.Element => {
if (item === SEPARATOR) {
@ -39,19 +40,16 @@ const MemberListView: React.FC<IProps> = (props: IProps) => {
} else if (item.member) {
return <RoomMemberTileView member={item.member} showPresence={vm.isPresenceEnabled} focused={focused} />;
} else {
return <ThreePidInviteTileView threePidInvite={item.threePidInvite} />;
return <ThreePidInviteTileView threePidInvite={item.threePidInvite} focused={focused} />;
}
};
const scrollToIndex = useCallback(
(index: number): void => {
ref?.current?.scrollIntoView({
index: index,
behavior: "auto",
done: () => {
setFocusedIndex(index);
},
ref?.current?.scrollToIndex(index, {
align: "nearest",
});
setFocusedIndex(index);
},
[ref],
);
@ -81,18 +79,6 @@ const MemberListView: React.FC<IProps> = (props: IProps) => {
[scrollToIndex, focusedIndex, setFocusedIndex, vm, totalRows],
);
const scrollerRef = useCallback(
(element: any) => {
if (element) {
element.addEventListener("keydown", keyDownCallback);
listRef.current = element;
} else {
listRef?.current?.removeEventListener("keydown", keyDownCallback);
}
},
[keyDownCallback],
);
const onFocus = (e: React.FocusEvent): void => {
const nextIndex = focusedIndex == -1 ? 0 : focusedIndex;
scrollToIndex(nextIndex);
@ -116,20 +102,24 @@ const MemberListView: React.FC<IProps> = (props: IProps) => {
<Form.Root>
<MemberListHeaderView vm={vm} />
</Form.Root>
<Virtuoso
<div
style={{
overflowY: "auto",
// opt out browser's scroll anchoring on header/footer because it will conflict to scroll anchoring of virtualizer
overflowAnchor: "none",
}}
aria-label={_t("room_list|list_title")}
role="grid"
ref={ref}
style={{ height: "100%" }}
scrollerRef={scrollerRef}
context={{ focusedIndex }}
// Don't focus on the table as a whole go straight to the first item in the list
tabIndex={undefined}
data={vm.members}
ref={scrollRef}
onFocus={onFocus}
itemContent={(index, member) => getRowComponent(member, index === focusedIndex)}
components={{ Footer: () => footer() }}
/>
onKeyDown={keyDownCallback}
tabIndex={0}
>
<Virtualizer ref={ref} scrollRef={scrollRef}>
{vm.members.map((member, index) => getRowComponent(member, index === focusedIndex))}
</Virtualizer>
{footer()}
</div>
</Flex>
</BaseCard>
);

View File

@ -3729,7 +3729,7 @@
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.3.tgz#cc54d8b3e9472bcd8e622126ba364ee31952cd8a"
integrity sha512-fqo8P55Vc/t0vxpFar9RDJN5gKEjJmzrLo+O4piDbFda6VrRoqrWAtiu0Au0g6B4hRDPKIuFupk8v9Ja7q8Hvg==
dependencies:
"@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.3-cc54d8b3e9472bcd8e622126ba364ee31952cd8a-integrity/node_modules/bindings/wysiwyg-wasm"
"@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.3-cc54d8b3e9472bcd8e622126ba364ee31952cd8a-integrity/node_modules/bindings/wysiwyg-wasm"
"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1":
version "1.14.1"
@ -13020,6 +13020,11 @@ vaul@^1.0.0:
dependencies:
"@radix-ui/react-dialog" "^1.1.1"
virtua@^0.41.0:
version "0.41.0"
resolved "https://registry.yarnpkg.com/virtua/-/virtua-0.41.0.tgz#1e3c847baceb14c57e14be36272903f80a95f006"
integrity sha512-P8XJhPAz3mNrxAjPc+NRvD8a8+JtInKgHXuvtucThXW93U1ztUKJ2TDCAMaCPRY0CQCR465mYcOf26yQkCHWEw==
vt-pbf@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac"