Add permission checks before saving image (#945)

* catch permission errors when saving image to album

* Save photos to media library alone (not an album)

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
zio/stable
Ansh 2023-07-03 11:17:12 -07:00 committed by GitHub
parent 7cf0db7d14
commit edff1992b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 26 deletions

View File

@ -108,13 +108,7 @@ export async function shareImageModal({uri}: {uri: string}) {
RNFS.unlink(imagePath) RNFS.unlink(imagePath)
} }
export async function saveImageToAlbum({ export async function saveImageToMediaLibrary({uri}: {uri: string}) {
uri,
album,
}: {
uri: string
album: string
}) {
// download the file to cache // download the file to cache
// NOTE // NOTE
// assuming PNG // assuming PNG
@ -126,14 +120,8 @@ export async function saveImageToAlbum({
let imagePath = downloadResponse.path() let imagePath = downloadResponse.path()
imagePath = normalizePath(await moveToPermanentPath(imagePath, '.png'), true) imagePath = normalizePath(await moveToPermanentPath(imagePath, '.png'), true)
// save to the album (creating as needed) // save
const assetRef = await MediaLibrary.createAssetAsync(imagePath) await MediaLibrary.createAssetAsync(imagePath)
const albumRef = await MediaLibrary.getAlbumAsync(album)
if (albumRef) {
await MediaLibrary.addAssetsToAlbumAsync(assetRef, albumRef)
} else {
await MediaLibrary.createAlbumAsync(album, assetRef)
}
} }
export function getImageDim(path: string): Promise<Dimensions> { export function getImageDim(path: string): Promise<Dimensions> {

View File

@ -5,21 +5,47 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import ImageView from './ImageViewing' import ImageView from './ImageViewing'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import * as models from 'state/models/ui/shell' import * as models from 'state/models/ui/shell'
import {shareImageModal, saveImageToAlbum} from 'lib/media/manip' import {shareImageModal, saveImageToMediaLibrary} from 'lib/media/manip'
import * as Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {Text} from '../util/text/Text' import {Text} from '../util/text/Text'
import {s, colors} from 'lib/styles' import {s, colors} from 'lib/styles'
import {Button} from '../util/forms/Button' import {Button} from '../util/forms/Button'
import {isIOS} from 'platform/detection' import {isIOS} from 'platform/detection'
import * as MediaLibrary from 'expo-media-library'
export const Lightbox = observer(function Lightbox() { export const Lightbox = observer(function Lightbox() {
const store = useStores() const store = useStores()
const [isAltExpanded, setAltExpanded] = React.useState(false) const [isAltExpanded, setAltExpanded] = React.useState(false)
const [permissionResponse, requestPermission] = MediaLibrary.usePermissions()
const onClose = React.useCallback(() => { const onClose = React.useCallback(() => {
store.shell.closeLightbox() store.shell.closeLightbox()
}, [store]) }, [store])
const saveImageToAlbumWithToasts = React.useCallback(
async (uri: string) => {
if (!permissionResponse || permissionResponse.granted === false) {
Toast.show('Permission to access camera roll is required.')
if (permissionResponse?.canAskAgain) {
requestPermission()
} else {
Toast.show(
'Permission to access camera roll was denied. Please enable it in your system settings.',
)
}
return
}
try {
await saveImageToMediaLibrary({uri})
Toast.show('Saved to your camera roll.')
} catch (e: any) {
Toast.show(`Failed to save image: ${String(e)}`)
}
},
[permissionResponse, requestPermission],
)
const LightboxFooter = React.useCallback( const LightboxFooter = React.useCallback(
({imageIndex}: {imageIndex: number}) => { ({imageIndex}: {imageIndex: number}) => {
const lightbox = store.shell.activeLightbox const lightbox = store.shell.activeLightbox
@ -74,7 +100,7 @@ export const Lightbox = observer(function Lightbox() {
</View> </View>
) )
}, },
[store.shell.activeLightbox, isAltExpanded, setAltExpanded], [store.shell.activeLightbox, isAltExpanded, saveImageToAlbumWithToasts],
) )
if (!store.shell.activeLightbox) { if (!store.shell.activeLightbox) {
@ -106,15 +132,6 @@ export const Lightbox = observer(function Lightbox() {
} }
}) })
async function saveImageToAlbumWithToasts(uri: string) {
try {
await saveImageToAlbum({uri, album: 'Bluesky'})
Toast.show('Saved to the "Bluesky" album.')
} catch (e: any) {
Toast.show(`Failed to save image: ${String(e)}`)
}
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
footer: { footer: {
paddingTop: 16, paddingTop: 16,