Closed amosbastian closed 3 years ago
I second this, I needed this exact functionality today
I second this, I needed this exact functionality today
I ended up adapting part of his code to implement this. Maybe this is useful for you:
// AssetsSelector.tsx
const AssetsSelector = ({initialAssets, onCancel, onConfirm}: AssetsSelectorProps): JSX.Element => {
const [selectedItems, setSelectedItems] = useState<string[]>(initialAssets.map(asset => asset.id));
const [assets, setAssets] = useAssets();
...
return (
<Screen>
<AssetsSelectorHeading onCancel={onCancel} onConfirm={handleConfirm} />
<SelectableAssetsList
assets={assets}
loadMoreAssets={setAssets}
onClick={onAssetSelect}
selectedItems={selectedItems}
size={width / NUM_COLUMNS}
/>
</Screen>
);
};
// useAssets.tsx
import {Asset, AssetsOptions, getAssetsAsync, PagedInfo} from 'expo-media-library';
import * as Permissions from 'expo-permissions';
import {useCallback, useEffect, useState} from 'react';
import showToast from '../utils/showToast';
export const useAssets = (): [Asset[], () => Promise<void> | undefined] => {
const [assets, setAssets] = useState<Asset[]>([]);
const [permissions, setPermissions] = useState({
hasCameraPermission: false,
hasCameraRollPermission: false,
});
const [options, setOptions] = useState<Partial<AssetsOptions> & Partial<PagedInfo<Asset>>>({
first: 500,
after: '',
totalCount: 0,
endCursor: '',
hasNextPage: true,
});
const loadAssets = useCallback(
async (assetsOptions: AssetsOptions) => {
try {
const {endCursor, assets: newAssets, hasNextPage} = await getAssetsAsync(assetsOptions);
if (options.after === endCursor) return;
setOptions({
...options,
after: endCursor,
hasNextPage: hasNextPage,
});
return setAssets([...assets, ...newAssets]);
} catch (error) {
showToast({text: error, type: 'danger'});
}
},
[assets, permissions.hasCameraPermission]
);
const getCameraPermissions = useCallback(async () => {
const {status: CAMERA} = await Permissions.askAsync(Permissions.CAMERA);
const {status: MEDIA_LIBRARY} = await Permissions.askAsync(Permissions.MEDIA_LIBRARY);
setPermissions({
hasCameraPermission: CAMERA === 'granted',
hasCameraRollPermission: MEDIA_LIBRARY === 'granted',
});
}, []);
const getAssets = () => {
try {
if (options.hasNextPage) {
const assetsOptions: AssetsOptions = {
first: 200,
mediaType: ['photo', 'video'],
sortBy: ['creationTime'],
};
if (options.after) {
assetsOptions.after = options.after;
}
if (!options.hasNextPage) return;
return permissions.hasCameraRollPermission ? loadAssets(assetsOptions) : getCameraPermissions();
}
} catch (error) {
showToast({text: error, type: 'danger'});
}
};
useEffect(() => {
getAssets();
}, [permissions.hasCameraPermission, permissions.hasCameraRollPermission]);
return [assets, getAssets];
};
ill add this in the end of the month im busy atm , thanks for letting me know , on my list :)
If you have already selected assets and then open
AssetsSelector
again there is no way to pass which assets you have selected previously, which means you have to completely reselect all assets you want. I think this is a common situation (e.g. user selects 1 asset, afterwards decides they want to add 1 more) so it would be nice to have.