Add video support

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-08-01 14:35:10 +03:00
parent f1f969c8ea
commit b83407f1f4
13 changed files with 358 additions and 158 deletions

View File

@@ -6,7 +6,13 @@ import { FlashList } from '@shopify/flash-list';
import { Appbar, Portal, Snackbar } from 'react-native-paper';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import { NavigationProp, useNavigation } from '@react-navigation/native';
import { RootStackParamList, ROUTE } from '../types';
import { useSelector } from 'react-redux';
import {
memesSortQuery,
RootStackParamList,
ROUTE,
SORT_DIRECTION,
} from '../types';
import { Meme } from '../database';
import { LoadingView, MemeViewItem } from '../components';
import {
@@ -17,7 +23,6 @@ import {
multipleIdQuery,
shareMeme,
} from '../utilities';
import { useSelector } from 'react-redux';
import { RootState } from '../state';
const memeViewStyles = StyleSheet.create({
@@ -50,6 +55,10 @@ const MemeView = ({
}: NativeStackScreenProps<RootStackParamList, ROUTE.MEME_VIEW>) => {
const { height, width } = useSafeAreaFrame();
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
const sort = useSelector((state: RootState) => state.memes.sort);
const sortDirection = useSelector(
(state: RootState) => state.memes.sortDirection,
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const storageUri = useSelector(
(state: RootState) => state.settings.storageUri,
@@ -61,15 +70,20 @@ const MemeView = ({
const flashListRef = useRef<FlashList<Meme>>(null);
const [index, setIndex] = useState(route.params.index);
const index = useRef(route.params.index);
const memes = useQuery<Meme>(Meme.schema.name, collectionIn => {
return collectionIn.filtered(multipleIdQuery(route.params.ids));
return collectionIn
.filtered(multipleIdQuery(route.params.ids))
.sorted(
memesSortQuery(sort),
sortDirection === SORT_DIRECTION.DESCENDING,
);
});
useEffect(() => {
if (memes.length === 0) navigation.goBack();
if (index >= memes.length) {
setIndex(memes.length - 1);
if (index.current >= memes.length) {
index.current = memes.length - 1;
flashListRef.current?.scrollToIndex({ index: memes.length - 1 });
}
}, [index, memes.length, navigation]);
@@ -79,19 +93,19 @@ const MemeView = ({
<Appbar.Header style={memeViewStyles.header}>
<Appbar.BackAction onPress={() => navigation.goBack()} />
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */}
<Appbar.Content title={memes[index]?.title} />
<Appbar.Content title={memes[index.current]?.title} />
</Appbar.Header>
<FlashList
ref={flashListRef}
key={height}
data={memes}
initialScrollIndex={index}
initialScrollIndex={index.current}
onScroll={event => {
const newIndex = Math.round(
event.nativeEvent.contentOffset.x /
event.nativeEvent.layoutMeasurement.width,
);
if (newIndex !== index) setIndex(newIndex);
if (newIndex !== index.current) index.current = newIndex;
}}
estimatedItemSize={width}
estimatedListSize={{ height, width }}
@@ -111,14 +125,14 @@ const MemeView = ({
<Appbar style={memeViewStyles.footer}>
<Appbar.Action
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
icon={memes[index]?.isFavorite ? 'heart' : 'heart-outline'}
onPress={() => favoriteMeme(realm, memes[index])}
icon={memes[index.current]?.isFavorite ? 'heart' : 'heart-outline'}
onPress={() => favoriteMeme(realm, memes[index.current])}
disabled={isBlocked}
/>
<Appbar.Action
icon="share"
onPress={() => {
shareMeme(realm, storageUri, memes[index]).catch(() =>
shareMeme(realm, storageUri, memes[index.current]).catch(() =>
setSnackbarMessage('Failed to share meme!'),
);
}}
@@ -127,7 +141,7 @@ const MemeView = ({
<Appbar.Action
icon="content-copy"
onPress={async () => {
await copyMeme(realm, storageUri, memes[index])
await copyMeme(realm, storageUri, memes[index.current])
.then(() => setSnackbarMessage('Meme copied!'))
.catch(() => setSnackbarMessage('Failed to copy meme!'));
}}
@@ -136,7 +150,7 @@ const MemeView = ({
<Appbar.Action
icon="pencil"
onPress={() => {
editMeme(navigation, memes[index]);
editMeme(navigation, memes[index.current]);
}}
disabled={isBlocked}
/>
@@ -144,7 +158,7 @@ const MemeView = ({
icon="delete"
onPress={async () => {
setIsBlocked(true);
await deleteMeme(realm, storageUri, memes[index]);
await deleteMeme(realm, storageUri, memes[index.current]);
setIsBlocked(false);
}}
disabled={isBlocked}

View File

@@ -98,7 +98,7 @@ const Memes = () => {
[sort, sortDirection, favoritesOnly, filter, search],
);
const [scrollOffset, setScrollOffset] = useState(0);
const previousOffset = useRef(0);
const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
const currentOffset = event.nativeEvent.contentOffset.y;
@@ -106,13 +106,13 @@ const Memes = () => {
if (currentOffset <= 150) {
dispatch(setNavVisible(true));
} else {
const diff = currentOffset - scrollOffset;
if (Math.abs(diff) > 50) {
const diff = currentOffset - previousOffset.current;
if (Math.abs(diff) > 35) {
dispatch(setNavVisible(diff < 0));
}
}
setScrollOffset(currentOffset);
previousOffset.current = currentOffset;
};
const flashListRef = useRef<FlashList<Meme>>(null);
@@ -120,7 +120,7 @@ const Memes = () => {
useFocusEffect(
useCallback(() => {
const handleBackPress = () => {
if (scrollOffset <= 0) return false;
if (previousOffset.current <= 0) return false;
flashListRef.current?.scrollToOffset({ offset: 0, animated: true });
return true;
};
@@ -129,7 +129,7 @@ const Memes = () => {
return () =>
BackHandler.removeEventListener('hardwareBackPress', handleBackPress);
}, [scrollOffset]),
}, []),
);
useFocusEffect(

View File

@@ -71,7 +71,7 @@ const Tags = () => {
[search, sort, sortDirection],
);
const [scrollOffset, setScrollOffset] = useState(0);
const previousOffset = useRef(0);
const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
const currentOffset = event.nativeEvent.contentOffset.y;
@@ -79,11 +79,11 @@ const Tags = () => {
if (currentOffset <= 150) {
dispatch(setNavVisible(true));
} else {
const diff = currentOffset - scrollOffset;
const diff = currentOffset - previousOffset.current;
if (Math.abs(diff) > 50) dispatch(setNavVisible(diff < 0));
}
setScrollOffset(currentOffset);
previousOffset.current = currentOffset;
};
const flashListRef = useRef<FlashList<Tag>>(null);
@@ -91,7 +91,7 @@ const Tags = () => {
useFocusEffect(
useCallback(() => {
const handleBackPress = () => {
if (scrollOffset > 0) {
if (previousOffset.current > 0) {
flashListRef.current?.scrollToOffset({ offset: 0, animated: true });
return true;
}
@@ -102,7 +102,7 @@ const Tags = () => {
return () =>
BackHandler.removeEventListener('hardwareBackPress', handleBackPress);
}, [scrollOffset]),
}, []),
);
useFocusEffect(