Right Search: Add infinite scroll, fix jumps
This commit is contained in:
parent
8ed75455de
commit
c95b404085
@ -15,13 +15,6 @@
|
||||
transition: none;
|
||||
}
|
||||
|
||||
// @optimization
|
||||
&:not(:hover) {
|
||||
.chat-item-clickable:not(.picker-list-item):nth-child(n + 18) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1275px) {
|
||||
box-shadow: 0 .25rem .5rem .125rem var(--color-default-shadow);
|
||||
border-left: none;
|
||||
|
||||
@ -5,6 +5,7 @@ import { getDispatch, getGlobal, withGlobal } from '../../lib/teact/teactn';
|
||||
|
||||
import { ApiMessage, ApiUser, ApiChat } from '../../api/types';
|
||||
|
||||
import { MEMO_EMPTY_ARRAY } from '../../util/memo';
|
||||
import {
|
||||
selectUser,
|
||||
selectChatMessages,
|
||||
@ -16,13 +17,12 @@ import {
|
||||
getUserFullName,
|
||||
isChatChannel,
|
||||
} from '../../modules/helpers';
|
||||
import renderText from '../common/helpers/renderText';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import { orderBy } from '../../util/iteratees';
|
||||
import { MEMO_EMPTY_ARRAY } from '../../util/memo';
|
||||
import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation';
|
||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||
import useInfiniteScroll from '../../hooks/useInfiniteScroll';
|
||||
import { renderMessageSummary } from '../common/helpers/renderMessageText';
|
||||
import renderText from '../common/helpers/renderText';
|
||||
|
||||
import InfiniteScroll from '../ui/InfiniteScroll';
|
||||
import ListItem from '../ui/ListItem';
|
||||
@ -46,13 +46,6 @@ type StateProps = {
|
||||
foundIds?: number[];
|
||||
};
|
||||
|
||||
interface Result {
|
||||
message: ApiMessage;
|
||||
senderUser?: ApiUser;
|
||||
senderChat?: ApiChat;
|
||||
onClick: NoneToVoidFunction;
|
||||
}
|
||||
|
||||
const RightSearch: FC<OwnProps & StateProps> = ({
|
||||
chatId,
|
||||
threadId,
|
||||
@ -69,14 +62,20 @@ const RightSearch: FC<OwnProps & StateProps> = ({
|
||||
focusMessage,
|
||||
} = getDispatch();
|
||||
|
||||
const lang = useLang();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const foundResults = useMemo(() => {
|
||||
if (!query || !foundIds || !foundIds.length || !messagesById) {
|
||||
const lang = useLang();
|
||||
useHistoryBack(isActive, onClose);
|
||||
|
||||
const [viewportIds, getMore] = useInfiniteScroll(searchTextMessagesLocal, foundIds);
|
||||
|
||||
const viewportResults = useMemo(() => {
|
||||
if (!query || !viewportIds?.length || !messagesById) {
|
||||
return MEMO_EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
const results = foundIds.map((id) => {
|
||||
return viewportIds.map((id) => {
|
||||
const message = messagesById[id];
|
||||
if (!message) {
|
||||
return undefined;
|
||||
@ -100,19 +99,31 @@ const RightSearch: FC<OwnProps & StateProps> = ({
|
||||
senderChat,
|
||||
onClick: () => focusMessage({ chatId, threadId, messageId: id }),
|
||||
};
|
||||
}).filter(Boolean) as Result[];
|
||||
}).filter(Boolean);
|
||||
}, [query, viewportIds, messagesById, chat, focusMessage, chatId, threadId]);
|
||||
|
||||
return orderBy(results, ({ message }) => message.date, 'desc');
|
||||
}, [chatId, threadId, focusMessage, foundIds, chat, messagesById, query]);
|
||||
const handleKeyDown = useKeyboardListNavigation(containerRef, true, (index) => {
|
||||
const foundResult = viewportResults?.[index === -1 ? 0 : index];
|
||||
if (foundResult) {
|
||||
foundResult.onClick();
|
||||
}
|
||||
}, '.ListItem-button', true);
|
||||
|
||||
const renderSearchResult = ({
|
||||
message, senderUser, senderChat, onClick,
|
||||
}: Result) => {
|
||||
}: {
|
||||
message: ApiMessage;
|
||||
senderUser?: ApiUser;
|
||||
senderChat?: ApiChat;
|
||||
onClick: NoneToVoidFunction;
|
||||
}) => {
|
||||
const title = senderChat ? getChatTitle(lang, senderChat) : getUserFullName(senderUser);
|
||||
const text = renderMessageSummary(lang, message, undefined, query);
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
key={message.id}
|
||||
teactOrderKey={-message.date}
|
||||
className="chat-item-clickable search-result-message m-0"
|
||||
onClick={onClick}
|
||||
>
|
||||
@ -130,39 +141,31 @@ const RightSearch: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
useHistoryBack(isActive, onClose);
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const handleKeyDown = useKeyboardListNavigation(containerRef, true, (index) => {
|
||||
const foundResult = foundResults?.[index === -1 ? 0 : index];
|
||||
if (foundResult) {
|
||||
foundResult.onClick();
|
||||
}
|
||||
}, '.ListItem-button', true);
|
||||
const isOnTop = viewportIds?.[0] === foundIds?.[0];
|
||||
|
||||
return (
|
||||
<InfiniteScroll
|
||||
className="RightSearch custom-scroll"
|
||||
items={foundResults}
|
||||
preloadBackwards={0}
|
||||
onLoadMore={searchTextMessagesLocal}
|
||||
noFastList
|
||||
onKeyDown={handleKeyDown}
|
||||
ref={containerRef}
|
||||
className="RightSearch custom-scroll"
|
||||
items={viewportResults}
|
||||
preloadBackwards={0}
|
||||
onLoadMore={getMore}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<p className="helper-text" dir="auto">
|
||||
{!query ? (
|
||||
lang('lng_dlg_search_for_messages')
|
||||
) : (totalCount === 0 || !foundResults.length) ? (
|
||||
lang('lng_search_no_results')
|
||||
) : totalCount === 1 ? (
|
||||
'1 message found'
|
||||
) : (
|
||||
`${(foundResults.length && (totalCount || foundResults.length))} messages found`
|
||||
)}
|
||||
</p>
|
||||
{foundResults.map(renderSearchResult)}
|
||||
{isOnTop && (
|
||||
<p key="helper-text" className="helper-text" dir="auto">
|
||||
{!query ? (
|
||||
lang('lng_dlg_search_for_messages')
|
||||
) : (totalCount === 0 || !viewportResults.length) ? (
|
||||
lang('lng_search_no_results')
|
||||
) : totalCount === 1 ? (
|
||||
'1 message found'
|
||||
) : (
|
||||
`${(viewportResults.length && (totalCount || viewportResults.length))} messages found`
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{viewportResults.map(renderSearchResult)}
|
||||
</InfiniteScroll>
|
||||
);
|
||||
};
|
||||
|
||||
@ -159,7 +159,7 @@ function useInfiniteScrollForSharedMedia(
|
||||
chatMessages,
|
||||
foundIds,
|
||||
forSharedMediaType,
|
||||
).reverse();
|
||||
);
|
||||
}
|
||||
}, [chatMessages, foundIds, currentResultType, forSharedMediaType]);
|
||||
|
||||
|
||||
@ -85,6 +85,10 @@ async function searchTextMessages(
|
||||
query?: string,
|
||||
offsetId?: number,
|
||||
) {
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('searchMessagesLocal', {
|
||||
chatOrUser,
|
||||
type: 'text',
|
||||
@ -108,7 +112,7 @@ async function searchTextMessages(
|
||||
let global = getGlobal();
|
||||
|
||||
const currentSearch = selectCurrentTextSearch(global);
|
||||
if (!currentSearch || (query && query !== currentSearch.query)) {
|
||||
if (!currentSearch || query !== currentSearch.query) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -303,9 +303,7 @@ export function hasMessageLocalBlobUrl(message: ApiMessage) {
|
||||
export function getChatMediaMessageIds(
|
||||
messages: Record<number, ApiMessage>, listedIds: number[], isFromSharedMedia = false,
|
||||
) {
|
||||
const ids = getMessageContentIds(messages, listedIds, isFromSharedMedia ? 'media' : 'inlineMedia');
|
||||
|
||||
return isFromSharedMedia ? ids.reverse() : ids;
|
||||
return getMessageContentIds(messages, listedIds, isFromSharedMedia ? 'media' : 'inlineMedia');
|
||||
}
|
||||
|
||||
export function getPhotoFullDimensions(photo: ApiPhoto): ApiDimensions | undefined {
|
||||
|
||||
@ -158,5 +158,5 @@ export function updateLocalMediaSearchResults(
|
||||
}
|
||||
|
||||
function orderFoundIds(listedIds: number[]) {
|
||||
return listedIds.sort((a, b) => a - b);
|
||||
return listedIds.sort((a, b) => b - a);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user