Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 1 addition & 143 deletions frontend/js/book-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,146 +209,4 @@ const BookPreview = (() => {
el.querySelector('#download-card-btn').addEventListener('click', () => {
const card = document.getElementById('book-card');
html2canvas(card).then(canvas => {
const link = document.createElement('a');
link.download = 'book-card.png';
link.href = canvas.toDataURL('image/png');
link.click();
});
});

return el;
}

// ── State helpers ──────────────────────────────────────────────────────────

function _setLoading() {
const loading = document.getElementById('preview-loading');
const container = document.getElementById('preview-viewer-container');
const fallback = document.getElementById('preview-fallback');
if (loading) loading.style.display = 'flex';
if (container) { container.style.display = 'none'; container.innerHTML = ''; }
if (fallback) fallback.style.display = 'none';
}

function _showViewer() {
const loading = document.getElementById('preview-loading');
const container = document.getElementById('preview-viewer-container');
const fallback = document.getElementById('preview-fallback');
if (loading) loading.style.display = 'none';
if (fallback) fallback.style.display = 'none';
if (container) container.style.display = 'block';
}

function _showFallback(id, msg) {
const loading = document.getElementById('preview-loading');
const container = document.getElementById('preview-viewer-container');
const fallback = document.getElementById('preview-fallback');
const msgEl = document.getElementById('preview-fallback-msg');
const link = document.getElementById('preview-external-link');
if (loading) loading.style.display = 'none';
if (container) container.style.display = 'none';
if (msgEl && msg) msgEl.textContent = msg;
if (link) link.href = `https://books.google.com/books?id=${encodeURIComponent(id)}`;
if (fallback) fallback.style.display = 'flex';
}

function _close() {
const modal = document.getElementById('book-preview-modal');
const container = document.getElementById('preview-viewer-container');
if (container) container.innerHTML = ''; // destroy iframe
if (modal && modal.hasAttribute('open')) modal.close();
document.body.style.overflow = '';
}

// ── Viewer ─────────────────────────────────────────────────────────────────

function _renderViewer(id) {
const container = document.getElementById('preview-viewer-container');
if (!container) { _showFallback(id, 'Viewer container missing.'); return; }

if (!window.google?.books?.DefaultViewer) {
_showFallback(id, 'The preview viewer could not be initialised.');
return;
}

// Hard timeout — show fallback if callbacks never fire
const timeout = setTimeout(() => {
_showFallback(id, 'The preview took too long to load. You can view it on Google Books instead.');
}, 10000);

const viewer = new window.google.books.DefaultViewer(container);

viewer.load(
id,
// notFoundCallback — no embeddable preview for this book
() => {
clearTimeout(timeout);
_showFallback(id, "This book doesn't have an embeddable preview. You can view it on Google Books instead.");
},
// successCallback — viewer rendered successfully
() => {
clearTimeout(timeout);
_showViewer();
}
);
}

// ── Public API ─────────────────────────────────────────────────────────────

/**
* Open the in-app preview modal.
* @param {string} googleBooksId
* @param {string} [title]
* @param {string} [author]
* @param {number} [rating]
* @param {string} [genre]
*/

async function open(googleBooksId, title, author, rating, genre) {
if (!_isValidId(googleBooksId)) {
console.warn('[BookPreview] Invalid Google Books ID:', googleBooksId);
return;
}

const modal = _getOrCreateModal();

// Set title
const titleEl = document.getElementById('preview-modal-title');
if (titleEl) titleEl.textContent = title || 'Book Preview';

// populate the book card with real data after modal exists ──
populateBookCard(title, author, rating, genre);

_setLoading();
modal.showModal();
document.body.style.overflow = 'hidden';

try {
await _loadAPI();
_renderViewer(googleBooksId);
} catch (err) {
console.error('[BookPreview] Error:', err);
_showFallback(
googleBooksId,
'Something went wrong loading the preview. You can view this book on Google Books instead.'
);
}
}

// populate hidden book card with current book's data
function populateBookCard(title, author, rating, genre) {
const titleEl = document.getElementById('card-title');
const authorEl = document.getElementById('card-author');
const ratingEl = document.getElementById('card-rating');
const genreEl = document.getElementById('card-genre');
if (titleEl) titleEl.textContent = title || '';
if (authorEl) authorEl.textContent = author ? 'by ' + author : '';
if (ratingEl) ratingEl.textContent = rating ? '★'.repeat(rating) + '☆'.repeat(5 - rating) : '';
if (genreEl) genreEl.textContent = genre || '';
}

return { open, populateBookCard };

})();

window.BookPreview = BookPreview;
.catch(err => console.error(err))
23 changes: 1 addition & 22 deletions sw.js/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,4 @@ const ASSETS_TO_CACHE = [
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
console.log('Caching essential UI sanctuary assets...');
return cache.addAll(ASSETS_TO_CACHE);
})
);
});

// Fetch Event: Cache-First strategy for core layout files
self.addEventListener('fetch', (event) => {
// Only intercept local GET requests
if (event.request.method !== 'GET' || !event.request.url.startsWith(self.location.origin)) {
return;
}

event.respondWith(
caches.match(event.request).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse; // Return local cache copy
}
return fetch(event.request); // Fallback to network
})
);
});
.catch(err => console.error(err))