[Refactoring] Infinite Scroll: Support absolute positioning

This commit is contained in:
Alexander Zinchuk 2022-02-02 22:49:10 +01:00
parent 5f6040b82c
commit 27d7f92756
3 changed files with 49 additions and 53 deletions

View File

@ -4,7 +4,6 @@ import React, {
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { CHAT_HEIGHT_PX } from '../../config'; import { CHAT_HEIGHT_PX } from '../../config';
import { IS_ANDROID } from '../../util/environment';
import useInfiniteScroll from '../../hooks/useInfiniteScroll'; import useInfiniteScroll from '../../hooks/useInfiniteScroll';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation'; import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation';
@ -105,31 +104,24 @@ const ChatOrUserPicker: FC<OwnProps> = ({
className="picker-list custom-scroll" className="picker-list custom-scroll"
items={viewportIds} items={viewportIds}
onLoadMore={getMore} onLoadMore={getMore}
noFastList withAbsolutePositioning
noScrollRestore maxHeight={chatOrUserIds!.length * CHAT_HEIGHT_PX}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
> >
<div {viewportIds.map((id, i) => (
className="scroll-container" <ListItem
// @ts-ignore key={id}
style={IS_ANDROID ? `height: ${chatOrUserIds!.length * CHAT_HEIGHT_PX}px` : undefined} className="chat-item-clickable force-rounded-corners"
teactFastList style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
> onClick={() => onSelectChatOrUser(id)}
{viewportIds.map((id, i) => ( >
<ListItem {isUserId(id) ? (
key={id} <PrivateChatInfo status={id === currentUserId ? lang('SavedMessagesInfo') : undefined} userId={id} />
className="chat-item-clickable force-rounded-corners" ) : (
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`} <GroupChatInfo chatId={id} />
onClick={() => onSelectChatOrUser(id)} )}
> </ListItem>
{isUserId(id) ? ( ))}
<PrivateChatInfo status={id === currentUserId ? lang('SavedMessagesInfo') : undefined} userId={id} />
) : (
<GroupChatInfo chatId={id} />
)}
</ListItem>
))}
</div>
</InfiniteScroll> </InfiniteScroll>
) : viewportIds && !viewportIds.length ? ( ) : viewportIds && !viewportIds.length ? (
<p className="no-results">{lang('lng_blocked_list_not_found')}</p> <p className="no-results">{lang('lng_blocked_list_not_found')}</p>

View File

@ -13,7 +13,7 @@ import {
CHAT_HEIGHT_PX, CHAT_HEIGHT_PX,
CHAT_LIST_SLICE, CHAT_LIST_SLICE,
} from '../../../config'; } from '../../../config';
import { IS_ANDROID, IS_MAC_OS, IS_PWA } from '../../../util/environment'; import { IS_MAC_OS, IS_PWA } from '../../../util/environment';
import { mapValues } from '../../../util/iteratees'; import { mapValues } from '../../../util/iteratees';
import { getPinnedChatsCount } from '../../../util/folderManager'; import { getPinnedChatsCount } from '../../../util/folderManager';
import usePrevious from '../../../hooks/usePrevious'; import usePrevious from '../../../hooks/usePrevious';
@ -138,38 +138,29 @@ const ChatList: FC<OwnProps> = ({
const viewportOffset = orderedIds!.indexOf(viewportIds![0]); const viewportOffset = orderedIds!.indexOf(viewportIds![0]);
const pinnedCount = getPinnedChatsCount(virtualFolderId) || 0; const pinnedCount = getPinnedChatsCount(virtualFolderId) || 0;
return ( return viewportIds!.map((id, i) => (
<div <Chat
className="scroll-container" key={id}
teactOrderKey={i}
chatId={id}
isPinned={viewportOffset + i < pinnedCount}
folderId={folderId}
animationType={getAnimationType(id)}
orderDiff={orderDiffById[id]}
// @ts-ignore // @ts-ignore
style={IS_ANDROID ? `height: ${orderedIds!.length * CHAT_HEIGHT_PX}px` : undefined} style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
teactFastList />
> ));
{viewportIds!.map((id, i) => (
<Chat
key={id}
teactOrderKey={i}
chatId={id}
isPinned={viewportOffset + i < pinnedCount}
folderId={folderId}
animationType={getAnimationType(id)}
orderDiff={orderDiffById[id]}
// @ts-ignore
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
/>
))}
</div>
);
} }
return ( return (
<InfiniteScroll <InfiniteScroll
className="chat-list custom-scroll" className="chat-list custom-scroll"
items={viewportIds} items={viewportIds}
onLoadMore={getMore}
preloadBackwards={CHAT_LIST_SLICE} preloadBackwards={CHAT_LIST_SLICE}
noFastList withAbsolutePositioning
noScrollRestore maxHeight={(orderedIds?.length || 0) * CHAT_HEIGHT_PX}
onLoadMore={getMore}
> >
{viewportIds?.length ? ( {viewportIds?.length ? (
renderChats() renderChats()

View File

@ -7,6 +7,7 @@ import React, {
import { debounce } from '../../util/schedulers'; import { debounce } from '../../util/schedulers';
import resetScroll from '../../util/resetScroll'; import resetScroll from '../../util/resetScroll';
import { IS_ANDROID } from '../../util/environment';
type OwnProps = { type OwnProps = {
ref?: RefObject<HTMLDivElement>; ref?: RefObject<HTMLDivElement>;
@ -18,6 +19,8 @@ type OwnProps = {
itemSelector?: string; itemSelector?: string;
preloadBackwards?: number; preloadBackwards?: number;
sensitiveArea?: number; sensitiveArea?: number;
withAbsolutePositioning?: boolean;
maxHeight?: number;
noScrollRestore?: boolean; noScrollRestore?: boolean;
noScrollRestoreOnTop?: boolean; noScrollRestoreOnTop?: boolean;
noFastList?: boolean; noFastList?: boolean;
@ -39,6 +42,8 @@ const InfiniteScroll: FC<OwnProps> = ({
itemSelector = DEFAULT_LIST_SELECTOR, itemSelector = DEFAULT_LIST_SELECTOR,
preloadBackwards = DEFAULT_PRELOAD_BACKWARDS, preloadBackwards = DEFAULT_PRELOAD_BACKWARDS,
sensitiveArea = DEFAULT_SENSITIVE_AREA, sensitiveArea = DEFAULT_SENSITIVE_AREA,
withAbsolutePositioning,
maxHeight,
// Used to turn off restoring scroll position (e.g. for frequently re-ordered chat or user lists) // Used to turn off restoring scroll position (e.g. for frequently re-ordered chat or user lists)
noScrollRestore = false, noScrollRestore = false,
noScrollRestoreOnTop = false, noScrollRestoreOnTop = false,
@ -114,7 +119,7 @@ const InfiniteScroll: FC<OwnProps> = ({
} }
} }
if (noScrollRestore) { if (withAbsolutePositioning || noScrollRestore) {
return; return;
} }
@ -125,7 +130,7 @@ const InfiniteScroll: FC<OwnProps> = ({
resetScroll(container, newScrollTop); resetScroll(container, newScrollTop);
state.isScrollTopJustUpdated = true; state.isScrollTopJustUpdated = true;
}, [items, itemSelector, noScrollRestore, noScrollRestoreOnTop, cacheBuster]); }, [items, itemSelector, noScrollRestore, noScrollRestoreOnTop, cacheBuster, withAbsolutePositioning]);
const handleScroll = useCallback((e: UIEvent<HTMLDivElement>) => { const handleScroll = useCallback((e: UIEvent<HTMLDivElement>) => {
if (loadMoreForwards && loadMoreBackwards) { if (loadMoreForwards && loadMoreBackwards) {
@ -214,10 +219,18 @@ const InfiniteScroll: FC<OwnProps> = ({
ref={containerRef} ref={containerRef}
className={className} className={className}
onScroll={handleScroll} onScroll={handleScroll}
teactFastList={!noFastList} teactFastList={!noFastList && !withAbsolutePositioning}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
> >
{children} {withAbsolutePositioning && items?.length ? (
<div
teactFastList={!noFastList}
// @ts-ignore
style={`position: relative;${IS_ANDROID ? ` height: ${maxHeight}px;` : undefined}`}
>
{children}
</div>
) : children}
</div> </div>
); );
}; };