import React, { useCallback, useRef, useState } from 'react'; import { Appbar, Banner, Button, useTheme } from 'react-native-paper'; import { useNavigation } from '@react-navigation/native'; import { ScrollView, View } from 'react-native'; import { NativeStackScreenProps } from '@react-navigation/native-stack'; import { useRealm } from '@realm/react'; import { BSON } from 'realm'; import { AndroidScoped, FileSystem } from 'react-native-file-access'; import { useSelector } from 'react-redux'; import { extension } from 'react-native-mime-types'; import { useDeviceOrientation } from '@react-native-community/hooks'; import { pick } from 'react-native-document-picker'; import { documentPickerResponseToAddMemeFile, ROUTE, RootStackParamList, } from '../../types'; import { Meme, Tag } from '../../database'; import { RootState } from '../../state'; import { allowedMimeTypes, getMemeType, validateMemeTitle, } from '../../utilities'; import { MemeEditor } from '../../components'; import editorStyles from './editorStyles'; const AddMeme = ({ route, }: NativeStackScreenProps) => { const { goBack } = useNavigation(); const { colors } = useTheme(); const orientation = useDeviceOrientation(); const realm = useRealm(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const storageUri = useSelector( (state: RootState) => state.settings.storageUri, )!; const [index, setIndex] = useState(0); const files = useRef(route.params.files); const file = useRef(files.current[index]); const isLastFile = index === files.current.length - 1; const [memeUri, setMemeUri] = useState(file.current.uri); const [memeFilename, setMemeFilename] = useState(file.current.filename); const [memeError, setMemeError] = useState(); const [memeTitle, setMemeTitle] = useState(validateMemeTitle('New Meme')); const [memeIsFavorite, setMemeIsFavorite] = useState(false); const [memeTags, setMemeTags] = useState(new Map()); const [isSaving, setIsSaving] = useState(false); const [isSavingAndAddingMore, setIsSavingAndAddingMore] = useState(false); const saveMeme = useCallback(async () => { const uuid = new BSON.UUID(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const mimeType = file.current.type!; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const memeType = getMemeType(mimeType)!; const fileExtension = extension(mimeType) as string; if (!fileExtension) goBack(); const filename = `${uuid.toHexString()}-${Math.round( Date.now() / 1000, )}.${fileExtension}`; const uri = AndroidScoped.appendPath(storageUri, filename); await FileSystem.cp(file.current.uri, uri); const { size } = await FileSystem.stat(uri); realm.write(() => { const meme: Meme | undefined = realm.create(Meme.schema.name, { id: uuid, type: memeType, filename, mimeType, size, title: memeTitle.parsed, isFavorite: memeIsFavorite, tags: [...memeTags.values()], tagsLength: memeTags.size, }); memeTags.forEach(tag => { tag.dateModified = new Date(); tag.memes.push(meme); tag.memesLength = tag.memes.length; }); }); }, [goBack, memeIsFavorite, memeTags, memeTitle.parsed, realm, storageUri]); const handleSave = useCallback(async () => { setIsSaving(true); await saveMeme(); goBack(); }, [goBack, saveMeme]); const handleSaveAndNext = useCallback(async () => { setIsSaving(true); await saveMeme(); setIsSaving(false); setIndex(index + 1); file.current = files.current[index + 1]; setMemeUri(file.current.uri); setMemeFilename(file.current.filename); setMemeTitle(validateMemeTitle('New Meme')); setMemeIsFavorite(false); setMemeTags(new Map()); }, [index, 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]; setMemeUri(file.current.uri); setMemeFilename(file.current.filename); setMemeTitle(validateMemeTitle('New Meme')); setMemeIsFavorite(false); setMemeTags(new Map()); }, [goBack, saveMeme]); return ( <> goBack()} /> setMemeIsFavorite(!memeIsFavorite)} /> The selected URI appears to be broken. This may have been caused by the file being corrupted or unsupported. ); }; export default AddMeme;