feat(media): Embed Google Photo Picker via Popup Flow
- Revert 'Unified Embedded Picker' which caused 403 errors due to iframe restrictions on the Google Photos Picker. - Implement a 'Popup Window' flow for Google Photos selections, keeping the Media Manager active. - Restore 'Classic' Embedded Picker for Google Drive (DocsView) as it is compatible with iframes. - Update ppsscript.json with drive.photos.readonly scope for correct permissions. - Update Media Manager UI to separate Drive and Photos buttons.
This commit is contained in:
@ -404,6 +404,8 @@
|
||||
<div id="photos-session-status" style="font-size:11px; color:#64748b; text-align:center;">Initializing...</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card" style="padding-bottom: 0;">
|
||||
<div class="header" style="margin-bottom:8px; display:flex; justify-content:space-between; align-items:center;">
|
||||
<div style="display:flex; align-items:baseline; gap:12px;">
|
||||
@ -698,6 +700,44 @@
|
||||
this.saveBtn.innerText = enable ? "Save Changes" : "No Changes";
|
||||
};
|
||||
|
||||
UI.prototype.showPhotoSession = function (url) {
|
||||
var uiEl = document.getElementById('photos-session-ui');
|
||||
var link = document.getElementById('photos-session-link');
|
||||
var status = document.getElementById('photos-session-status');
|
||||
|
||||
uiEl.style.display = 'block';
|
||||
link.href = url;
|
||||
// We also open it automatically in a popup
|
||||
const width = 1200;
|
||||
const height = 800;
|
||||
const left = (screen.width - width) / 2;
|
||||
const top = (screen.height - height) / 2;
|
||||
|
||||
// Attempt popup
|
||||
const popup = window.open(url, 'googlePhotos', `width=${width},height=${height},top=${top},left=${left}`);
|
||||
|
||||
if (popup) {
|
||||
link.innerText = "Re-open Popup ↗";
|
||||
link.onclick = function (e) {
|
||||
e.preventDefault();
|
||||
window.open(url, 'googlePhotos', `width=${width},height=${height},top=${top},left=${left}`);
|
||||
}
|
||||
} else {
|
||||
link.innerText = "Open Google Photos ↗";
|
||||
link.onclick = null; // Default href behavior
|
||||
}
|
||||
|
||||
status.innerText = "Waiting for selection in popup...";
|
||||
};
|
||||
|
||||
UI.prototype.closePhotoSession = function () {
|
||||
document.getElementById('photos-session-ui').style.display = 'none';
|
||||
};
|
||||
|
||||
UI.prototype.updatePhotoStatus = function (msg) {
|
||||
document.getElementById('photos-session-status').innerText = msg;
|
||||
};
|
||||
|
||||
UI.prototype.render = function (items) {
|
||||
this.grid.innerHTML = '';
|
||||
var _this = this; // Capture 'this' for callbacks
|
||||
@ -900,25 +940,6 @@
|
||||
document.getElementById('details-modal').style.display = 'none';
|
||||
};
|
||||
|
||||
UI.prototype.showPhotoSession = function (url) {
|
||||
var uiEl = document.getElementById('photos-session-ui');
|
||||
var link = document.getElementById('photos-session-link');
|
||||
var status = document.getElementById('photos-session-status');
|
||||
|
||||
uiEl.style.display = 'block';
|
||||
link.href = url;
|
||||
link.style.display = 'block';
|
||||
status.innerText = "Waiting for selection...";
|
||||
};
|
||||
|
||||
UI.prototype.closePhotoSession = function () {
|
||||
document.getElementById('photos-session-ui').style.display = 'none';
|
||||
};
|
||||
|
||||
UI.prototype.updatePhotoStatus = function (msg) {
|
||||
document.getElementById('photos-session-status').innerText = msg;
|
||||
};
|
||||
|
||||
var ui = new UI();
|
||||
window.ui = ui;
|
||||
|
||||
@ -1104,6 +1125,7 @@
|
||||
});
|
||||
},
|
||||
|
||||
// --- Picker ---
|
||||
// --- Picker ---
|
||||
openPicker() {
|
||||
if (!pickerApiLoaded) return alert("API Loading...");
|
||||
@ -1116,7 +1138,7 @@
|
||||
.importFromPicker(state.sku, fileId, mime, name, url);
|
||||
},
|
||||
|
||||
// --- Photos ---
|
||||
// --- Photos (Popup Flow) ---
|
||||
startPhotoSession() {
|
||||
ui.updatePhotoStatus("Starting session...");
|
||||
google.script.run
|
||||
@ -1165,7 +1187,11 @@
|
||||
});
|
||||
},
|
||||
|
||||
// --- Legacy Photos Session (Removed in favor of Embedded Picker) ---
|
||||
// startPhotoSession() { ... }
|
||||
|
||||
// --- Compatibility / Matching Logic ---
|
||||
|
||||
matches: [],
|
||||
currentMatchIndex: 0,
|
||||
hasRunMatching: false,
|
||||
@ -1319,18 +1345,20 @@
|
||||
.setMimeTypes("image/png,image/jpeg,image/jpg,video/mp4")
|
||||
.setIncludeFolders(true)
|
||||
.setSelectFolderEnabled(false);
|
||||
const photosView = new google.picker.PhotosView();
|
||||
|
||||
new google.picker.PickerBuilder()
|
||||
.addView(view)
|
||||
.addView(photosView)
|
||||
const builder = new google.picker.PickerBuilder();
|
||||
|
||||
builder.addView(view)
|
||||
.setOAuthToken(config.token)
|
||||
.setDeveloperKey(config.apiKey)
|
||||
.setOrigin(window.location.protocol + '//' + window.location.host)
|
||||
.setCallback(data => {
|
||||
if (data.action == google.picker.Action.PICKED) {
|
||||
const doc = data.docs[0];
|
||||
const url = (doc.thumbnails && doc.thumbnails.length > 0) ? doc.thumbnails[doc.thumbnails.length - 1].url : null;
|
||||
controller.importFromPicker(doc.id, doc.mimeType, doc.name, url);
|
||||
const isDrive = doc.serviceId === 'docs';
|
||||
|
||||
// Drive File (Always, since we removed Photos view)
|
||||
controller.importFromPicker(doc.id, doc.mimeType, doc.name, null);
|
||||
}
|
||||
})
|
||||
.build()
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"https://www.googleapis.com/auth/script.scriptapp",
|
||||
"https://www.googleapis.com/auth/drive",
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
"https://www.googleapis.com/auth/photospicker.mediaitems.readonly"
|
||||
"https://www.googleapis.com/auth/photospicker.mediaitems.readonly",
|
||||
"https://www.googleapis.com/auth/drive.photos.readonly"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user