mattermost-mobile/app/components/files_search/file_results.tsx
Elias Nahum 784b05fe97
Upgrade Dependencies (#7299)
* upgrade reanimated

* update devDependencies

* upgrade react-intl

* update react-native and some dependencies

* update react-native-permissions

* update RN

* use Share sheet for Report a problem

* update Sentry

* remove step to downloadWebRTC

* update detox deps

* feedback review
2023-04-21 12:16:54 -04:00

171 lines
5.8 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useMemo, useState} from 'react';
import {FlatList, type ListRenderItemInfo, type StyleProp, type ViewStyle} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import NoResults from '@components/files_search/no_results';
import NoResultsWithTerm from '@components/no_results_with_term';
import {useTheme} from '@context/theme';
import {useIsTablet} from '@hooks/device';
import {useImageAttachments} from '@hooks/files';
import {
getChannelNamesWithID,
getFileInfosIndexes,
getNumberFileMenuOptions,
getOrderedFileInfos,
getOrderedGalleryItems,
} from '@utils/files';
import {openGalleryAtIndex} from '@utils/gallery';
import {TabTypes} from '@utils/search';
import {preventDoubleTap} from '@utils/tap';
import {showMobileOptionsBottomSheet} from './file_options/mobile_options';
import Toasts from './file_options/toasts';
import FileResult from './file_result';
import type ChannelModel from '@typings/database/models/servers/channel';
import type {GalleryAction} from '@typings/screens/gallery';
type Props = {
canDownloadFiles: boolean;
fileChannels: ChannelModel[];
fileInfos: FileInfo[];
paddingTop: StyleProp<ViewStyle>;
publicLinkEnabled: boolean;
searchValue: string;
isChannelFiles?: boolean;
isFilterEnabled?: boolean;
}
const galleryIdentifier = 'search-files-location';
const FileResults = ({
canDownloadFiles,
fileChannels,
fileInfos,
paddingTop,
publicLinkEnabled,
searchValue,
isChannelFiles,
isFilterEnabled,
}: Props) => {
const theme = useTheme();
const insets = useSafeAreaInsets();
const isTablet = useIsTablet();
const [action, setAction] = useState<GalleryAction>('none');
const [lastViewedFileInfo, setLastViewedFileInfo] = useState<FileInfo | undefined>(undefined);
const containerStyle = useMemo(() => ([paddingTop, {top: fileInfos.length ? 8 : 0, flexGrow: 1}]), [fileInfos, paddingTop]);
const numOptions = getNumberFileMenuOptions(canDownloadFiles, publicLinkEnabled);
const {images: imageAttachments, nonImages: nonImageAttachments} = useImageAttachments(fileInfos, publicLinkEnabled);
const filesForGallery = useMemo(() => imageAttachments.concat(nonImageAttachments), [imageAttachments, nonImageAttachments]);
const channelNames = useMemo(() => getChannelNamesWithID(fileChannels), [fileChannels]);
const orderedFileInfos = useMemo(() => getOrderedFileInfos(filesForGallery), [filesForGallery]);
const fileInfosIndexes = useMemo(() => getFileInfosIndexes(orderedFileInfos), [orderedFileInfos]);
const orderedGalleryItems = useMemo(() => getOrderedGalleryItems(orderedFileInfos), [orderedFileInfos]);
const onPreviewPress = useCallback(preventDoubleTap((idx: number) => {
openGalleryAtIndex(galleryIdentifier, idx, orderedGalleryItems);
}), [orderedGalleryItems]);
const updateFileForGallery = (idx: number, file: FileInfo) => {
'worklet';
orderedFileInfos[idx] = file;
};
const onOptionsPress = useCallback((fInfo: FileInfo) => {
setLastViewedFileInfo(fInfo);
if (!isTablet) {
showMobileOptionsBottomSheet({
fileInfo: fInfo,
insets,
numOptions,
setAction,
theme,
});
}
}, [insets, isTablet, numOptions, theme]);
const renderItem = useCallback(({item}: ListRenderItemInfo<FileInfo>) => {
let channelName: string | undefined;
if (!isChannelFiles && item.channel_id) {
channelName = channelNames[item.channel_id];
}
return (
<FileResult
canDownloadFiles={canDownloadFiles}
channelName={channelName}
fileInfo={item}
index={fileInfosIndexes[item.id!] || 0}
key={`${item.id}-${item.name}`}
numOptions={numOptions}
onOptionsPress={onOptionsPress}
onPress={onPreviewPress}
publicLinkEnabled={publicLinkEnabled}
setAction={setAction}
updateFileForGallery={updateFileForGallery}
/>
);
}, [
(orderedFileInfos.length === 1) && orderedFileInfos[0].mime_type,
canDownloadFiles,
channelNames,
fileInfosIndexes,
onPreviewPress,
onOptionsPress,
numOptions,
publicLinkEnabled,
]);
const noResults = useMemo(() => {
if (!searchValue && isChannelFiles) {
return (
<NoResults isFilterEnabled={isFilterEnabled}/>
);
}
return (
<NoResultsWithTerm
term={searchValue}
type={TabTypes.FILES}
/>
);
}, [searchValue]);
return (
<>
<FlatList
ListEmptyComponent={noResults}
contentContainerStyle={containerStyle}
data={orderedFileInfos}
indicatorStyle='black'
initialNumToRender={10}
//@ts-expect-error key not defined in types
listKey={'files'}
maxToRenderPerBatch={5}
nestedScrollEnabled={true}
refreshing={false}
removeClippedSubviews={true}
renderItem={renderItem}
scrollEventThrottle={16}
scrollToOverflowEnabled={true}
showsVerticalScrollIndicator={true}
testID='search_results.post_list.flat_list'
/>
<Toasts
action={action}
fileInfo={lastViewedFileInfo}
setAction={setAction}
/>
</>
);
};
export default FileResults;