mattermost-mobile/app/screens/home/search/results/results.tsx
2025-06-19 15:30:56 +08:00

137 lines
4.1 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useMemo} from 'react';
import {Freeze} from 'react-freeze';
import {StyleSheet, View} from 'react-native';
import Animated, {useAnimatedStyle, withTiming} from 'react-native-reanimated';
import FileResults from '@components/files_search/file_results';
import Loading from '@components/loading';
import {useTheme} from '@context/theme';
import {useWindowDimensions} from '@hooks/device';
import {TabTypes, type TabType} from '@utils/search';
import PostResults from './post_results';
import type ChannelModel from '@typings/database/models/servers/channel';
import type PostModel from '@typings/database/models/servers/post';
const duration = 250;
const getStyles = (width: number) => {
return StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
width: width * 2,
},
result: {
flex: 1,
width,
},
loading: {
justifyContent: 'center',
flex: 1,
width,
},
});
};
type Props = {
appsEnabled: boolean;
canDownloadFiles: boolean;
currentTimezone: string;
customEmojiNames: string[];
enableSecureFilePreview: boolean;
fileChannels: ChannelModel[];
fileInfos: FileInfo[];
loading: boolean;
posts: PostModel[];
matches?: SearchMatches;
publicLinkEnabled: boolean;
scrollPaddingTop: number;
searchValue: string;
selectedTab: TabType;
}
const Results = ({
appsEnabled,
canDownloadFiles,
currentTimezone,
customEmojiNames,
enableSecureFilePreview,
fileChannels,
fileInfos,
loading,
posts,
matches,
publicLinkEnabled,
scrollPaddingTop,
searchValue,
selectedTab,
}: Props) => {
const {width} = useWindowDimensions();
const theme = useTheme();
const styles = useMemo(() => getStyles(width), [width]);
const transform = useAnimatedStyle(() => {
const translateX = selectedTab === TabTypes.MESSAGES ? 0 : -width;
return {
transform: [
{translateX: withTiming(translateX, {duration})},
],
};
// Do not transform if loading new data. Causes a case where post
// results show up in Files results when the team is changed
}, [selectedTab, width, !loading]);
const paddingTop = useMemo(() => (
{paddingTop: scrollPaddingTop}
), [scrollPaddingTop]);
return (
<>
{loading &&
<Loading
color={theme.buttonBg}
size='large'
containerStyle={[styles.loading, paddingTop]}
/>
}
{!loading &&
<Animated.View style={[styles.container, transform]}>
<View style={styles.result}>
<Freeze freeze={selectedTab !== TabTypes.MESSAGES}>
<PostResults
appsEnabled={appsEnabled}
currentTimezone={currentTimezone}
customEmojiNames={customEmojiNames}
posts={posts}
matches={matches}
paddingTop={paddingTop}
searchValue={searchValue}
/>
</Freeze>
</View>
<View style={styles.result}>
<Freeze freeze={selectedTab !== TabTypes.FILES}>
<FileResults
canDownloadFiles={canDownloadFiles}
enableSecureFilePreview={enableSecureFilePreview}
fileChannels={fileChannels}
fileInfos={fileInfos}
paddingTop={paddingTop}
publicLinkEnabled={publicLinkEnabled}
searchValue={searchValue}
/>
</Freeze>
</View>
</Animated.View>
}
</>
);
};
export default Results;