Skip to content
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

Gallery superhero fixes #20

Merged
merged 11 commits into from
May 9, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ logs/*
node_modules/*
.DS_Store
.idea
ssl/*
67 changes: 57 additions & 10 deletions blocks/firefly-gallery/firefly-gallery.css
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
.firefly-gallery {
width: calc(4 * 360px);
margin: 0 auto;
padding: 10px;
}

.card-container {
display: flex;
position: relative;
overflow: hidden;
flex-flow: column wrap;
width: calc(4 * 360px); /* 4 cards per row */
max-height: calc(12 * 360px); /* 12 rows atleast */
gap: 5px 10px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
grid-auto-rows: 10px; /* make the row height small and set the span via js */
grid-gap: 10px;
}

.card {
position: relative;
}

.card > img {
width: 100%;
height: 100%;
}

.card .card-details {
display: none;
}


.card:hover .card-details {
display:flex;
flex-direction: column;
Expand All @@ -33,7 +34,53 @@
bottom: 0;
right: 0;
/* stylelint-disable-next-line color-function-notation */
background-color: rgba(0, 0, 0, 61%);
background: rgba(0, 0, 0, 64.7%);
color: white;
padding: 10px;
}
animation-play-state: running;
opacity: 1;
transition-delay: 0s;
}

.card .card-details .author img {
vertical-align: middle;
padding-right: 10px;
}

.card .card-details .prompt {
overflow: hidden;
line-clamp: 2;
color: #FFF;
font-family: adobe-clean, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 21px;
}

.card .card-details .card-footer {
position: absolute;
bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
}

/*
@media (width >= 450px) {
.card-container {
column-count: 2;
}
}

@media (width >= 600px) {
.card-container {
column-count: 3;
}
}

@media (width >= 900px) {
.card-container {
column-count: 4;
}
} */
194 changes: 138 additions & 56 deletions blocks/firefly-gallery/firefly-gallery.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable quote-props */
/* eslint-disable no-underscore-dangle */
import { getLibs } from '../../scripts/utils.js';

Expand All @@ -8,69 +9,150 @@ const DEFAULT_FORMAT = 'jpg';
const DEFAULT_DIMENSION = 'width';
const DEFAULT_SIZE = '350';
const SHORT_GALLERY_SIZE = '20';
// const FULL_GALLERY_SIZE = '48';
const FULL_GALLERY_SIZE = '48';
const GRID_GAP = 10;
const GRID_ROW_HEIGHT = 10;
let totalImages = 0;
let cursor;
let GETTING_IMAGES = false;

export default async function decorate(block) {
const link = block.querySelector('a') || GALLERY_URL + SHORT_GALLERY_SIZE;
block.innerHTML = '';
const accessToken = window.adobeIMS.getAccessToken();
function resizeGridItem(item) {
const rowSpan = Math.ceil((item.querySelector('img').height + GRID_GAP) / (GRID_ROW_HEIGHT + GRID_GAP));
item.style.gridRowEnd = `span ${rowSpan}`;
}

function resizeAllGridItems(block) {
const cards = block.querySelectorAll('.card');
for (let i = 0; i < cards.length; i += 1) {
resizeGridItem(cards[i]);
}
}

async function getImages(link, next = '') {
let endpoint = link;
// const requestId = (Math.random() + 1).toString(36).substring(5);
const headers = new Headers({
'X-Api-Key': 'alfred-community-hubs',
// 'X-Api-Key': 'clio-playground-web',
Authorization: `Bearer ${accessToken.token}`,
'community_id': 'ff_community',
});
if (cursor !== null && cursor !== '') endpoint += `&cursor=${encodeURIComponent(next)}`;
const resp = await fetch(endpoint, {
headers,
mode: 'cors',
});
const resp = await fetch(link.href, headers);
if (!resp.ok) {
console.error('Failed to fetch images', resp.status, resp.statusText);
// resp = await fetch('/blocks/firefly-gallery/assets-sample.json');
return [];
}
const respJson = await resp.json();
if ((totalImages === 0) && respJson && respJson.total) {
totalImages = respJson.total;
}
if (respJson && respJson._links && respJson._links.next) {
const nextLink = new URL(respJson._links.next.href);
cursor = nextLink.searchParams.get('cursor');
}
if (respJson && respJson._embedded.assets && respJson._embedded.assets.length > 0) {
const images = respJson._embedded.assets;
const cardContainer = createTag('div', { class: 'card-container' });
images.forEach((image) => {
const rendition = image._links.rendition.href;
const authorName = image._embedded.owner.display_name;
const authorImage = image._embedded.owner._links.images[0].href;
const imageUrn = image.urn;
const prompt = image.title;
const imageUrl = rendition.replace('{format}', DEFAULT_FORMAT).replace('{dimension}', DEFAULT_DIMENSION).replace('{size}', DEFAULT_SIZE);
const communityUrl = COMMUNITY_URL + imageUrn;
if (imageUrl && prompt && authorName && authorImage && communityUrl) {
const img = createTag('img', {
src: imageUrl,
alt: prompt,
id: imageUrn,
});
const card = createTag('div', { class: 'card' });
card.append(img);
const cardDetails = createTag('div', { class: 'card-details' });
const author = createTag('div', { class: 'author' });
const authorImg = createTag('img', {
src: authorImage,
alt: authorName,
});
author.append(authorImg);
author.append(authorName);
const cardPrompt = createTag('div', { class: 'prompt' });
cardPrompt.innerHTML = prompt;
const viewLink = createTag('a', {
href: communityUrl,
class: 'viewLink button',
});
viewLink.textContent = 'View';
const likeButton = createTag('button', { class: 'like button' });
likeButton.textContent = 'Like';
const cardFooter = createTag('div', { class: 'card-footer' });
cardFooter.append(likeButton);
cardFooter.append(viewLink);
cardDetails.append(author);
cardDetails.append(cardPrompt);
cardDetails.append(cardFooter);
card.append(cardDetails);
cardContainer.append(card);
}
});
block.append(cardContainer);
return respJson._embedded.assets;
}
return [];
}

async function addCards(cardContainer, images) {
await images.forEach((image) => {
const rendition = image._links.rendition.href;
const maxWidth = image._links.rendition.max_width;
const maxHeight = image._links.rendition.max_height;
const aspectRatio = (maxWidth / maxHeight).toFixed(2);
const height = (DEFAULT_SIZE / aspectRatio).toFixed(2);
const authorName = image._embedded.owner.display_name;
const authorImage = image._embedded.owner._links.images[0].href;
const imageUrn = image.urn;
const prompt = image.title;
const imageUrl = rendition.replace('{format}', DEFAULT_FORMAT).replace('{dimension}', DEFAULT_DIMENSION).replace('{size}', DEFAULT_SIZE);
const communityUrl = COMMUNITY_URL + imageUrn;
if (imageUrl && prompt && authorName && authorImage && communityUrl) {
const img = createTag('img', {
src: imageUrl,
alt: prompt,
id: imageUrn,
width: DEFAULT_SIZE,
height,
});
const card = createTag('div', { class: 'card' });
card.append(img);
const rowSpan = Math.ceil((height + GRID_GAP) / (GRID_ROW_HEIGHT + GRID_GAP));
card.style.gridRowEnd = `span ${rowSpan}`;
const cardDetails = createTag('div', { class: 'card-details' });
const author = createTag('div', { class: 'author' });
const authorImg = createTag('img', {
src: authorImage,
alt: authorName,
});
author.append(authorImg);
author.append(authorName);
const cardPrompt = createTag('div', { class: 'prompt' });
cardPrompt.innerHTML = prompt;
const viewLink = createTag('a', {
href: communityUrl,
class: 'viewLink button',
});
viewLink.textContent = 'View';
const likeButton = createTag('button', { class: 'like button' });
likeButton.textContent = 'Like';
const cardFooter = createTag('div', { class: 'card-footer' });
cardFooter.append(likeButton);
cardFooter.append(viewLink);
cardDetails.append(author);
cardDetails.append(cardPrompt);
cardDetails.append(cardFooter);
card.append(cardDetails);
cardContainer.append(card);
}
});
GETTING_IMAGES = false;
}

export default async function decorate(block) {
let size = SHORT_GALLERY_SIZE;
let IS_INFINITE_SCROLL = false;
if (window.location.pathname.includes('/community') || window.location.pathname.includes('/gallery')) {
IS_INFINITE_SCROLL = true;
size = FULL_GALLERY_SIZE;
}
const link = block.querySelector('a')?.href || `${GALLERY_URL}${size}`;
block.innerHTML = '';
const images = await getImages(link);
const cardContainer = createTag('div', { class: 'card-container' });
await addCards(cardContainer, images);
block.append(cardContainer);
resizeAllGridItems(block);
window.addEventListener('resize', resizeAllGridItems(block));
if (IS_INFINITE_SCROLL) {
// if last card is visible, fetch more images
setTimeout(() => {
const intersectionContainer = block.querySelector('.card-container .card:last-child');
const observer = new IntersectionObserver(async (entries) => {
if (entries[0].isIntersecting) {
if (GETTING_IMAGES) return;
GETTING_IMAGES = true;
observer.unobserve(intersectionContainer);
const containerEl = block.querySelector('.card-container');
if (containerEl.children.length < totalImages) {
// fetch more images if there are more images to fetch
const nextImages = await getImages(link, cursor);
if (nextImages.length === 0) {
observer.unobserve(intersectionContainer);
return;
}
await addCards(cardContainer, nextImages);
const newIntersectionContainer = block.querySelector('.card-container .card:last-child');
observer.observe(newIntersectionContainer);
} else {
observer.unobserve(intersectionContainer);
}
}
}, { threshold: 1 });
observer.observe(intersectionContainer);
}, 2000);
}
}
3 changes: 3 additions & 0 deletions blocks/superhero/superhero.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
display: grid;
justify-content: center;
align-items: center;
margin: unset;
max-width: unset;
min-width: 100vw;
}

.superhero .content-container {
Expand Down
8 changes: 3 additions & 5 deletions blocks/superhero/superhero.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-underscore-dangle */
import { getLibs, createOptimizedFireflyPicture } from '../../scripts/utils.js';

const { createTag, loadIms } = await import(`${getLibs()}/utils/utils.js`);
const { createTag } = await import(`${getLibs()}/utils/utils.js`);
const ASSET_BASE_URL = 'https://community-hubs.adobe.io/api/v2/ff_community/assets/';
const TEXT_TO_IMAGE_BASE_URL = 'https://firefly.adobe.com/community/view/texttoimage?id=';
const DEFAULT_FORMAT = 'jpg';
Expand Down Expand Up @@ -75,8 +75,6 @@ export default async function decorate(block) {
const assetIds = block.querySelectorAll('p');
block.innerHTML = '';
const imageContainer = createTag('div', { class: 'image-container' });
// if user is not signed in, load IMS
if (!window.adobeIMS?.isSignedInUser()) loadIms();
assetIds.forEach(async (assetId, i) => {
const imageId = assetId.textContent.trim();
if (!imageId || imageId === '') return;
Expand All @@ -85,9 +83,9 @@ export default async function decorate(block) {
const imageDetails = await resp.json();
const imageHref = imageDetails._embedded.artwork._links.rendition.href;
const imageUrl = imageHref.replace('{format}', DEFAULT_FORMAT).replace('{dimension}', DEFAULT_DIMENSION);
const userLocale = window.adobeIMS?.adobeIdData?.locale.replace('_', '-') || navigator.language;
const userLocale = window.adobeIMS?.adobeIdData?.locale.replace('_', '-') || navigator.language || 'en-US';
const prompt = imageDetails.custom.input['firefly#prompts'][userLocale];
const picture = createOptimizedFireflyPicture(imageUrl, prompt, i === 0, i === 0, i === 0 ? 'high' : '');
const picture = createOptimizedFireflyPicture(imageUrl, prompt, i === 0, i === 0, 'high');
imageContainer.append(picture);
}
});
Expand Down
1 change: 1 addition & 0 deletions scripts/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const miloLibs = setLibs(LIBS);
}());

async function loadPage() {
// eslint-disable-next-line no-unused-vars
const { loadArea, setConfig, loadMartech } = await import(`${miloLibs}/utils/utils.js`);
// eslint-disable-next-line no-unused-vars
const config = setConfig({ ...CONFIG, miloLibs });
Expand Down
1 change: 1 addition & 0 deletions scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function createOptimizedFireflyPicture(
eager = false,
fetchpriority = '',
breakpoints = [
{ media: '(min-width: 2000px)', width: '3000' },
{ media: '(min-width: 1200px)', width: '2000' },
{ media: '(min-width: 900px)', width: '1200' },
{ media: '(min-width: 600px)', width: '900' },
Expand Down
5 changes: 5 additions & 0 deletions styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@
}

@media (width >= 600px) {
main > div > div {
max-width: 1500px;
margin: 0 auto;
}

.feds-nav-wrapper {
justify-content: center;
}
Expand Down