Skip to content

Commit 09442b2

Browse files
authored
Merge pull request #295 from neural-loop/social-sharing
Social sharing
2 parents ae27b9f + 75b6f34 commit 09442b2

File tree

11 files changed

+841
-150
lines changed

11 files changed

+841
-150
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Deploy Hugo site to Pages
22

33
on:
44
push:
5-
branches: ["main", "supporters"]
5+
branches: ["main", "social-sharing"]
66

77
permissions:
88
contents: read
@@ -57,7 +57,7 @@ jobs:
5757
content/**/*-og-*.jpg
5858
static/images/og-image-*.jpg
5959
tmp/og-cache-manifest.json
60-
key: ${{ runner.os }}-og-images-${{ hashFiles('**/content/**/index.md', '**/content/**/_index.md', 'assets/og-template/template.html', 'assets/images/ONM-logo.png') }}
60+
key: ${{ runner.os }}-og-images-${{ hashFiles('**/content/**/index.md', '**/content/**/_index.md', 'assets/og-template/template.html', 'assets/og-template/event-template.html', 'assets/images/ONM-logo.png', 'scripts/collectOgData.js', 'scripts/generateOgImages.js') }}
6161
restore-keys: |
6262
${{ runner.os }}-og-images-
6363

assets/js/main.js

Lines changed: 123 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
if (navCloseBtn) {
2222
navCloseBtn.addEventListener("click", toggleNav);
2323
}
24-
24+
2525
// Close on Escape key
2626
document.addEventListener('keydown', (e) => {
2727
if (e.key === 'Escape' && body.classList.contains('is-mobile-nav-open')) {
@@ -44,75 +44,75 @@
4444

4545
let bubblePool = [];
4646
for (let i = 0; i < MAX_BUBBLES; i++) {
47-
let bubble = document.createElement('div');
48-
bubble.className = 'contribution-bubble';
49-
bubble.dataset.busy = 'false';
50-
bubbleContainer.appendChild(bubble);
51-
bubblePool.push(bubble);
47+
let bubble = document.createElement('div');
48+
bubble.className = 'contribution-bubble';
49+
bubble.dataset.busy = 'false';
50+
bubbleContainer.appendChild(bubble);
51+
bubblePool.push(bubble);
5252
}
53-
53+
5454
let activeBubbles = new Map();
5555

5656
const updateBubblePositions = () => {
5757
activeBubbles.forEach((bubble, partner) => {
5858
const partnerRect = partner.getBoundingClientRect();
5959
const containerRect = bubbleContainer.getBoundingClientRect();
60-
60+
6161
const left = partnerRect.left - containerRect.left + (partnerRect.width / 2) - (bubble.offsetWidth / 2);
6262
const top = partnerRect.top - containerRect.top - bubble.offsetHeight - 10;
6363

6464
bubble.style.transform = `translate(${left}px, ${top}px)`;
6565
});
6666
requestAnimationFrame(updateBubblePositions);
6767
};
68-
68+
6969
requestAnimationFrame(updateBubblePositions);
7070

7171
const showBubble = (partner) => {
72-
const bubble = bubblePool.find(b => b.dataset.busy === 'false');
73-
if (!bubble) return;
74-
75-
bubble.dataset.busy = 'true';
76-
activeBubbles.set(partner, bubble);
77-
78-
bubble.innerHTML = partner.dataset.contributions;
79-
bubble.classList.add('visible');
80-
81-
setTimeout(() => {
82-
hideBubble(partner, bubble);
83-
}, BUBBLE_LIFETIME);
72+
const bubble = bubblePool.find(b => b.dataset.busy === 'false');
73+
if (!bubble) return;
74+
75+
bubble.dataset.busy = 'true';
76+
activeBubbles.set(partner, bubble);
77+
78+
bubble.innerHTML = partner.dataset.contributions;
79+
bubble.classList.add('visible');
80+
81+
setTimeout(() => {
82+
hideBubble(partner, bubble);
83+
}, BUBBLE_LIFETIME);
8484
};
8585

8686
const hideBubble = (partner, bubble) => {
87-
bubble.classList.remove('visible');
88-
activeBubbles.delete(partner);
89-
90-
setTimeout(() => {
91-
bubble.dataset.busy = 'false';
92-
}, 300);
87+
bubble.classList.remove('visible');
88+
activeBubbles.delete(partner);
89+
90+
setTimeout(() => {
91+
bubble.dataset.busy = 'false';
92+
}, 300);
9393
};
9494

9595
setInterval(() => {
96-
if (activeBubbles.size >= MAX_BUBBLES) return;
97-
98-
const rect = section.getBoundingClientRect();
99-
const isInView = rect.top < window.innerHeight && rect.bottom >= 0;
100-
101-
if (isInView) {
102-
const availablePartners = partnersWithContributions.filter(p => {
103-
if (activeBubbles.has(p)) return false;
104-
const r = p.getBoundingClientRect();
105-
return r.left > 50 && r.right < window.innerWidth - 50;
106-
});
107-
108-
if (availablePartners.length > 0) {
109-
const randomIndex = Math.floor(Math.random() * availablePartners.length);
110-
showBubble(availablePartners[randomIndex]);
111-
}
96+
if (activeBubbles.size >= MAX_BUBBLES) return;
97+
98+
const rect = section.getBoundingClientRect();
99+
const isInView = rect.top < window.innerHeight && rect.bottom >= 0;
100+
101+
if (isInView) {
102+
const availablePartners = partnersWithContributions.filter(p => {
103+
if (activeBubbles.has(p)) return false;
104+
const r = p.getBoundingClientRect();
105+
return r.left > 50 && r.right < window.innerWidth - 50;
106+
});
107+
108+
if (availablePartners.length > 0) {
109+
const randomIndex = Math.floor(Math.random() * availablePartners.length);
110+
showBubble(availablePartners[randomIndex]);
112111
}
113-
}, BUBBLE_INTERVAL);
112+
}
113+
}, BUBBLE_INTERVAL);
114114
};
115-
115+
116116
// --- Copy Code Block ---
117117
const initCopyCodeButtons = () => {
118118
const codeBlocks = document.querySelectorAll('.code-block-wrapper');
@@ -131,7 +131,7 @@
131131
setTimeout(() => {
132132
button.classList.remove('copied');
133133
button.querySelector('.copy-text').classList.remove('hidden');
134-
button.querySelector('.copied-text').classList.add('hidden');
134+
button.querySelector('.copied-text').add('hidden');
135135
}, 2000);
136136
}).catch(err => {
137137
console.error('Failed to copy text: ', err);
@@ -142,18 +142,90 @@
142142
});
143143
};
144144

145+
// --- OG Image Assets Modal ---
146+
const initOgImageModal = () => {
147+
const modal = document.getElementById('og-image-modal');
148+
const modalContent = document.getElementById('og-modal-content');
149+
const closeBtn = document.getElementById('og-modal-close');
150+
if (!modal || !modalContent || !closeBtn) return;
151+
152+
const showModal = () => {
153+
modal.classList.remove('hidden');
154+
modal.classList.add('flex');
155+
};
156+
157+
const hideModal = () => {
158+
modal.classList.add('hidden');
159+
modal.classList.remove('flex');
160+
};
161+
162+
closeBtn.addEventListener('click', hideModal);
163+
modal.addEventListener('click', (e) => {
164+
if (e.target === modal) {
165+
hideModal();
166+
}
167+
});
168+
document.addEventListener('keydown', (e) => {
169+
if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
170+
hideModal();
171+
}
172+
});
173+
174+
window.openOgModal = (imageUrls) => {
175+
modalContent.innerHTML = ''; // Clear previous content
176+
177+
if (!imageUrls || imageUrls.length === 0) {
178+
modalContent.innerHTML = '<p class="text-center col-span-full">No social media assets found for this page.</p>';
179+
} else {
180+
imageUrls.forEach(img => {
181+
const cardHTML = `
182+
<div class="og-image-card text-center">
183+
<h4 class="font-semibold mb-2 text-sm">${img.label}</h4>
184+
<a href="${img.url}" download="${img.filename}" title="Download this image">
185+
<img src="${img.url}" alt="OG Image Preview for ${img.label}" class="w-full rounded-md border border-border dark:border-darkmode-border shadow-md hover:shadow-lg transition-shadow">
186+
</a>
187+
<div class="mt-3">
188+
<a href="${img.url}" download="${img.filename}" class="btn btn-sm btn-new-primary">
189+
Download
190+
</a>
191+
</div>
192+
</div>
193+
`;
194+
modalContent.insertAdjacentHTML('beforeend', cardHTML);
195+
});
196+
}
197+
showModal();
198+
};
199+
200+
document.querySelectorAll('[data-og-assets]').forEach(trigger => {
201+
trigger.addEventListener('click', (e) => {
202+
e.preventDefault();
203+
const assetsJson = trigger.dataset.ogAssets;
204+
try {
205+
const assets = JSON.parse(assetsJson);
206+
window.openOgModal(assets);
207+
} catch (error) {
208+
console.error("Could not parse OG assets JSON:", error);
209+
window.openOgModal([]);
210+
}
211+
});
212+
});
213+
};
214+
145215
// Wait for the DOM to be fully loaded to initialize
146216
if (document.readyState === 'loading') {
147217
document.addEventListener('DOMContentLoaded', () => {
148-
initCopyCodeButtons();
149-
if (window.innerWidth > 768) { // Only run on larger screens
150-
initContributionBubbles();
151-
}
218+
initCopyCodeButtons();
219+
initOgImageModal();
220+
if (window.innerWidth > 768) { // Only run on larger screens
221+
initContributionBubbles();
222+
}
152223
});
153224
} else {
154225
initCopyCodeButtons();
226+
initOgImageModal();
155227
if (window.innerWidth > 768) { // Only run on larger screens
156-
initContributionBubbles();
228+
initContributionBubbles();
157229
}
158230
}
159231

0 commit comments

Comments
 (0)