Add tag sorting

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-07-15 13:09:53 +03:00
parent 1e36e01ea1
commit de44828434
13 changed files with 312 additions and 98 deletions

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { View } from 'react-native';
import { StyleSheet, View } from 'react-native';
import {
Button,
Menu,
@@ -7,22 +7,33 @@ import {
Divider,
useTheme,
Searchbar,
HelperText,
} from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux';
import { RootScrollView } from '../components';
import styles from '../styles';
import { SORT, SORT_DIRECTION } from '../types';
import { HOME_SORT, SORT_DIRECTION } from '../types';
import { getSortIcon, getViewIcon } from '../utilities';
import {
RootState,
cycleView,
toggleSortDirection,
setSortDirection,
toggleFavoritesOnly,
setSort,
setFilter,
cycleHomeView,
toggleHomeSortDirection,
setHomeSortDirection,
toggleHomeFavoritesOnly,
setHomeSort,
setHomeFilter,
} from '../state';
import { MEME_TYPE, memeTypePlural } from '../database';
import { MEME_TYPE, Meme, memeTypePlural } from '../database';
import { useQuery } from '@realm/react';
const homeStyles = StyleSheet.create({
headerButtonView: {
height: 50,
},
helperText: {
marginVertical: 10,
},
});
const Home = () => {
const theme = useTheme();
@@ -40,26 +51,27 @@ const Home = () => {
const [sortMenuVisible, setSortMenuVisible] = useState(false);
const [filterMenuVisible, setFilterMenuVisible] = useState(false);
const handleSortModeChange = (newSort: SORT) => {
const handleSortModeChange = (newSort: HOME_SORT) => {
if (newSort === sort) {
dispatch(toggleSortDirection());
dispatch(toggleHomeSortDirection());
} else {
dispatch(setSort(newSort));
if (newSort === SORT.TITLE) {
dispatch(setSortDirection(SORT_DIRECTION.ASCENDING));
dispatch(setHomeSort(newSort));
if (newSort === HOME_SORT.TITLE) {
dispatch(setHomeSortDirection(SORT_DIRECTION.ASCENDING));
} else {
dispatch(setSortDirection(SORT_DIRECTION.DESCENDING));
dispatch(setHomeSortDirection(SORT_DIRECTION.DESCENDING));
}
}
setSortMenuVisible(false);
};
const handleFilterChange = (newFilter: MEME_TYPE | undefined) => {
dispatch(setFilter(newFilter));
dispatch(setHomeFilter(newFilter));
setFilterMenuVisible(false);
};
const [search, setSearch] = useState('');
const memes = useQuery<Meme>('Meme');
return (
<RootScrollView padded>
@@ -68,7 +80,12 @@ const Home = () => {
value={search}
onChangeText={setSearch}
/>
<View style={[styles.flexRowSpaceBetween, styles.alignCenter]}>
<View
style={[
styles.flexRowSpaceBetween,
styles.alignCenter,
homeStyles.headerButtonView,
]}>
<View style={[styles.flexRow, styles.alignCenter]}>
<Menu
visible={sortMenuVisible}
@@ -82,31 +99,33 @@ const Home = () => {
Sort By: {sort}
</Button>
}>
{Object.keys(SORT).map(key => {
{Object.keys(HOME_SORT).map(key => {
return (
<Menu.Item
key={key}
onPress={() =>
handleSortModeChange(SORT[key as keyof typeof SORT])
handleSortModeChange(
HOME_SORT[key as keyof typeof HOME_SORT],
)
}
title={SORT[key as keyof typeof SORT]}
title={HOME_SORT[key as keyof typeof HOME_SORT]}
/>
);
})}
</Menu>
</View>
<View style={styles.flexRow}>
<View style={[styles.flexRow, styles.alignCenter]}>
<IconButton
icon={getViewIcon(view)}
iconColor={theme.colors.primary}
size={18}
onPress={() => dispatch(cycleView())}
size={16}
onPress={() => dispatch(cycleHomeView())}
/>
<IconButton
icon={favoritesOnly ? 'heart' : 'heart-outline'}
iconColor={theme.colors.primary}
size={18}
onPress={() => dispatch(toggleFavoritesOnly())}
size={16}
onPress={() => dispatch(toggleHomeFavoritesOnly())}
/>
<Menu
visible={filterMenuVisible}
@@ -116,7 +135,7 @@ const Home = () => {
onPress={() => setFilterMenuVisible(true)}
icon={filter ? 'filter' : 'filter-outline'}
iconColor={theme.colors.primary}
size={18}
size={16}
/>
}>
<Menu.Item
@@ -141,6 +160,14 @@ const Home = () => {
</View>
</View>
<Divider />
{/* TODO: Meme Views */}
{memes.length === 0 && (
<View style={styles.alignCenter}>
<HelperText type={'info'} style={homeStyles.helperText}>
No memes found
</HelperText>
</View>
)}
</RootScrollView>
);
};

View File

@@ -1,16 +1,35 @@
import React, { useState } from 'react';
import { DataTable, HelperText, Searchbar } from 'react-native-paper';
import { StyleSheet, View } from 'react-native';
import {
Button,
DataTable,
Divider,
HelperText,
Menu,
Searchbar,
} from 'react-native-paper';
import { useQuery, useRealm } from '@realm/react';
import { useDispatch, useSelector } from 'react-redux';
import { RootScrollView, TagChip } from '../components';
import { Tag, deleteTag } from '../database';
import { StyleSheet, View } from 'react-native';
import styles from '../styles';
import {
RootState,
setTagsSort,
setTagsSortDirection,
toggleTagsSortDirection,
} from '../state';
import { SORT_DIRECTION, TAG_SORT, tagSortQuery } from '../types';
import { getSortIcon } from '../utilities';
const tagStyles = StyleSheet.create({
headerButtonView: {
height: 50,
},
helperText: {
marginVertical: 10,
},
view: {
tagView: {
justifyContent: 'center',
maxWidth: '75%',
},
@@ -18,37 +37,90 @@ const tagStyles = StyleSheet.create({
const Tags = () => {
const realm = useRealm();
const sort = useSelector((state: RootState) => state.tags.sort);
const sortDirection = useSelector(
(state: RootState) => state.tags.sortDirection,
);
const dispatch = useDispatch();
const [sortMenuVisible, setSortMenuVisible] = useState(false);
const handleSortModeChange = (newSort: TAG_SORT) => {
if (newSort === sort) {
dispatch(toggleTagsSortDirection());
} else {
dispatch(setTagsSort(newSort));
if (newSort === TAG_SORT.NAME) {
dispatch(setTagsSortDirection(SORT_DIRECTION.ASCENDING));
} else {
dispatch(setTagsSortDirection(SORT_DIRECTION.DESCENDING));
}
}
setSortMenuVisible(false);
};
const [search, setSearch] = useState('');
const tags = useQuery<Tag>('Tag').filtered(`name CONTAINS[c] "${search}"`);
const tags = useQuery<Tag>('Tag')
.filtered(`name CONTAINS[c] "${search}"`)
.sorted(tagSortQuery(sort), sortDirection === SORT_DIRECTION.ASCENDING);
return (
<RootScrollView padded style={styles.alignCenter}>
<RootScrollView padded>
<Searchbar
placeholder="Search Tags"
value={search}
onChangeText={setSearch}
/>
<View
style={[
styles.flexRow,
styles.alignCenter,
tagStyles.headerButtonView,
]}>
<Menu
visible={sortMenuVisible}
onDismiss={() => setSortMenuVisible(false)}
anchor={
<Button
onPress={() => setSortMenuVisible(true)}
icon={getSortIcon(sort, sortDirection)}
contentStyle={styles.flexRowReverse}
compact>
Sort By: {sort}
</Button>
}>
{Object.keys(TAG_SORT).map(key => {
return (
<Menu.Item
key={key}
onPress={() =>
handleSortModeChange(TAG_SORT[key as keyof typeof TAG_SORT])
}
title={TAG_SORT[key as keyof typeof TAG_SORT]}
/>
);
})}
</Menu>
</View>
<Divider />
<DataTable>
<DataTable.Header>
<DataTable.Title>Tag</DataTable.Title>
<DataTable.Title numeric>Items</DataTable.Title>
</DataTable.Header>
{tags.map(tag => (
<DataTable.Row
key={tag.id.toHexString()}
onPress={() => deleteTag(realm, tag)}>
<View style={tagStyles.view}>
<View style={tagStyles.tagView}>
<TagChip tag={tag} />
</View>
<DataTable.Cell numeric>{tag.memes.length}</DataTable.Cell>
<DataTable.Cell numeric>{tag.memesLength}</DataTable.Cell>
</DataTable.Row>
))}
</DataTable>
{tags.length === 0 && (
<HelperText type={'info'} style={tagStyles.helperText}>
No tags found
</HelperText>
<View style={styles.alignCenter}>
<HelperText type={'info'} style={tagStyles.helperText}>
No tags found
</HelperText>
</View>
)}
</RootScrollView>
);