This repository has been archived on 2025-07-31. You can view files and clone it, but cannot push or open issues or pull requests.
Files
terminally-online/src/screens/memeView.tsx
Nikolaos Karaolidis abe1c0847d Refactor styles
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2023-07-26 10:14:01 +03:00

143 lines
4.1 KiB
TypeScript

import React, { useRef, useState } from 'react';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { StyleSheet } from 'react-native';
import { useQuery, useRealm } from '@realm/react';
import { FlashList } from '@shopify/flash-list';
import { Appbar, Portal, Snackbar } from 'react-native-paper';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import { RootStackParamList, ROUTE } from '../types';
import { Meme } from '../database';
import { MemeViewItem } from '../components';
import {
copyMeme,
deleteMeme,
editMeme,
favoriteMeme,
multipleIdQuery,
shareMeme,
} from '../utilities';
import { NavigationProp, useNavigation } from '@react-navigation/native';
const memeViewStyles = StyleSheet.create({
// eslint-disable-next-line react-native/no-color-literals
header: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 1,
backgroundColor: 'transparent',
},
// eslint-disable-next-line react-native/no-color-literals
footer: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'transparent',
flexDirection: 'row',
justifyContent: 'space-evenly',
},
snackbar: {
marginBottom: 64,
},
});
const MemeView = ({
route,
}: NativeStackScreenProps<RootStackParamList, ROUTE.MEME_VIEW>) => {
const { height, width } = useSafeAreaFrame();
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
const realm = useRealm();
const { ids } = route.params;
const [index, setIndex] = useState(route.params.index);
const [snackbarVisible, setSnackbarVisible] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState('');
const flashListRef = useRef<FlashList<Meme>>(null);
const memes = useQuery<Meme>(Meme.schema.name, collectionIn => {
return collectionIn.filtered(multipleIdQuery(ids));
});
if (memes.length === 0) return <></>;
return (
<>
<Appbar.Header style={memeViewStyles.header}>
<Appbar.BackAction onPress={() => navigation.goBack()} />
<Appbar.Content title={memes[index].title} />
</Appbar.Header>
<FlashList
ref={flashListRef}
key={height}
data={memes}
initialScrollIndex={index}
onScroll={event => {
const newIndex = Math.round(
event.nativeEvent.contentOffset.x /
event.nativeEvent.layoutMeasurement.width,
);
if (newIndex !== index) setIndex(newIndex);
}}
estimatedItemSize={width}
estimatedListSize={{ height, width }}
pagingEnabled
horizontal
showsHorizontalScrollIndicator={false}
renderItem={({ item: meme }) => <MemeViewItem meme={meme} />}
/>
<Appbar style={memeViewStyles.footer}>
<Appbar.Action
icon={memes[index].isFavorite ? 'heart' : 'heart-outline'}
onPress={() => favoriteMeme(realm, memes[index])}
/>
<Appbar.Action icon="share" onPress={() => shareMeme(memes[index])} />
<Appbar.Action
icon="content-copy"
onPress={() => {
copyMeme(memes[index]);
setSnackbarMessage('Meme copied!');
setSnackbarVisible(true);
}}
/>
<Appbar.Action
icon="pencil"
onPress={() => {
editMeme(navigation, memes[index]);
}}
/>
<Appbar.Action
icon="delete"
onPress={() => {
if (index === memes.length - 1) {
setIndex(index - 1);
flashListRef.current?.scrollToIndex({
index: index - 1,
});
}
void deleteMeme(realm, memes[index]);
if (memes.length === 1) navigation.goBack();
}}
/>
</Appbar>
<Portal>
<Snackbar
visible={snackbarVisible}
onDismiss={() => setSnackbarVisible(false)}
style={memeViewStyles.snackbar}
action={{
label: 'Dismiss',
onPress: () => setSnackbarVisible(false),
}}>
{snackbarMessage}
</Snackbar>
</Portal>
</>
);
};
export default MemeView;