Skip to content

fix: empty path in selected assets + added augementAssetsInfo and resolveWhenDismissed options #581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/imagepicker/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ interface Options {
*/
numberOfColumnsInLandscape?: number;

/**
* Set to false on iOS to disable querying thumbnail/filesize for selected assets
*/
augmentedAssetsInfo: boolean;

/**
* Set to true on iOS to wait for controller to be dismissed before resolving
*/
resolveWhenDismissed: boolean;

/**
* Set the media type (image/video/any) to pick
*/
Expand Down
138 changes: 78 additions & 60 deletions packages/imagepicker/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type FileMap = {
const defaultAssetCollectionSubtypes: NSArray<any> = NSArray.arrayWithArray(<any>[PHAssetCollectionSubtype.SmartAlbumRecentlyAdded, PHAssetCollectionSubtype.SmartAlbumUserLibrary, PHAssetCollectionSubtype.AlbumMyPhotoStream, PHAssetCollectionSubtype.SmartAlbumFavorites, PHAssetCollectionSubtype.SmartAlbumPanoramas, PHAssetCollectionSubtype.SmartAlbumBursts, PHAssetCollectionSubtype.AlbumCloudShared, PHAssetCollectionSubtype.SmartAlbumSelfPortraits, PHAssetCollectionSubtype.SmartAlbumScreenshots, PHAssetCollectionSubtype.SmartAlbumLivePhotos]);
let copyToAppFolder;
let renameFileTo;
let augmentedAssetsInfo;
let resolveWhenDismissed;
let fileMap: FileMap = {};
export class ImagePicker extends ImagePickerBase {
_imagePickerController: QBImagePickerController;
Expand Down Expand Up @@ -45,6 +47,8 @@ export class ImagePicker extends ImagePickerBase {
imagePickerController.prompt = options.prompt || imagePickerController.prompt;
copyToAppFolder = options.copyToAppFolder || false;
renameFileTo = options.renameFileTo || false;
augmentedAssetsInfo = options.augmentedAssetsInfo ?? true;
resolveWhenDismissed = options.resolveWhenDismissed ?? false;
this._imagePickerController = imagePickerController;
}

Expand Down Expand Up @@ -88,7 +92,7 @@ class ImagePickerControllerDelegate extends NSObject implements QBImagePickerCon
});
}

qb_imagePickerControllerDidFinishPickingAssets?(imagePickerController: QBImagePickerController, iosAssets: NSArray<any>): void {
async qb_imagePickerControllerDidFinishPickingAssets?(imagePickerController: QBImagePickerController, iosAssets: NSArray<any>): void {
for (let i = 0; i < iosAssets.count; i++) {
const asset = new ImageAsset(iosAssets.objectAtIndex(i));
const phAssetImage: PHAsset = (<any>asset)._ios;
Expand All @@ -115,74 +119,88 @@ class ImagePickerControllerDelegate extends NSObject implements QBImagePickerCon
} else {
const imageOptions = new PHContentEditingInputRequestOptions();
imageOptions.networkAccessAllowed = true;
phAssetImage.requestContentEditingInputWithOptionsCompletionHandler(imageOptions, (thing) => {
fileMap[existingFileName].path = thing.fullSizeImageURL.toString().replace('file://', '');
await new Promise(resolve => {
phAssetImage.requestContentEditingInputWithOptionsCompletionHandler(imageOptions, (thing) => {
fileMap[existingFileName].path = thing.fullSizeImageURL.toString().replace('file://', '');
resolve();
});
});
}
}

if (this._resolve) {
setTimeout(() => {
const promises = [];
let count = 0;
for (const key in fileMap) {
const item = fileMap[key];
const folder = knownFolders.documents();
const extension = item.filename.split('.').pop();
let filename = renameFileTo ? renameFileTo + '.' + extension : item.filename;
if (iosAssets.count > 1) filename = renameFileTo ? renameFileTo + '-' + count + '.' + extension : item.filename;
fileMap[item.filename].filename = filename;
const fileManager = new NSFileManager();
if (copyToAppFolder) {
const filePath = path.join(folder.path + '/' + copyToAppFolder, filename);
let wasDismissed = false;
const closePromise = new Promise(resolve => {
imagePickerController.dismissViewControllerAnimatedCompletion(true, () => {
wasDismissed = true;
resolve();
if (imagePicker) {
imagePicker._cleanup();
}
imagePicker = null;
// FIX: possible memory issue when picking images many times.
// Not the best solution, but the only one working for now
// https://github.com/NativeScript/nativescript-imagepicker/issues/222
setTimeout(Utils.GC, 200);
});
});
const resolvedFunction = this._resolve;
if (resolvedFunction) {
if (!copyToAppFolder && augmentedAssetsInfo === false) {
if (resolveWhenDismissed && !wasDismissed) {
await closePromise;
}
return resolvedFunction?.(Object.values(fileMap));
}
const promises = [];
let count = 0;
for (const key in fileMap) {
const item = fileMap[key];
const folder = knownFolders.documents();
const extension = item.filename.split('.').pop();
let filename = renameFileTo ? renameFileTo + '.' + extension : item.filename;
if (iosAssets.count > 1) filename = renameFileTo ? renameFileTo + '-' + count + '.' + extension : item.filename;
fileMap[item.filename].filename = filename;
const fileManager = new NSFileManager();
if (copyToAppFolder) {
const filePath = path.join(folder.path + '/' + copyToAppFolder, filename);
promises.push(
getFile('file://' + item.path, filePath)
.then((result) => {
fileMap[item.originalFilename].path = filePath;
fileMap[item.originalFilename].filesize = fileManager.attributesOfItemAtPathError(filePath).fileSize();
if (item.type == 'video') {
return ImageSource.fromAsset(item.asset).then((source) => {
fileMap[item.originalFilename].thumbnail = source;
});
}
})
.catch((error) => {
console.log('Error copying file: ', error);
})
);
} else {
fileMap[item.originalFilename].filesize = fileManager.attributesOfItemAtPathError(fileMap[item.filename].path).fileSize();
if (item.type == 'video') {
promises.push(
getFile('file://' + item.path, filePath)
.then((result) => {
fileMap[item.originalFilename].path = filePath;
fileMap[item.originalFilename].filesize = fileManager.attributesOfItemAtPathError(filePath).fileSize();
if (item.type == 'video') {
return ImageSource.fromAsset(item.asset).then((source) => {
fileMap[item.originalFilename].thumbnail = source;
});
}
})
.catch((error) => {
console.log('Error copying file: ', error);
})
ImageSource.fromAsset(item.asset).then((source) => {
fileMap[item.originalFilename].thumbnail = source;
})
);
} else {
fileMap[item.originalFilename].filesize = fileManager.attributesOfItemAtPathError(fileMap[item.filename].path).fileSize();
if (item.type == 'video') {
promises.push(
ImageSource.fromAsset(item.asset).then((source) => {
fileMap[item.originalFilename].thumbnail = source;
})
);
}
}
count++;
}
count++;
}

Promise.all(promises).then(() => {
const results: ImagePickerSelection[] = [];
for (const key in fileMap) {
results.push(fileMap[key]);
}
this._resolve(results);
});
}, 300);
Promise.all(promises).then(() => {
const results: ImagePickerSelection[] = [];
for (const key in fileMap) {
results.push(fileMap[key]);
}
if (resolveWhenDismissed && !wasDismissed) {
await closePromise;
}
resolvedFunction?.(results);
});
}

imagePickerController.dismissViewControllerAnimatedCompletion(true, () => {
if (imagePicker) {
imagePicker._cleanup();
}
imagePicker = null;
// FIX: possible memory issue when picking images many times.
// Not the best solution, but the only one working for now
// https://github.com/NativeScript/nativescript-imagepicker/issues/222
setTimeout(Utils.GC, 200);
});
}

static ObjCProtocols = [QBImagePickerControllerDelegate];
Expand Down