mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
perf(app): render guild stickers only near the modal viewport (#1964)
This commit is contained in:
1 parent
987768e8dc
commit
022ccc794d
2 files changed
+26
-1
No files matched your search
@@ -16,10 +16,12 @@ import {getAcceptString, getAssetFormatErrorMessage} from '@app/features/express
|
|||||||
import {isSvgFile} from '@app/features/expressions/utils/ImageUploadFileUtils';
|
import {isSvgFile} from '@app/features/expressions/utils/ImageUploadFileUtils';
|
||||||
import {CloneAllowedToggle} from '@app/features/guild/components/modals/guild_tabs/CloneAllowedToggle';
|
import {CloneAllowedToggle} from '@app/features/guild/components/modals/guild_tabs/CloneAllowedToggle';
|
||||||
import styles from '@app/features/guild/components/modals/guild_tabs/GuildStickersTab.module.css';
|
import styles from '@app/features/guild/components/modals/guild_tabs/GuildStickersTab.module.css';
|
||||||
|
import {resolveEnclosingScrollSurface} from '@app/features/guild/components/modals/guild_tabs/GuildStickersTabScrollSurface';
|
||||||
import {UploadDropZone} from '@app/features/guild/components/UploadDropZone';
|
import {UploadDropZone} from '@app/features/guild/components/UploadDropZone';
|
||||||
import {UploadSlotInfo} from '@app/features/guild/components/UploadSlotInfo';
|
import {UploadSlotInfo} from '@app/features/guild/components/UploadSlotInfo';
|
||||||
import Guilds from '@app/features/guild/state/Guilds';
|
import Guilds from '@app/features/guild/state/Guilds';
|
||||||
import {OKAY_DESCRIPTOR, TRY_AGAIN_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
import {OKAY_DESCRIPTOR, TRY_AGAIN_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||||
|
import {NearViewportSurfaceContext} from '@app/features/messaging/hooks/useNearViewport';
|
||||||
import {openFilePicker} from '@app/features/messaging/utils/FilePickerUtils';
|
import {openFilePicker} from '@app/features/messaging/utils/FilePickerUtils';
|
||||||
import {formatFileSize} from '@app/features/messaging/utils/FileUtils';
|
import {formatFileSize} from '@app/features/messaging/utils/FileUtils';
|
||||||
import Permission from '@app/features/permissions/state/Permission';
|
import Permission from '@app/features/permissions/state/Permission';
|
||||||
@@ -42,7 +44,7 @@ import {clsx} from 'clsx';
|
|||||||
import {matchSorter} from 'match-sorter';
|
import {matchSorter} from 'match-sorter';
|
||||||
import {observer} from 'mobx-react-lite';
|
import {observer} from 'mobx-react-lite';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import {useCallback, useEffect, useMemo, useState} from 'react';
|
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||||
|
|
||||||
const SEARCH_STICKERS_DESCRIPTOR = msg({
|
const SEARCH_STICKERS_DESCRIPTOR = msg({
|
||||||
message: 'Search stickers',
|
message: 'Search stickers',
|
||||||
@@ -92,6 +94,8 @@ const GuildStickersTab: React.FC<{guildId: string}> = observer(function GuildSti
|
|||||||
const [stickers, setStickers] = useState<ReadonlyArray<GuildStickerWithUser>>([]);
|
const [stickers, setStickers] = useState<ReadonlyArray<GuildStickerWithUser>>([]);
|
||||||
const [fetchStatus, setFetchStatus] = useState<'idle' | 'pending' | 'success' | 'error'>('idle');
|
const [fetchStatus, setFetchStatus] = useState<'idle' | 'pending' | 'success' | 'error'>('idle');
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
|
const gridRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const resolveGridScrollSurface = useCallback(() => resolveEnclosingScrollSurface(gridRef.current), []);
|
||||||
const layoutState = EmojiStickerLayout;
|
const layoutState = EmojiStickerLayout;
|
||||||
const viewMode = layoutState.getStickerViewMode();
|
const viewMode = layoutState.getStickerViewMode();
|
||||||
const guild = Guilds.getGuild(guildId);
|
const guild = Guilds.getGuild(guildId);
|
||||||
@@ -309,7 +313,9 @@ const GuildStickersTab: React.FC<{guildId: string}> = observer(function GuildSti
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{fetchStatus === 'success' && filteredStickers.length > 0 && (
|
{fetchStatus === 'success' && filteredStickers.length > 0 && (
|
||||||
|
<NearViewportSurfaceContext.Provider value={resolveGridScrollSurface}>
|
||||||
<div
|
<div
|
||||||
|
ref={gridRef}
|
||||||
className={clsx(styles.stickerGrid, viewMode === 'compact' ? styles.compactGrid : styles.cozyGrid)}
|
className={clsx(styles.stickerGrid, viewMode === 'compact' ? styles.compactGrid : styles.cozyGrid)}
|
||||||
data-flx="guild.guild-tabs.guild-stickers-tab.sticker-grid"
|
data-flx="guild.guild-tabs.guild-stickers-tab.sticker-grid"
|
||||||
>
|
>
|
||||||
@@ -324,6 +330,7 @@ const GuildStickersTab: React.FC<{guildId: string}> = observer(function GuildSti
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</NearViewportSurfaceContext.Provider>
|
||||||
)}
|
)}
|
||||||
{fetchStatus === 'error' && (
|
{fetchStatus === 'error' && (
|
||||||
<StatusSlate
|
<StatusSlate
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
const SCROLLABLE_OVERFLOW_VALUES = new Set(['auto', 'scroll', 'overlay']);
|
||||||
|
|
||||||
|
export function resolveEnclosingScrollSurface(node: Element | null): Element | null {
|
||||||
|
let candidate = node?.parentElement ?? null;
|
||||||
|
while (candidate) {
|
||||||
|
const computedStyle = window.getComputedStyle(candidate);
|
||||||
|
if (
|
||||||
|
SCROLLABLE_OVERFLOW_VALUES.has(computedStyle.overflowY) ||
|
||||||
|
SCROLLABLE_OVERFLOW_VALUES.has(computedStyle.overflow)
|
||||||
|
) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
candidate = candidate.parentElement;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user