mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
perf(app): load sheet and popout media against their own scrollers (#1900)
This commit is contained in:
1 parent
94bbbd1021
commit
bb34c73069
3 files changed
+217
-200
No files matched your search
+86
-82
@@ -27,6 +27,7 @@ import {isKeyboardActivationKey} from '@app/features/input/utils/KeyboardUtils';
|
||||
import * as MessageCommands from '@app/features/messaging/commands/MessageCommands';
|
||||
import {useMessageListKeyboardNavigation} from '@app/features/messaging/hooks/useMessageListKeyboardNavigation';
|
||||
import {useMessageSelectionCopyForMessages} from '@app/features/messaging/hooks/useMessageSelectionCopy';
|
||||
import {NearViewportSurfaceContext} from '@app/features/messaging/hooks/useNearViewport';
|
||||
import type {Message} from '@app/features/messaging/models/MessagingMessage';
|
||||
import {
|
||||
applyChannelSearchHighlight,
|
||||
@@ -67,7 +68,7 @@ import {MessagePreviewContext} from '@fluxer/constants/src/ChannelConstants';
|
||||
import {Trans, useLingui} from '@lingui/react/macro';
|
||||
import {HashIcon} from '@phosphor-icons/react';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
import React, {useCallback, useEffect, useRef, useState} from 'react';
|
||||
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||
|
||||
const NEWEST_DESCRIPTOR = msg({
|
||||
message: 'Newest',
|
||||
@@ -189,6 +190,7 @@ export const ChannelSearchBottomSheet: React.FC<ChannelSearchBottomSheetProps> =
|
||||
const [selectedMessage, setSelectedMessage] = useState<Message | null>(null);
|
||||
const [selectedMessageChannel, setSelectedMessageChannel] = useState<Channel | null>(null);
|
||||
const scrollerRef = useRef<ScrollerHandle | null>(null);
|
||||
const resolveSearchSheetScrollSurface = useMemo(() => () => scrollerRef.current?.getViewportElement() ?? null, []);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [hasFilters, setHasFilters] = useState<Array<HasFilterType>>([]);
|
||||
const [fromUserIds, setFromUserIds] = useState<Array<string>>([]);
|
||||
@@ -605,89 +607,91 @@ export const ChannelSearchBottomSheet: React.FC<ChannelSearchBottomSheetProps> =
|
||||
value={collapsedMessageVisibility}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.collapsed-message-visibility-provider"
|
||||
>
|
||||
<Scroller
|
||||
ref={scrollerRef}
|
||||
className={styles.resultsScroller}
|
||||
key="channel-search-results-scroller"
|
||||
onCopy={onCopySelectedMessages}
|
||||
data-message-selection-root="true"
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.results-scroller"
|
||||
>
|
||||
{resultGroups.map((resultGroup) => {
|
||||
const messageChannel =
|
||||
searchChannelsById.get(resultGroup.channelId) ?? Channels.getChannel(resultGroup.channelId);
|
||||
if (!messageChannel) {
|
||||
return null;
|
||||
}
|
||||
const renderMessageWrapper = ({
|
||||
message,
|
||||
index,
|
||||
isGroupStart,
|
||||
children,
|
||||
}: MessageGroupRenderWrapperProps) => (
|
||||
<LongPressable
|
||||
data-message-index={index}
|
||||
data-message-id={message.id}
|
||||
data-is-group-start={isGroupStart}
|
||||
className={styles.searchResultItem}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={() => handleTap(message)}
|
||||
onKeyDown={(e) => {
|
||||
if (isKeyboardActivationKey(e.key)) {
|
||||
e.preventDefault();
|
||||
handleTap(message);
|
||||
}
|
||||
}}
|
||||
onLongPress={() => {
|
||||
setSelectedMessage(message);
|
||||
setMenuOpen(true);
|
||||
}}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-message-wrapper.search-result-item.tap"
|
||||
>
|
||||
{children}
|
||||
</LongPressable>
|
||||
);
|
||||
return (
|
||||
<React.Fragment key={resultGroup.key}>
|
||||
{hasMultipleChannels && (
|
||||
<div
|
||||
className={styles.channelSection}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.channel-section"
|
||||
>
|
||||
{ChannelUtils.getIcon(messageChannel, {
|
||||
className: styles.channelIcon,
|
||||
})}
|
||||
<span
|
||||
className={styles.channelName}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.channel-name"
|
||||
<NearViewportSurfaceContext.Provider value={resolveSearchSheetScrollSurface}>
|
||||
<Scroller
|
||||
ref={scrollerRef}
|
||||
className={styles.resultsScroller}
|
||||
key="channel-search-results-scroller"
|
||||
onCopy={onCopySelectedMessages}
|
||||
data-message-selection-root="true"
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.results-scroller"
|
||||
>
|
||||
{resultGroups.map((resultGroup) => {
|
||||
const messageChannel =
|
||||
searchChannelsById.get(resultGroup.channelId) ?? Channels.getChannel(resultGroup.channelId);
|
||||
if (!messageChannel) {
|
||||
return null;
|
||||
}
|
||||
const renderMessageWrapper = ({
|
||||
message,
|
||||
index,
|
||||
isGroupStart,
|
||||
children,
|
||||
}: MessageGroupRenderWrapperProps) => (
|
||||
<LongPressable
|
||||
data-message-index={index}
|
||||
data-message-id={message.id}
|
||||
data-is-group-start={isGroupStart}
|
||||
className={styles.searchResultItem}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={() => handleTap(message)}
|
||||
onKeyDown={(e) => {
|
||||
if (isKeyboardActivationKey(e.key)) {
|
||||
e.preventDefault();
|
||||
handleTap(message);
|
||||
}
|
||||
}}
|
||||
onLongPress={() => {
|
||||
setSelectedMessage(message);
|
||||
setMenuOpen(true);
|
||||
}}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-message-wrapper.search-result-item.tap"
|
||||
>
|
||||
{children}
|
||||
</LongPressable>
|
||||
);
|
||||
return (
|
||||
<React.Fragment key={resultGroup.key}>
|
||||
{hasMultipleChannels && (
|
||||
<div
|
||||
className={styles.channelSection}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.channel-section"
|
||||
>
|
||||
{messageChannel.name || 'Unnamed Channel'}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<SearchResultMessageList
|
||||
channel={messageChannel}
|
||||
messages={resultGroup.messages}
|
||||
revealedGroupKeys={revealedGroupKeys}
|
||||
onGroupRevealChange={handleCollapsedGroupRevealChange}
|
||||
collapsedGroupClassName={styles.collapsedMessageGroup}
|
||||
messagePreviewContext={MessagePreviewContext.LIST_POPOUT}
|
||||
renderMessageWrapper={renderMessageWrapper}
|
||||
spammerOverrideVersion={spammerOverrideVersion}
|
||||
renderMessage={(message) => (
|
||||
<SearchResultItem
|
||||
message={message}
|
||||
messageChannel={messageChannel}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.search-result-item"
|
||||
/>
|
||||
{ChannelUtils.getIcon(messageChannel, {
|
||||
className: styles.channelIcon,
|
||||
})}
|
||||
<span
|
||||
className={styles.channelName}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.channel-name"
|
||||
>
|
||||
{messageChannel.name || 'Unnamed Channel'}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.search-result-message-list"
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</Scroller>
|
||||
<SearchResultMessageList
|
||||
channel={messageChannel}
|
||||
messages={resultGroup.messages}
|
||||
revealedGroupKeys={revealedGroupKeys}
|
||||
onGroupRevealChange={handleCollapsedGroupRevealChange}
|
||||
collapsedGroupClassName={styles.collapsedMessageGroup}
|
||||
messagePreviewContext={MessagePreviewContext.LIST_POPOUT}
|
||||
renderMessageWrapper={renderMessageWrapper}
|
||||
spammerOverrideVersion={spammerOverrideVersion}
|
||||
renderMessage={(message) => (
|
||||
<SearchResultItem
|
||||
message={message}
|
||||
messageChannel={messageChannel}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.search-result-item"
|
||||
/>
|
||||
)}
|
||||
data-flx="channel.channel-search-bottom-sheet.render-content.search-result-message-list"
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</Scroller>
|
||||
</NearViewportSurfaceContext.Provider>
|
||||
</CollapsedMessageVisibilityProvider>
|
||||
{totalPages > 1 && (
|
||||
<div
|
||||
|
||||
Reference in new issue
Block a user