[MM-48225] Reduce Padding/Margins from Files Tab and moving the Search Results to the FlatList (#7430)
* feat: reducing the padding/margins of tabs and filter icons on the Search Page * feat: adds the results text inside the post_results and file_results * feat: changes search results to use translation * feat: updates text on search results to use FormattedText * feat: removing text wrapper * feat: removing margins and using an ItemSeparator to separate the rows of the file results * feat: refactor spacing on post results and unnecessary top * review: externalizing Separator on the file_results * feat: add marginTop in all File components used inside the <Files> component
This commit is contained in:
parent
aeba5ed6d2
commit
722871d165
10 changed files with 90 additions and 46 deletions
|
|
@ -44,7 +44,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
|||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: changeOpacity(theme.centerChannelColor, 0.24),
|
||||
borderRadius: 4,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ const styles = StyleSheet.create({
|
|||
failed: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
marginTop: {
|
||||
marginTop: 10,
|
||||
},
|
||||
});
|
||||
|
||||
const Files = ({canDownloadFiles, failed, filesInfo, isReplyPost, layoutWidth, location, postId, publicLinkEnabled}: FilesProps) => {
|
||||
|
|
@ -86,7 +89,7 @@ const Files = ({canDownloadFiles, failed, filesInfo, isReplyPost, layoutWidth, l
|
|||
}
|
||||
return (
|
||||
<View
|
||||
style={container}
|
||||
style={[container, styles.marginTop]}
|
||||
key={file.id}
|
||||
>
|
||||
<File
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
// 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 {FlatList, type ListRenderItemInfo, type StyleProp, type ViewStyle, View} from 'react-native';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
|
||||
import NoResults from '@components/files_search/no_results';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import NoResultsWithTerm from '@components/no_results_with_term';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
|
|
@ -20,6 +21,8 @@ import {
|
|||
import {openGalleryAtIndex} from '@utils/gallery';
|
||||
import {TabTypes} from '@utils/search';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
import {showMobileOptionsBottomSheet} from './file_options/mobile_options';
|
||||
import Toasts from './file_options/toasts';
|
||||
|
|
@ -28,6 +31,14 @@ import FileResult from './file_result';
|
|||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type {GalleryAction} from '@typings/screens/gallery';
|
||||
|
||||
const getStyles = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
resultsNumber: {
|
||||
...typography('Heading', 300),
|
||||
padding: 20,
|
||||
color: theme.centerChannelColor,
|
||||
},
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
canDownloadFiles: boolean;
|
||||
fileChannels: ChannelModel[];
|
||||
|
|
@ -41,6 +52,9 @@ type Props = {
|
|||
|
||||
const galleryIdentifier = 'search-files-location';
|
||||
|
||||
const separatorStyle = {height: 10};
|
||||
const Separator = () => <View style={separatorStyle}/>;
|
||||
|
||||
const FileResults = ({
|
||||
canDownloadFiles,
|
||||
fileChannels,
|
||||
|
|
@ -52,13 +66,14 @@ const FileResults = ({
|
|||
isFilterEnabled,
|
||||
}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyles(theme);
|
||||
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 containerStyle = useMemo(() => ([paddingTop, {flexGrow: 1}]), [paddingTop]);
|
||||
const numOptions = getNumberFileMenuOptions(canDownloadFiles, publicLinkEnabled);
|
||||
|
||||
const {images: imageAttachments, nonImages: nonImageAttachments} = useImageAttachments(fileInfos, publicLinkEnabled);
|
||||
|
|
@ -141,6 +156,15 @@ const FileResults = ({
|
|||
return (
|
||||
<>
|
||||
<FlatList
|
||||
ListHeaderComponent={
|
||||
<FormattedText
|
||||
style={styles.resultsNumber}
|
||||
id='mobile.search.results'
|
||||
defaultMessage='{count} search {count, plural, one {result} other {results}}'
|
||||
values={{count: orderedFileInfos.length}}
|
||||
/>
|
||||
}
|
||||
ItemSeparatorComponent={Separator}
|
||||
ListEmptyComponent={noResults}
|
||||
contentContainerStyle={containerStyle}
|
||||
data={orderedFileInfos}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ type Props = {
|
|||
onFilterChanged: (filter: FileFilter) => void;
|
||||
selectedTab: TabType;
|
||||
selectedFilter: FileFilter;
|
||||
numberMessages: number;
|
||||
numberFiles: number;
|
||||
setTeamId: (id: string) => void;
|
||||
teamId: string;
|
||||
teams: TeamModel[];
|
||||
|
|
@ -65,8 +63,6 @@ const Header = ({
|
|||
setTeamId,
|
||||
onTabSelect,
|
||||
onFilterChanged,
|
||||
numberMessages,
|
||||
numberFiles,
|
||||
selectedTab,
|
||||
selectedFilter,
|
||||
teams,
|
||||
|
|
@ -122,7 +118,7 @@ const Header = ({
|
|||
});
|
||||
}, [onFilterChanged, selectedFilter]);
|
||||
|
||||
const filterStyle = useMemo(() => ({marginRight: teams.length > 1 ? 0 : 10}), [teams.length > 1]);
|
||||
const filterStyle = useMemo(() => ({marginRight: teams.length > 1 ? 0 : 8}), [teams.length > 1]);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
|
|
@ -130,39 +126,42 @@ const Header = ({
|
|||
<SelectButton
|
||||
selected={selectedTab === TabTypes.MESSAGES}
|
||||
onPress={handleMessagesPress}
|
||||
text={`${messagesText} (${numberMessages})`}
|
||||
text={messagesText}
|
||||
/>
|
||||
<SelectButton
|
||||
selected={selectedTab === TabTypes.FILES}
|
||||
onPress={handleFilesPress}
|
||||
text={`${filesText} (${numberFiles})`}
|
||||
text={filesText}
|
||||
/>
|
||||
<View style={styles.iconsContainer}>
|
||||
{showFilterIcon &&
|
||||
<View style={filterStyle}>
|
||||
<CompassIcon
|
||||
name={'filter-variant'}
|
||||
size={24}
|
||||
color={changeOpacity(theme.centerChannelColor, 0.56)}
|
||||
onPress={handleFilterPress}
|
||||
{showFilterIcon && (
|
||||
<View style={filterStyle}>
|
||||
<CompassIcon
|
||||
name={'filter-variant'}
|
||||
size={24}
|
||||
color={changeOpacity(
|
||||
theme.centerChannelColor,
|
||||
0.56,
|
||||
)}
|
||||
onPress={handleFilterPress}
|
||||
/>
|
||||
<Badge
|
||||
style={styles.badge}
|
||||
visible={hasFilters}
|
||||
testID={'search.filters.badge'}
|
||||
value={-1}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{teams.length > 1 && (
|
||||
<TeamPickerIcon
|
||||
size={32}
|
||||
divider={true}
|
||||
setTeamId={setTeamId}
|
||||
teamId={teamId}
|
||||
teams={teams}
|
||||
/>
|
||||
<Badge
|
||||
style={styles.badge}
|
||||
visible={hasFilters}
|
||||
testID={'search.filters.badge'}
|
||||
value={-1}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
{teams.length > 1 &&
|
||||
<TeamPickerIcon
|
||||
size={32}
|
||||
divider={true}
|
||||
setTeamId={setTeamId}
|
||||
teamId={teamId}
|
||||
teams={teams}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
|
@ -170,4 +169,3 @@ const Header = ({
|
|||
};
|
||||
|
||||
export default Header;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
borderRadius: 4,
|
||||
},
|
||||
text: {
|
||||
paddingHorizontal: 16,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 8,
|
||||
...typography('Body', 200, 'SemiBold'),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,18 +4,30 @@
|
|||
import React, {useCallback, useMemo} from 'react';
|
||||
import {FlatList, type ListRenderItemInfo, type StyleProp, type ViewStyle} from 'react-native';
|
||||
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import NoResultsWithTerm from '@components/no_results_with_term';
|
||||
import DateSeparator from '@components/post_list/date_separator';
|
||||
import PostWithChannelInfo from '@components/post_with_channel_info';
|
||||
import {Screens} from '@constants';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {convertSearchTermToRegex, parseSearchTerms} from '@utils/markdown';
|
||||
import {getDateForDateLine, selectOrderedPosts} from '@utils/post_list';
|
||||
import {TabTypes} from '@utils/search';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
import type {PostListItem, PostListOtherItem} from '@typings/components/post_list';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type {SearchPattern} from '@typings/global/markdown';
|
||||
|
||||
const getStyles = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
resultsNumber: {
|
||||
...typography('Heading', 300),
|
||||
padding: 20,
|
||||
color: theme.centerChannelColor,
|
||||
},
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
appsEnabled: boolean;
|
||||
customEmojiNames: string[];
|
||||
|
|
@ -37,8 +49,10 @@ const PostResults = ({
|
|||
paddingTop,
|
||||
searchValue,
|
||||
}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyles(theme);
|
||||
const orderedPosts = useMemo(() => selectOrderedPosts(posts, 0, false, '', '', false, isTimezoneEnabled, currentTimezone, false).reverse(), [posts]);
|
||||
const containerStyle = useMemo(() => ({top: posts.length ? 4 : 8, flexGrow: 1}), [posts]);
|
||||
const containerStyle = useMemo(() => ([paddingTop, {flexGrow: 1}]), [paddingTop]);
|
||||
|
||||
const renderItem = useCallback(({item}: ListRenderItemInfo<PostListItem | PostListOtherItem>) => {
|
||||
switch (item.type) {
|
||||
|
|
@ -88,8 +102,16 @@ const PostResults = ({
|
|||
|
||||
return (
|
||||
<FlatList
|
||||
ListHeaderComponent={
|
||||
<FormattedText
|
||||
style={styles.resultsNumber}
|
||||
id='mobile.search.results'
|
||||
defaultMessage='{count} search {count, plural, one {result} other {results}}'
|
||||
values={{count: posts.length}}
|
||||
/>
|
||||
}
|
||||
ListEmptyComponent={noResults}
|
||||
contentContainerStyle={[paddingTop, containerStyle]}
|
||||
contentContainerStyle={containerStyle}
|
||||
data={orderedPosts}
|
||||
indicatorStyle='black'
|
||||
initialNumToRender={5}
|
||||
|
|
@ -104,7 +126,6 @@ const PostResults = ({
|
|||
scrollEventThrottle={16}
|
||||
scrollToOverflowEnabled={true}
|
||||
showsVerticalScrollIndicator={true}
|
||||
style={containerStyle}
|
||||
testID='search_results.post_list.flat_list'
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ const Results = ({
|
|||
}
|
||||
{!loading &&
|
||||
<Animated.View style={[styles.container, transform]}>
|
||||
<View style={styles.result} >
|
||||
<View style={styles.result}>
|
||||
<PostResults
|
||||
appsEnabled={appsEnabled}
|
||||
currentTimezone={currentTimezone}
|
||||
|
|
@ -112,7 +112,7 @@ const Results = ({
|
|||
searchValue={searchValue}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.result} >
|
||||
<View style={styles.result}>
|
||||
<FileResults
|
||||
canDownloadFiles={canDownloadFiles}
|
||||
fileChannels={fileChannels}
|
||||
|
|
|
|||
|
|
@ -372,9 +372,7 @@ const SearchScreen = ({teamId, teams}: Props) => {
|
|||
setTeamId={handleResultsTeamChange}
|
||||
onTabSelect={setSelectedTab}
|
||||
onFilterChanged={handleFilterChange}
|
||||
numberMessages={posts.length}
|
||||
selectedTab={selectedTab}
|
||||
numberFiles={fileInfos.length}
|
||||
selectedFilter={filter}
|
||||
teams={teams}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const NO_TEAMS_HEIGHT = 392;
|
|||
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
teamContainer: {
|
||||
paddingLeft: 12,
|
||||
paddingLeft: 8,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -681,6 +681,7 @@
|
|||
"mobile.search.show_less": "Show less",
|
||||
"mobile.search.show_more": "Show more",
|
||||
"mobile.search.team.select": "Select a team to search",
|
||||
"mobile.search.results": "{count} search {count, plural, one {result} other {results}}",
|
||||
"mobile.server_identifier.exists": "You are already connected to this server.",
|
||||
"mobile.server_link.error.text": "The link could not be found on this server.",
|
||||
"mobile.server_link.error.title": "Link Error",
|
||||
|
|
@ -1061,4 +1062,4 @@
|
|||
"video.download_description": "This video must be downloaded to play it.",
|
||||
"video.failed_description": "An error occurred while trying to play the video.",
|
||||
"your.servers": "Your servers"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue