diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dcdf46..cdb821d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,14 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi --- +## [1.52.0] — 2026-09-22 + +### Changed +- **Magazine: the article-thumbnail grid is gone; "Thumbnails" now means the page-by-page view.** An article is a poor thumbnail unit — it can span many pages or share one with others — so the toggle is back to two states: List (articles, for the title/author/duration/status detail that only makes sense per article) and the page-complete thumbnail grid added earlier. "All pages" is also now the default view on first open. +- **Magazine: the page grid's column count is adjustable, 1-12**, via a slider next to the view toggle (shown only in that view) — a "zoom" between an overview of the whole issue and a close look at a few pages, remembered per browser. + +--- + ## [1.51.0] — 2026-09-22 ### Fixed @@ -4401,7 +4409,8 @@ Initial feature-complete release. --- -[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.51.0...HEAD +[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.52.0...HEAD +[1.52.0]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.51.0...v1.52.0 [1.51.0]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.50.0...v1.51.0 [1.50.0]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.49.0...v1.50.0 [1.49.0]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.48.2...v1.49.0 diff --git a/VERSION b/VERSION index ba0a719..a63cb35 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.51.0 +1.52.0 diff --git a/static/index.html b/static/index.html index 809234c..7eb8f00 100644 --- a/static/index.html +++ b/static/index.html @@ -10,7 +10,7 @@ - + @@ -27,12 +27,12 @@ - - - - - - + + + + + + @@ -403,7 +403,7 @@ window.toggleNavTree = function(treeId, chevronId) { - + diff --git a/static/js/magazine.js b/static/js/magazine.js index a9ebb3f..0a9f4b1 100644 --- a/static/js/magazine.js +++ b/static/js/magazine.js @@ -22,9 +22,10 @@ const state = { sentences: [], // [{ text, blockId, page, bbox }] images: [], // current article's figures, in reading order view: 'library', // library | contents | review | read - contentsView: 'list', // list | grid — how the article list itself is shown + contentsView: 'pages', // list | pages — how the article list itself is shown contentsSelectMode: false, // batch-select articles for bulk approve/reject contentsSelected: new Set(), + pagesCols: 8, // "All pages" grid column count, user-adjustable 1-12 playlistCurrent: null, // article id of the MP3 playlist's current track pane: 'reflow', // reflow | pdf playing: false, @@ -724,17 +725,21 @@ function renderContents() { bySection.get(key).push(a); }); - const grid = state.contentsView === 'grid'; const toggleBtn = $('mag-contents-view-toggle'); if (toggleBtn) { - const nextLabel = { list: 'Thumbnails', grid: 'All pages', pages: 'List' }[state.contentsView]; - const nextIcon = { list: 'mdi-view-grid-outline', grid: 'mdi-view-module-outline', pages: 'mdi-view-list-outline' }[state.contentsView]; + const nextLabel = { list: 'Thumbnails', pages: 'List' }[state.contentsView]; + const nextIcon = { list: 'mdi-view-grid-outline', pages: 'mdi-view-list-outline' }[state.contentsView]; toggleBtn.innerHTML = ' ' + nextLabel; toggleBtn.setAttribute('aria-pressed', String(state.contentsView !== 'list')); - toggleBtn.title = 'Currently: ' + { list: 'list', grid: 'thumbnails (by article)', pages: 'all pages' }[state.contentsView] + + toggleBtn.title = 'Currently: ' + { list: 'article list', pages: 'page thumbnails' }[state.contentsView] + '. Click to switch to ' + nextLabel.toLowerCase() + '.'; } + const colsControl = $('mag-cols-control'); + if (colsControl) colsControl.hidden = state.contentsView !== 'pages'; if (state.contentsView === 'pages') { + const range = $('mag-cols-range'), valueEl = $('mag-cols-value'); + if (range) range.value = state.pagesCols; + if (valueEl) valueEl.textContent = String(state.pagesCols); renderPagesView(host); renderContentsBulkBar(); magUpdateAudioZipLink(); @@ -768,53 +773,37 @@ function renderContents() { let html = ''; bySection.forEach((arts, section) => { - html += '

' + esc(section) + '

' + (grid ? '
' : '
' : '
'; + html += ''; }); host.innerHTML = html; renderContentsBulkBar(); magUpdateAudioZipLink(); } -const MAG_CONTENTS_VIEW_CYCLE = ['list', 'grid', 'pages']; +const MAG_CONTENTS_VIEW_CYCLE = ['list', 'pages']; +const MAG_PAGES_COLS_KEY = 'ttsvc_mag_pages_cols'; // Every page, 1..pageCount, regardless of whether an article claims it -- // the article grid/list above can only ever show what detection already @@ -830,7 +819,7 @@ function renderPagesView(host) { if (!byPage.has(p)) byPage.set(p, []); byPage.get(p).push(a); })); - let html = '
'; + let html = '
'; for (let p = 1; p <= pageCount; p++) { const arts = byPage.get(p) || []; html += '
' + @@ -851,6 +840,15 @@ function renderPagesView(host) { host.innerHTML = html; } +function magSetPagesCols(n) { + state.pagesCols = Math.max(1, Math.min(12, parseInt(n, 10) || 8)); + try { localStorage.setItem(MAG_PAGES_COLS_KEY, String(state.pagesCols)); } catch (_) {} + const valueEl = $('mag-cols-value'); + if (valueEl) valueEl.textContent = String(state.pagesCols); + const grid = document.querySelector('.mag-pages-grid'); + if (grid) grid.style.setProperty('--cols', state.pagesCols); +} + function magToggleContentsView() { const i = MAG_CONTENTS_VIEW_CYCLE.indexOf(state.contentsView); state.contentsView = MAG_CONTENTS_VIEW_CYCLE[(i + 1) % MAG_CONTENTS_VIEW_CYCLE.length]; @@ -3559,6 +3557,8 @@ async function magInit() { try { const savedView = localStorage.getItem(MAG_CONTENTS_VIEW_KEY); if (MAG_CONTENTS_VIEW_CYCLE.includes(savedView)) state.contentsView = savedView; + const savedCols = parseInt(localStorage.getItem(MAG_PAGES_COLS_KEY), 10); + if (savedCols >= 1 && savedCols <= 12) state.pagesCols = savedCols; } catch (_) {} if (!$('mag-library-list')) return; // section not mounted magLoadLibrary(); @@ -3594,6 +3594,7 @@ root.magContentsCommitTitle = magContentsCommitTitle; root.magGenerateAllAudio = magGenerateAllAudio; root.magTogglePlaylist = magTogglePlaylist; root.magReviewPage = magReviewPage; +root.magSetPagesCols = magSetPagesCols; root.magPlaylistPlay = magPlaylistPlay; root.magContentsToggleArticle = magContentsToggleArticle; root.magContentsSelectAllVisible = magContentsSelectAllVisible; diff --git a/static/sections/s-magazine.html b/static/sections/s-magazine.html index 4cbd9eb..d66026e 100644 --- a/static/sections/s-magazine.html +++ b/static/sections/s-magazine.html @@ -58,9 +58,14 @@

Magazine

- + diff --git a/static/style.css b/static/style.css index 75e7b0e..011d226 100644 --- a/static/style.css +++ b/static/style.css @@ -4935,8 +4935,13 @@ input[list="lang-codes"] { background: color-mix(in srgb, var(--yellow, #d97706) 10%, var(--surface)); } .mag-coverage-banner .mdi { color: var(--yellow, #d97706); flex-shrink: 0; margin-top: 2px; } .mag-coverage-ranges { display: flex; flex-wrap: wrap; gap: 6px; } -.mag-pages-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); } +.mag-pages-grid { display: grid; grid-template-columns: repeat(var(--cols, 8), 1fr); gap: 12px; } .mag-pages-grid .mag-card-thumb { height: 120px; } +.mag-cols-control { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--subtext); } +.mag-cols-control input[type="range"] { width: 90px; accent-color: var(--accent); } +#mag-cols-value { min-width: 16px; text-align: right; } +@media (max-width: 900px) { .mag-pages-grid { grid-template-columns: repeat(min(var(--cols, 8), 4), 1fr); } } +@media (max-width: 560px) { .mag-pages-grid { grid-template-columns: repeat(min(var(--cols, 8), 2), 1fr); } } .mag-card.is-uncovered { border-color: var(--yellow, #d97706); background: color-mix(in srgb, var(--yellow, #d97706) 6%, var(--surface)); }