Fix crash when deleting memes
Again. Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
import { useTheme } from 'react-native-paper';
|
||||
|
||||
@@ -10,12 +10,17 @@ const loadingViewStyles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const LoadingView = () => {
|
||||
const LoadingView = ({ ...props }: ComponentProps<typeof View>) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[loadingViewStyles.view, { backgroundColor: colors.background }]}>
|
||||
{...props}
|
||||
style={[
|
||||
props.style,
|
||||
loadingViewStyles.view,
|
||||
{ backgroundColor: colors.background },
|
||||
]}>
|
||||
<ActivityIndicator size="large" color={colors.primary} />
|
||||
</View>
|
||||
);
|
||||
|
@@ -27,11 +27,7 @@ const MemeViewItem = ({ meme }: { meme: Meme }) => {
|
||||
const { dimensions, loading, error } = useImageDimensions({ uri });
|
||||
|
||||
if (!error && (loading || !dimensions)) {
|
||||
return (
|
||||
<View style={{ width, height }}>
|
||||
<LoadingView />
|
||||
</View>
|
||||
);
|
||||
return <LoadingView style={{ width, height }} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@@ -17,7 +17,6 @@ const memeTypePlural = {
|
||||
[MEME_TYPE.TEXT]: 'Text',
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
class Meme extends Object<Meme> {
|
||||
id!: BSON.UUID;
|
||||
memeType!: MEME_TYPE;
|
||||
|
@@ -2,7 +2,6 @@ import { BSON, Object, ObjectSchema } from 'realm';
|
||||
import { Meme } from './meme';
|
||||
import { generateRandomColor } from '../utilities';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
class Tag extends Object<Tag> {
|
||||
id!: BSON.UUID;
|
||||
name!: string;
|
||||
|
@@ -56,23 +56,33 @@ const AddMeme = ({
|
||||
const [memeIsFavorite, setMemeIsFavorite] = useState(false);
|
||||
const [memeTags, setMemeTags] = useState(new Map<string, Tag>());
|
||||
|
||||
useEffect(() => {
|
||||
const loadMeme = async () => {
|
||||
const mimeType = await guessMimeType(file.current.uri);
|
||||
if (!mimeType) {
|
||||
setMemeError(
|
||||
new Error('Could not determine MIME type or file is not supported.'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setMemeMimeType(mimeType);
|
||||
};
|
||||
|
||||
const resetState = useCallback(async (newIndex = 0) => {
|
||||
setMemeLoading(true);
|
||||
void loadMeme();
|
||||
// eslint-disable-next-line unicorn/no-useless-undefined
|
||||
setMemeError(undefined);
|
||||
|
||||
setIndex(newIndex);
|
||||
file.current = files.current[newIndex];
|
||||
|
||||
setMemeUri(file.current.uri);
|
||||
setMemeFilename(file.current.filename);
|
||||
setMemeTitle(validateMemeTitle('New Meme'));
|
||||
setMemeIsFavorite(false);
|
||||
setMemeTags(new Map<string, Tag>());
|
||||
|
||||
const mimeType = await guessMimeType(file.current.uri);
|
||||
if (!mimeType) {
|
||||
setMemeError(
|
||||
new Error('Could not determine MIME type or file is not supported.'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
setMemeMimeType(mimeType);
|
||||
|
||||
setMemeLoading(false);
|
||||
}, [file]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => void resetState(), [resetState]);
|
||||
|
||||
const saveMeme = useCallback(async () => {
|
||||
if (!memeMimeType) return;
|
||||
@@ -126,40 +136,24 @@ const AddMeme = ({
|
||||
goBack();
|
||||
}, [goBack, saveMeme]);
|
||||
|
||||
const resetState = useCallback(() => {
|
||||
setMemeUri(file.current.uri);
|
||||
setMemeFilename(file.current.filename);
|
||||
setMemeTitle(validateMemeTitle('New Meme'));
|
||||
setMemeIsFavorite(false);
|
||||
setMemeTags(new Map<string, Tag>());
|
||||
}, []);
|
||||
|
||||
const handleSaveAndNext = useCallback(async () => {
|
||||
setIsSaving(true);
|
||||
await saveMeme();
|
||||
setIsSaving(false);
|
||||
|
||||
setIndex(index + 1);
|
||||
file.current = files.current[index + 1];
|
||||
|
||||
resetState();
|
||||
await resetState(index + 1);
|
||||
}, [index, resetState, saveMeme]);
|
||||
|
||||
const handleSaveAndAddMore = useCallback(async () => {
|
||||
setIsSavingAndAddingMore(true);
|
||||
await saveMeme();
|
||||
setIsSavingAndAddingMore(false);
|
||||
|
||||
setIndex(0);
|
||||
const response = await pick({
|
||||
type: allowedMimeTypes,
|
||||
allowMultiSelection: true,
|
||||
}).catch(goBack);
|
||||
if (!response) return;
|
||||
files.current = documentPickerResponseToAddMemeFile(response);
|
||||
file.current = files.current[0];
|
||||
|
||||
resetState();
|
||||
await resetState(0);
|
||||
}, [goBack, resetState, saveMeme]);
|
||||
|
||||
return (
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { useQuery, useRealm } from '@realm/react';
|
||||
@@ -8,7 +8,7 @@ import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
||||
import { NavigationProp, useNavigation } from '@react-navigation/native';
|
||||
import { RootStackParamList, ROUTE } from '../types';
|
||||
import { Meme } from '../database';
|
||||
import { MemeViewItem } from '../components';
|
||||
import { LoadingView, MemeViewItem } from '../components';
|
||||
import {
|
||||
copyMeme,
|
||||
deleteMeme,
|
||||
@@ -56,22 +56,30 @@ const MemeView = ({
|
||||
)!;
|
||||
const realm = useRealm();
|
||||
|
||||
const { ids } = route.params;
|
||||
const [index, setIndex] = useState(route.params.index);
|
||||
|
||||
const [isBlocked, setIsBlocked] = useState(false);
|
||||
const [snackbarMessage, setSnackbarMessage] = useState<string>();
|
||||
|
||||
const flashListRef = useRef<FlashList<Meme>>(null);
|
||||
|
||||
const [index, setIndex] = useState(route.params.index);
|
||||
const memes = useQuery<Meme>(Meme.schema.name, collectionIn => {
|
||||
return collectionIn.filtered(multipleIdQuery(ids));
|
||||
return collectionIn.filtered(multipleIdQuery(route.params.ids));
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (memes.length === 0) navigation.goBack();
|
||||
if (index >= memes.length) {
|
||||
setIndex(memes.length - 1);
|
||||
flashListRef.current?.scrollToIndex({ index: memes.length - 1 });
|
||||
}
|
||||
}, [index, memes.length, navigation]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Appbar.Header style={memeViewStyles.header}>
|
||||
<Appbar.BackAction onPress={() => navigation.goBack()} />
|
||||
<Appbar.Content title={memes[index].title} />
|
||||
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */}
|
||||
<Appbar.Content title={memes[index]?.title} />
|
||||
</Appbar.Header>
|
||||
<FlashList
|
||||
ref={flashListRef}
|
||||
@@ -90,12 +98,22 @@ const MemeView = ({
|
||||
pagingEnabled
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
renderItem={({ item: meme }) => <MemeViewItem meme={meme} />}
|
||||
renderItem={({ item }) =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
item ? (
|
||||
<MemeViewItem meme={item} />
|
||||
) : (
|
||||
<LoadingView style={{ width, height }} />
|
||||
)
|
||||
}
|
||||
scrollEnabled={!isBlocked}
|
||||
/>
|
||||
<Appbar style={memeViewStyles.footer}>
|
||||
<Appbar.Action
|
||||
icon={memes[index].isFavorite ? 'heart' : 'heart-outline'}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
icon={memes[index]?.isFavorite ? 'heart' : 'heart-outline'}
|
||||
onPress={() => favoriteMeme(realm, memes[index])}
|
||||
disabled={isBlocked}
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="share"
|
||||
@@ -104,6 +122,7 @@ const MemeView = ({
|
||||
setSnackbarMessage('Failed to share meme!'),
|
||||
);
|
||||
}}
|
||||
disabled={isBlocked}
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="content-copy"
|
||||
@@ -112,25 +131,23 @@ const MemeView = ({
|
||||
.then(() => setSnackbarMessage('Meme copied!'))
|
||||
.catch(() => setSnackbarMessage('Failed to copy meme!'));
|
||||
}}
|
||||
disabled={isBlocked}
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="pencil"
|
||||
onPress={() => {
|
||||
editMeme(navigation, memes[index]);
|
||||
}}
|
||||
disabled={isBlocked}
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="delete"
|
||||
onPress={() => {
|
||||
void deleteMeme(realm, storageUri, memes[index]);
|
||||
if (index === memes.length - 1) {
|
||||
setIndex(index - 1);
|
||||
flashListRef.current?.scrollToIndex({
|
||||
index: index - 1,
|
||||
});
|
||||
}
|
||||
if (memes.length === 1) navigation.goBack();
|
||||
onPress={async () => {
|
||||
setIsBlocked(true);
|
||||
await deleteMeme(realm, storageUri, memes[index]);
|
||||
setIsBlocked(false);
|
||||
}}
|
||||
disabled={isBlocked}
|
||||
/>
|
||||
</Appbar>
|
||||
<Portal>
|
||||
|
@@ -91,8 +91,7 @@ const updateNoMedia = createAsyncThunk(
|
||||
|
||||
const validateSettings = createAsyncThunk(
|
||||
'settings/validateSettings',
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
async (_, { dispatch, getState }) => {
|
||||
async (ignored, { dispatch, getState }) => {
|
||||
const state = getState() as RootState;
|
||||
const { storageUri, noMedia } = state.settings;
|
||||
|
||||
|
@@ -1,8 +1,7 @@
|
||||
const packageName = 'com.karaolidis.terminallyonline';
|
||||
const appName = 'Terminally Online';
|
||||
const fileProvider = 'com.karaolidis.terminallyonline.rnshare.fileprovider';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const noOp = () => {};
|
||||
|
||||
export { packageName, appName, fileProvider, noOp };
|
||||
export { packageName, appName, noOp };
|
||||
|
@@ -7,7 +7,7 @@ export {
|
||||
rgbToRgba,
|
||||
generateRandomColor,
|
||||
} from './color';
|
||||
export { packageName, appName, fileProvider, noOp } from './constants';
|
||||
export { packageName, appName, noOp } from './constants';
|
||||
export { multipleIdQuery } from './database';
|
||||
export { getFlashListItemHeight, getFontAwesome5IconSize } from './dimensions';
|
||||
export {
|
||||
|
Reference in New Issue
Block a user