Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Cleanup files after each iteration of compression and downloading (#3599)

* delete image on each iteration of compression

* replace a few other instances of `unlink()`

* ensure that moving to the permanent path will succeed

* use `cacheDirectory`

* missing file extension?

* assert

* Remove extra .

* Extract safeDeleteAsync, fix normalization

* Normalize everywhere

* Use safeDeleteAsync in more places

* Delete .bin too

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>

authored by

Hailey
Dan Abramov
and committed by
GitHub
c3fcd486 90c3ec87

+41 -29
+4 -15
src/lib/api/index.ts
··· 1 - import {deleteAsync} from 'expo-file-system' 2 1 import { 3 2 AppBskyEmbedExternal, 4 3 AppBskyEmbedImages, ··· 20 19 import {isNative, isWeb} from 'platform/detection' 21 20 import {ImageModel} from 'state/models/media/image' 22 21 import {LinkMeta} from '../link-meta/link-meta' 22 + import {safeDeleteAsync} from '../media/manip' 23 23 24 24 export interface ExternalEmbedDraft { 25 25 uri: string ··· 119 119 const {width, height} = image.compressed || image 120 120 logger.debug(`Uploading image`) 121 121 const res = await uploadBlob(agent, path, 'image/jpeg') 122 - 123 122 if (isNative) { 124 - try { 125 - deleteAsync(path) 126 - } catch (e) { 127 - console.error(e) 128 - } 123 + safeDeleteAsync(path) 129 124 } 130 - 131 125 images.push({ 132 126 image: res.data.blob, 133 127 alt: image.altText ?? '', ··· 182 176 encoding, 183 177 ) 184 178 thumb = thumbUploadRes.data.blob 185 - 186 - try { 187 - if (isNative) { 188 - deleteAsync(opts.extLink.localThumb.path) 189 - } 190 - } catch (e) { 191 - console.error(e) 179 + if (isNative) { 180 + safeDeleteAsync(opts.extLink.localThumb.path) 192 181 } 193 182 } 194 183 }
+37 -14
src/lib/media/manip.ts
··· 1 1 import {Image as RNImage, Share as RNShare} from 'react-native' 2 - import * as RNFS from 'react-native-fs' 3 2 import {Image} from 'react-native-image-crop-picker' 4 3 import uuid from 'react-native-uuid' 4 + import {cacheDirectory, copyAsync, deleteAsync} from 'expo-file-system' 5 5 import * as MediaLibrary from 'expo-media-library' 6 6 import * as Sharing from 'expo-sharing' 7 7 import ImageResizer from '@bam.tech/react-native-image-resizer' ··· 24 24 mode: 'stretch', 25 25 maxSize, 26 26 }) 27 - const finalImageMovedPath = await moveToPermanentPath(resizedImage.path) 27 + const finalImageMovedPath = await moveToPermanentPath( 28 + resizedImage.path, 29 + '.jpg', 30 + ) 28 31 const finalImg = { 29 32 ...resizedImage, 30 33 path: finalImageMovedPath, ··· 69 72 return 70 73 } 71 74 72 - let localUri = downloadRes.path() 73 - if (!localUri.startsWith('file://')) { 74 - localUri = `file://${localUri}` 75 - } 76 - 75 + const localUri = normalizePath(downloadRes.path(), true) 77 76 return await doResize(localUri, opts) 78 77 } finally { 78 + // TODO Whenever we remove `rn-fetch-blob`, we will need to replace this `flush()` with a `deleteAsync()` -hailey 79 79 if (downloadRes) { 80 80 downloadRes.flush() 81 81 } ··· 111 111 UTI: 'image/png', 112 112 }) 113 113 } 114 - RNFS.unlink(imagePath) 114 + 115 + safeDeleteAsync(imagePath) 115 116 } 116 117 117 118 export async function saveImageToMediaLibrary({uri}: {uri: string}) { ··· 128 129 129 130 // save 130 131 await MediaLibrary.createAssetAsync(imagePath) 132 + safeDeleteAsync(imagePath) 131 133 } 132 134 133 135 export function getImageDim(path: string): Promise<Dimensions> { ··· 174 176 width: resizeRes.width, 175 177 height: resizeRes.height, 176 178 } 179 + } else { 180 + safeDeleteAsync(resizeRes.path) 177 181 } 178 182 } 179 183 throw new Error( ··· 181 185 ) 182 186 } 183 187 184 - async function moveToPermanentPath(path: string, ext = ''): Promise<string> { 188 + async function moveToPermanentPath(path: string, ext = 'jpg'): Promise<string> { 185 189 /* 186 190 Since this package stores images in a temp directory, we need to move the file to a permanent location. 187 191 Relevant: IOS bug when trying to open a second time: ··· 189 193 */ 190 194 const filename = uuid.v4() 191 195 192 - const destinationPath = joinPath( 193 - RNFS.TemporaryDirectoryPath, 194 - `${filename}${ext}`, 195 - ) 196 - await RNFS.moveFile(path, destinationPath) 196 + // cacheDirectory will not ever be null on native, but it could be on web. This function only ever gets called on 197 + // native so we assert as a string. 198 + const destinationPath = joinPath(cacheDirectory as string, filename + ext) 199 + await copyAsync({ 200 + from: normalizePath(path), 201 + to: normalizePath(destinationPath), 202 + }) 203 + safeDeleteAsync(path) 197 204 return normalizePath(destinationPath) 205 + } 206 + 207 + export async function safeDeleteAsync(path: string) { 208 + // Normalize is necessary for Android, otherwise it doesn't delete. 209 + const normalizedPath = normalizePath(path) 210 + try { 211 + await Promise.allSettled([ 212 + deleteAsync(normalizedPath, {idempotent: true}), 213 + // HACK: Try this one too. Might exist due to api-polyfill hack. 214 + deleteAsync(normalizedPath.replace(/\.jpe?g$/, '.bin'), { 215 + idempotent: true, 216 + }), 217 + ]) 218 + } catch (e) { 219 + console.error('Failed to delete file', e) 220 + } 198 221 } 199 222 200 223 function joinPath(a: string, b: string) {