-
Notifications
You must be signed in to change notification settings - Fork 5
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
Issue 48 - Use high resolution assets when possible #52
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,6 +63,13 @@ | |
// TODO: change this to Asset Link IMS client ID | ||
const IMS_CLIENT_ID = 'p66302-franklin'; | ||
const ASSET_SELECTOR_ID = 'asset-selector'; | ||
const CLIPBOARD_SUPPORTED_BINARY_MIMETYPES = [ | ||
'image/png', | ||
]; | ||
const SUPPORTED_RENDITIONS_FORMATS = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renditions mimetypes that we can use in Franklin documents (needed for filtering). |
||
'image/png', | ||
'image/jpeg', | ||
]; | ||
|
||
let imsInstance = null; | ||
let imsEnvironment = IMS_ENV_PROD; | ||
|
@@ -200,9 +207,9 @@ | |
// TODO: the clipboard API only supports using PNGs as the blob, so | ||
// only using PNG renditions. Will be fixed to allow altnernate | ||
// formats in a follow-up ticket | ||
.filter((rendition) => rendition.type === 'image/png') | ||
.forEach((rendition) => { | ||
if ((!maxRendition || maxRendition.width < rendition.width)) { | ||
if (SUPPORTED_RENDITIONS_FORMATS.includes(rendition.type) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only look at mimetypes we can convert to use with the clipboard APIs... |
||
&& (!maxRendition || maxRendition.width < rendition.width)) { | ||
maxRendition = rendition; | ||
} | ||
}); | ||
|
@@ -227,6 +234,40 @@ | |
return navigator.clipboard.write(data); | ||
} | ||
|
||
async function loadImageIntoHtmlElement(url) { | ||
return new Promise((resolve, reject) => { | ||
const img = new Image(); | ||
/* | ||
crossorigin needs to be anonymous to allow the future canvas export, | ||
otherwise the canvas will be considered tainted and the export will fail | ||
*/ | ||
img.setAttribute('crossorigin', 'anonymous'); | ||
img.addEventListener('load', () => resolve(img)); | ||
img.addEventListener('error', (err) => reject(err)); | ||
img.src = url; | ||
}); | ||
} | ||
|
||
/** | ||
* Convert an image using an URL to a another image format | ||
* @param {*} assetPublicUrl Public asset URL | ||
* @param {*} targetMimeType Target mimetype (target format) | ||
* @returns A conversion promise resolving to a blob of the target mimetype | ||
*/ | ||
async function convertImage(assetPublicUrl, targetMimeType='image/png', asset) { | ||
Check failure on line 257 in blocks/aem-asset-selector/aem-asset-selector-util.js GitHub Actions / build
|
||
const imageElement = await loadImageIntoHtmlElement(assetPublicUrl); | ||
|
||
return new Promise(resolve => { | ||
const canvas = document.createElement('canvas'); | ||
canvas.width = asset['tiff:imageWidth']; | ||
canvas.height = asset['tiff:imageLength']; | ||
|
||
const context = canvas.getContext('2d'); | ||
context.drawImage(imageElement, 0, 0); | ||
canvas.toBlob(resolve, targetMimeType); | ||
}); | ||
} | ||
|
||
/** | ||
* Uses the navigator global object to write a clipboard item to the clipboard. | ||
* The clipboard item's content will be a Blob containing the image binary from | ||
|
@@ -235,22 +276,31 @@ | |
* @param {string} mimeType Content type of the image being retrieved. | ||
* @returns {Promise} Resolves when the item has been written to the clipboard. | ||
*/ | ||
async function copyToClipboardWithBinary(assetPublicUrl, mimeType) { | ||
const binary = await fetch(assetPublicUrl); | ||
async function copyToClipboardWithBinary(assetPublicUrl, mimeType, asset) { | ||
let clipboardOptions = {}; | ||
|
||
if (!binary || !binary.ok) { | ||
throw new Error(`Unexpected status code ${binary.status} retrieving asset binary`); | ||
} | ||
if (!CLIPBOARD_SUPPORTED_BINARY_MIMETYPES.includes(mimeType)) { | ||
const clipboardTargetMimetype = 'image/png'; | ||
const copiedBlob = await convertImage(assetPublicUrl, clipboardTargetMimetype, asset); | ||
clipboardOptions[clipboardTargetMimetype] = copiedBlob; | ||
} else { | ||
const binary = await fetch(assetPublicUrl); | ||
|
||
if (!binary || !binary.ok) { | ||
throw new Error(`Unexpected status code ${binary.status} retrieving asset binary`); | ||
} | ||
|
||
const blob = await binary.blob(); | ||
if (!blob) { | ||
throw new Error('No blob provided in asset response'); | ||
const blob = await binary.blob(); | ||
if (!blob) { | ||
throw new Error('No blob provided in asset response'); | ||
} | ||
clipboardOptions[mimeType] = blob; | ||
} | ||
const clipboardOptions = {}; | ||
clipboardOptions[mimeType] = blob; | ||
|
||
const data = [ | ||
new ClipboardItem(clipboardOptions), | ||
]; | ||
|
||
return navigator.clipboard.write(data); | ||
} | ||
|
||
|
@@ -325,9 +375,9 @@ | |
logMessage('Rendition download JSON not provided'); | ||
return false; | ||
} | ||
await copyToClipboardWithBinary(downloadJson.href, downloadJson.type); | ||
await copyToClipboardWithBinary(downloadJson.href, downloadJson.type, asset); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Asset info is needed to give the canvas the proper size |
||
} catch (e) { | ||
logMessage('error copying asset to clipboard', e); | ||
logMessage('Error copying asset using R-API to clipboard', e); | ||
return false; | ||
} | ||
|
||
|
@@ -352,7 +402,7 @@ | |
function handleAssetSelection(selection, cfg) { | ||
if (cfg) { | ||
if (selection.length && cfg.onAssetSelected) { | ||
if (selection.length > 0) { | ||
if (selection.length > 1) { | ||
logMessage('Multiple items received in selection, but only the first will be used'); | ||
} | ||
cfg.onAssetSelected(selection[0]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mimetypes supported "natively" by the clipboard API (from the browser)