chat-fe: improve render performance

This commit is contained in:
Liam Fitzgerald 2021-06-15 11:59:47 +10:00
parent 995a35cd76
commit c00768442a
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
4 changed files with 31 additions and 41 deletions

View File

@ -86,7 +86,7 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
); );
return `${url}\n~${msg.author}: `; return `${url}\n~${msg.author}: `;
}, },
[association] [association.resource]
); );
const isAdmin = useMemo( const isAdmin = useMemo(
@ -107,7 +107,7 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
if (newer) { if (newer) {
const index = graph.peekLargest()?.[0]; const index = graph.peekLargest()?.[0];
if (!index) { if (!index) {
return true; return false;
} }
await getYoungerSiblings( await getYoungerSiblings(
ship, ship,
@ -119,10 +119,12 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
} else { } else {
const index = graph.peekSmallest()?.[0]; const index = graph.peekSmallest()?.[0];
if (!index) { if (!index) {
return true; return false;
} }
await getOlderSiblings(ship, name, pageSize, `/${index.toString()}`); await getOlderSiblings(ship, name, pageSize, `/${index.toString()}`);
const done = expectedSize !== getCurrGraphSize(ship.slice(1), name); const currSize = getCurrGraphSize(ship.slice(1), name);
console.log(currSize);
const done = expectedSize !== currSize;
return done; return done;
} }
}, [graph, resource]); }, [graph, resource]);
@ -144,7 +146,7 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
const getPermalink = useCallback( const getPermalink = useCallback(
(index: BigInteger) => (index: BigInteger) =>
getPermalinkForGraph(association.group, resource, `/${index.toString()}`), getPermalinkForGraph(association.group, resource, `/${index.toString()}`),
[association] [association.resource]
); );
if (!graph) { if (!graph) {

View File

@ -16,7 +16,7 @@ import {
cite, daToUnix, useHovering, useShowNickname, uxToHex cite, daToUnix, useHovering, useShowNickname, uxToHex
} from '~/logic/lib/util'; } from '~/logic/lib/util';
import { useContact } from '~/logic/state/contact'; import { useContact } from '~/logic/state/contact';
import useLocalState from '~/logic/state/local'; import { useDark } from '~/logic/state/join';
import useSettingsState, { selectCalmState } from '~/logic/state/settings'; import useSettingsState, { selectCalmState } from '~/logic/state/settings';
import { Dropdown } from '~/views/components/Dropdown'; import { Dropdown } from '~/views/components/Dropdown';
import ProfileOverlay from '~/views/components/ProfileOverlay'; import ProfileOverlay from '~/views/components/ProfileOverlay';
@ -53,16 +53,13 @@ export const DayBreak = ({ when, shimTop = false }: DayBreakProps) => (
</Row> </Row>
); );
export const MessageAuthor = ({ export const MessageAuthor = React.memo<any>(({
timestamp, timestamp,
msg, msg,
showOurContact, showOurContact,
...props ...props
}) => { }) => {
const osDark = useLocalState(state => state.dark); const dark = useDark();
const theme = useSettingsState(s => s.display.theme);
const dark = theme === 'dark' || (theme === 'auto' && osDark);
let contact: Contact | null = useContact(`~${msg.author}`); let contact: Contact | null = useContact(`~${msg.author}`);
const date = daToUnix(bigInt(msg.index.split('/').reverse()[0])); const date = daToUnix(bigInt(msg.index.split('/').reverse()[0]));
@ -177,7 +174,8 @@ export const MessageAuthor = ({
</Box> </Box>
</Box> </Box>
); );
}; });
MessageAuthor.displayName = 'MessageAuthor';
type MessageProps = { timestamp: string; timestampHover: boolean; } type MessageProps = { timestamp: string; timestampHover: boolean; }
& Pick<ChatMessageProps, 'msg' | 'transcluded' | 'showOurContact'> & Pick<ChatMessageProps, 'msg' | 'transcluded' | 'showOurContact'>
@ -392,6 +390,7 @@ interface ChatMessageProps {
showOurContact: boolean; showOurContact: boolean;
onDelete?: () => void; onDelete?: () => void;
} }
const emptyCallback = () => {};
function ChatMessage(props: ChatMessageProps) { function ChatMessage(props: ChatMessageProps) {
let { highlighted } = props; let { highlighted } = props;
@ -416,10 +415,10 @@ function ChatMessage(props: ChatMessageProps) {
); );
} }
const onReply = props?.onReply ?? (() => {}); const onReply = props?.onReply || emptyCallback;
const onDelete = props?.onDelete ?? (() => {}); const onDelete = props?.onDelete || emptyCallback;
const transcluded = props?.transcluded ?? 0; const transcluded = props?.transcluded || 0;
const renderSigil = props.renderSigil ?? (Boolean(nextMsg && msg.author !== nextMsg.author) || const renderSigil = props.renderSigil || (Boolean(nextMsg && msg.author !== nextMsg.author) ||
!nextMsg !nextMsg
); );
@ -509,9 +508,9 @@ function ChatMessage(props: ChatMessageProps) {
); );
} }
export default React.forwardRef((props: Omit<ChatMessageProps, 'innerRef'>, ref: any) => ( export default React.memo(React.forwardRef((props: Omit<ChatMessageProps, 'innerRef'>, ref: any) => (
<ChatMessage {...props} innerRef={ref} /> <ChatMessage {...props} innerRef={ref} />
)); )));
export const MessagePlaceholder = ({ export const MessagePlaceholder = ({
height, height,

View File

@ -6,7 +6,7 @@ import React, { ReactElement, useCallback, useEffect, useRef, useState } from 'r
import { useFileDrag } from '~/logic/lib/useDrag'; import { useFileDrag } from '~/logic/lib/useDrag';
import { useLocalStorageState } from '~/logic/lib/useLocalStorageState'; import { useLocalStorageState } from '~/logic/lib/useLocalStorageState';
import { useOurContact } from '~/logic/state/contact'; import { useOurContact } from '~/logic/state/contact';
import useGraphState from '~/logic/state/graph'; import { useGraphTimesent } from '~/logic/state/graph';
import ShareProfile from '~/views/apps/chat/components/ShareProfile'; import ShareProfile from '~/views/apps/chat/components/ShareProfile';
import { Loading } from '~/views/components/Loading'; import { Loading } from '~/views/components/Loading';
import SubmitDragger from '~/views/components/SubmitDragger'; import SubmitDragger from '~/views/components/SubmitDragger';
@ -77,7 +77,7 @@ export function ChatPane(props: ChatPaneProps): ReactElement {
promptShare = [], promptShare = [],
fetchMessages fetchMessages
} = props; } = props;
const graphTimesentMap = useGraphState(state => state.graphTimesentMap); const graphTimesentMap = useGraphTimesent(id);
const ourContact = useOurContact(); const ourContact = useOurContact();
const chatInput = useRef<NakedChatInput>(); const chatInput = useRef<NakedChatInput>();
@ -88,7 +88,7 @@ export function ChatPane(props: ChatPaneProps): ReactElement {
} }
(chatInput.current as NakedChatInput)?.uploadFiles(files); (chatInput.current as NakedChatInput)?.uploadFiles(files);
}, },
[chatInput.current] [chatInput]
); );
const { bind, dragging } = useFileDrag(onFileDrag); const { bind, dragging } = useFileDrag(onFileDrag);
@ -147,7 +147,7 @@ export function ChatPane(props: ChatPaneProps): ReactElement {
graphSize={graph.size} graphSize={graph.size}
unreadCount={unreadCount} unreadCount={unreadCount}
showOurContact={promptShare.length === 0 && !showBanner} showOurContact={promptShare.length === 0 && !showBanner}
pendingSize={Object.keys(graphTimesentMap[id] || {}).length} pendingSize={Object.keys(graphTimesentMap).length}
onReply={onReply} onReply={onReply}
onDelete={onDelete} onDelete={onDelete}
dismissUnread={dismissUnread} dismissUnread={dismissUnread}
@ -170,3 +170,5 @@ export function ChatPane(props: ChatPaneProps): ReactElement {
</Col> </Col>
); );
} }
ChatPane.whyDidYouRender = true;

View File

@ -6,7 +6,7 @@ import {
import bigInt, { BigInteger } from 'big-integer'; import bigInt, { BigInteger } from 'big-integer';
import React, { Component } from 'react'; import React, { Component } from 'react';
import VirtualScroller from '~/views/components/VirtualScroller'; import VirtualScroller from '~/views/components/VirtualScroller';
import ChatMessage, { MessagePlaceholder } from './ChatMessage'; import ChatMessage from './ChatMessage';
import UnreadNotice from './UnreadNotice'; import UnreadNotice from './UnreadNotice';
const IDLE_THRESHOLD = 64; const IDLE_THRESHOLD = 64;
@ -57,7 +57,7 @@ class ChatWindow extends Component<
this.state = { this.state = {
fetchPending: false, fetchPending: false,
idle: true, idle: true,
initialized: false, initialized: true,
unreadIndex: bigInt.zero unreadIndex: bigInt.zero
}; };
@ -72,14 +72,10 @@ class ChatWindow extends Component<
componentDidMount() { componentDidMount() {
this.calculateUnreadIndex(); this.calculateUnreadIndex();
setTimeout(() => { if(this.props.scrollTo) {
this.setState({ initialized: true }, () => { this.virtualList!.scrollLocked = false;
if(this.props.scrollTo) { this.virtualList!.scrollToIndex(this.props.scrollTo);
this.virtualList!.scrollLocked = false; }
this.virtualList!.scrollToIndex(this.props.scrollTo);
}
});
}, this.INITIALIZATION_MAX_TIME);
} }
calculateUnreadIndex() { calculateUnreadIndex() {
@ -205,15 +201,6 @@ class ChatWindow extends Component<
</Text> </Text>
); );
} }
if (!this.state.initialized) {
return (
<MessagePlaceholder
key={index.toString()}
height='64px'
index={index}
/>
);
}
const isPending: boolean = 'pending' in msg && Boolean(msg.pending); const isPending: boolean = 'pending' in msg && Boolean(msg.pending);
const isLastMessage = index.eq( const isLastMessage = index.eq(
graph.peekLargest()?.[0] ?? bigInt.zero graph.peekLargest()?.[0] ?? bigInt.zero