Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-28250] iOS 14: openPhotoGallery with allowMultiple does not respect mediaTypes and returns LIVEPHOTO when requesting only PHOTO

GitHub Issuen/a
TypeBug
PriorityNone
StatusClosed
ResolutionUnresolved
Affected Version/sRelease 9.2.2
Fix Version/sRelease 9.3.0
ComponentsiOS
Labelsn/a
ReporterEwan Harris
AssigneeVijay Singh
Created2020-11-20T10:50:03.000+0000
Updated2020-11-25T10:34:15.000+0000

Description

Description

When calling openPhotoGallery and passing in mediaTypes: [ Ti.Media.MEDIA_TYPE_PHOTO ], a mediaType of Ti.Media.MEDIA_TYPE_LIVEPHOTO can be returned and the shape of the returned object is also different, containing a livePhotos array, instead of a images array
const win = Ti.UI.createWindow({ layout: 'vertical' });
const singleBtn = Ti.UI.createButton({ title: 'Select single', top: 50 });
singleBtn.addEventListener('click', () => {
    selectImage(false);
});
win.add(singleBtn);
const multiBtn = Ti.UI.createButton({ title: 'Select multiple' });
multiBtn.addEventListener('click', () => {
    selectImage(true);
});
win.add(multiBtn);
win.open();
function selectImage(allowMultiple) {
    Ti.Media.requestPhotoGalleryPermissions((e) => {
        if (!e.success) {
            console.error('failed to get permissions');
            console.error(e);
            return;
        }
        Titanium.Media.openPhotoGallery({
            success: function(e) {
                console.log(e);
            },
            error: function(e) {
                console.error('errored on openPhotoGallery')
                console.error(e);
            },
            mediaTypes: [ Ti.Media.MEDIA_TYPE_PHOTO ],
            allowMultiple
        });
    });
}

Steps to reproduce

1. Add the above code to an existing app.js 2. Ensure you have a NSPhotoLibraryUsageDescription key in your plist like below
<key>NSPhotoLibraryUsageDescription</key>
<string>Can we steal your pics?</string>
3. Build to iOS 4. Tap the Select single button and select a live photo 5. Tap the Select multi button and select a live photo

Actual

In step 4 an object is returned with mediaType of Ti.Media.MEDIA_TYPE_PHOTO In step 5 an object is returned with a livePhotos array and contains an object with a media type of Ti.Media.MEDIA_TYPE_LIVEPHOTO

Expected

A mediaType of Ti.Media.MEDIA_TYPE_LIVEPHOTO should not be returned if only Ti.Media.MEDIA_TYPE_PHOTO was requested

Comments

  1. Ewan Harris 2020-11-20

    It looks like we use a different type of picker dependent on whether allowMultiple is set, so it might be that this is down to a difference there. However it feels strange to me for us to return a live photo when one was not requested?
  2. Vijay Singh 2020-11-23

    PR - https://github.com/appcelerator/titanium_mobile/pull/12289 Test Case -
       var window = Ti.UI.createWindow();
        
       var navWindow = Ti.UI.createNavigationWindow({window: window});
       var tableView = Ti.UI.createTableView(
       {
       	width: Ti.UI.FILL,
       	height: Ti.UI.FILL,
       });
       window.add(tableView);
       var addButton = Ti.UI.createButton(
       {
       	title: "Add",
       	left: "10dp",
       	bottom: "10dp",
       });
       addButton.addEventListener("click", function(e) {
       	var dialog = Ti.UI.createAlertDialog(
       	{
       		message: "Which media type do you want to open?",
       		buttonNames: ["Photo", "Live Photo", "Video", "All"],
       	});
       	dialog.addEventListener("click", function(e) {
       		var mediaTypes;
       		if (e.index === 0) {
       			mediaTypes = [Ti.Media.MEDIA_TYPE_PHOTO];
       		} else if (e.index === 1) {
       			mediaTypes = [Ti.Media.MEDIA_TYPE_LIVEPHOTO];
       		} else if (e.index === 2) {
       			mediaTypes = [Ti.Media.MEDIA_TYPE_VIDEO];
       		} else if (e.index === 3) {
       			mediaTypes = [Ti.Media.MEDIA_TYPE_PHOTO, Ti.Media.MEDIA_TYPE_LIVEPHOTO, Ti.Media.MEDIA_TYPE_VIDEO];
       		} else {
       			Ti.API.info("@@@ Alert was canceled.");
       			return;
       		}
       		dialog.hide();
       		Ti.Media.openPhotoGallery(
       		{
       			allowMultiple: true,
       		    selectionLimit: 10,
       			autohide: true,
       			mediaTypes: mediaTypes,
       			success: function(e) {
       				Ti.API.info("@@@ success() e: " + JSON.stringify(e));
       				var createRowFrom = function(selectionEvent) {
        
       					var fileName = null;
        
       					if (!fileName) {
       						if (selectionEvent.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
       							fileName = "Image";
       						} else if (selectionEvent.mediaType === Ti.Media.MEDIA_TYPE_VIDEO) {
       							fileName = "Video";
       						} else {
       							fileName = "Live Photo";
       						}
       					}
       					var row = Ti.UI.createTableViewRow({ title: fileName });
       					row.addEventListener("click", function(e) {
       						switch (selectionEvent.mediaType) {
       							case Ti.Media.MEDIA_TYPE_PHOTO:
       								var childWindow = Ti.UI.createWindow({backgroundColor: 'white'});
       								childWindow.add(Ti.UI.createImageView(
       								{
       									image: selectionEvent.media,
       									width: Ti.UI.FILL,
       									height: Ti.UI.FILL,
       								}));
       								navWindow.openWindow(childWindow);
       								break;
       							case Ti.Media.MEDIA_TYPE_LIVEPHOTO:
       								var childWindow = Ti.UI.createWindow({backgroundColor: 'white'});
       								var livePhotoView = Ti.UI.iOS.createLivePhotoView({
       									livePhoto: selectionEvent.livePhoto,
       									muted: true,
       									width: 300
       								});
        
       								livePhotoView.addEventListener("start", function(e) {
       									Ti.API.warn("-- Start playback --");
       									Ti.API.warn(e);
       								});
        
       								livePhotoView.addEventListener("stop", function(e) {
       									Ti.API.warn("-- Stop playback --");
       									Ti.API.warn(e);
       								});
       								childWindow.add(livePhotoView);
       								navWindow.openWindow(childWindow);
       								break;
       							case Ti.Media.MEDIA_TYPE_VIDEO:
       								var childWindow = Ti.UI.createWindow({backgroundColor: 'white'});
       								childWindow.add(Ti.Media.createVideoPlayer(
       								{
       									url: selectionEvent.media.nativePath,
       									autoplay: true,
       									mediaControlStyle: Ti.Media.VIDEO_CONTROL_DEFAULT,
       									scalingMode: Ti.Media.VIDEO_SCALING_ASPECT_FIT,
       									width: Ti.UI.FILL,
       									height: Ti.UI.FILL,
       								}));
       								navWindow.openWindow(childWindow);
       								break;
       							default:
       								alert("Unknown media type selected.");
       								break;
       						}
       					});
       					return row;
       				};
       				if (e.images) {
       					for (var index = 0; index < e.images.length; index++) {
       						tableView.appendRow(createRowFrom(e.images[index]));
       					}
       				}
       				if (e.livePhotos) {
       					for (var index = 0; index < e.livePhotos.length; index++) {
       						tableView.appendRow(createRowFrom(e.livePhotos[index]));
       					}
       				}
       				if (e.videos) {
       					for (var index = 0; index < e.videos.length; index++) {
       						tableView.appendRow(createRowFrom(e.videos[index]));
       					}
       				}
       			},
       			cancel: function() {
       				Ti.API.info("@@@ Photo gallery selection canceled.");
       			},
       			error: function() {
       				Ti.API.info("@@@ Photo gallery selection error.");
       			},
       		});
       	});
       	dialog.show();
       });
       window.add(addButton);
       var clearButton = Ti.UI.createButton(
       {
       	title: "Clear",
       	right: "10dp",
       	bottom: "10dp",
       });
       clearButton.addEventListener("click", function(e) {
       	tableView.data = [];
       });
       window.add(clearButton);
       navWindow.open();
       
    In Case of Photo media type selection it should show images only after selection.
  3. Satyam Sekhri 2020-11-24

    FR Passed. Waiting for Jenkins build.

JSON Source