Add video support
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -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}
|
||||
|
@@ -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(
|
||||
|
@@ -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(
|
||||
|
Reference in New Issue
Block a user