From 5b0fc1cb65a1bbdb36cdd00d34a963ecaceb6654 Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Tue, 22 Sep 2026 23:18:37 +0200 Subject: [PATCH] Release v1.50.0 --- CHANGELOG.md | 10 +++++++- VERSION | 2 +- static/index.html | 16 ++++++------ static/js/magazine.js | 58 ++++++++++++++++++++++++++++++++++++++----- static/style.css | 4 +++ 5 files changed, 74 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c85fda4..d4c81fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi --- +## [1.50.0] — 2026-09-22 + +### Added +- **Magazine: an "All pages" view.** Articles are a poor unit for "have I seen everything" — one can span many pages, several can share one page, and neither the list nor thumbnail view (both article-grained) can show either case. This adds a third view, cycled by the same toggle button, showing every page 1..N with its own thumbnail and whichever article(s) claim it (a page shared by two pieces shows both; a page claimed by none is flagged and links straight into Review there via the page-coverage jump added earlier). Articles remain the unit for narration, Approve, and audio export, which are inherently article-scoped — this is a complete-picture view alongside them, not a replacement. + +--- + ## [1.49.0] — 2026-09-22 ### Added @@ -4386,7 +4393,8 @@ Initial feature-complete release. --- -[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.49.0...HEAD +[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.50.0...HEAD +[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 [1.48.2]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.48.1...v1.48.2 [1.48.1]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.48.0...v1.48.1 diff --git a/VERSION b/VERSION index 7f3a46a..5a5c721 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.49.0 +1.50.0 diff --git a/static/index.html b/static/index.html index 4adb799..7131eb2 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 d601c47..ecfc661 100644 --- a/static/js/magazine.js +++ b/static/js/magazine.js @@ -695,10 +695,18 @@ function renderContents() { const grid = state.contentsView === 'grid'; const toggleBtn = $('mag-contents-view-toggle'); if (toggleBtn) { - toggleBtn.innerHTML = grid - ? ' List' - : ' Thumbnails'; - toggleBtn.setAttribute('aria-pressed', String(grid)); + 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]; + 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] + + '. Click to switch to ' + nextLabel.toLowerCase() + '.'; + } + if (state.contentsView === 'pages') { + renderPagesView(host); + renderContentsBulkBar(); + magUpdateAudioZipLink(); + return; } const actionsHtml = (a, done, progress) => @@ -774,8 +782,46 @@ function renderContents() { magUpdateAudioZipLink(); } +const MAG_CONTENTS_VIEW_CYCLE = ['list', 'grid', 'pages']; + +// Every page, 1..pageCount, regardless of whether an article claims it -- +// the article grid/list above can only ever show what detection already +// grouped, which is exactly what left 36% of one real issue invisible (see +// magUncoveredPageRanges). This is the complete picture: a page can belong +// to zero articles (never reviewed), one, or several (a page shared by two +// short pieces), and this shows all three cases rather than picking one. +function renderPagesView(host) { + const pageCount = state.doc?.pageCount || 0; + if (!pageCount) { host.innerHTML = '

Page count unknown yet.

'; return; } + const byPage = new Map(); + state.articles.forEach((a) => (a.pages || []).forEach((p) => { + if (!byPage.has(p)) byPage.set(p, []); + byPage.get(p).push(a); + })); + let html = '
'; + for (let p = 1; p <= pageCount; p++) { + const arts = byPage.get(p) || []; + html += '
' + + 'Page ' + p + '' + + 'Page ' + p + '' + + (arts.length + ? '' + esc(arts[0].title || 'Untitled') + + (arts.length > 1 ? ' +' + (arts.length - 1) + ' more' : '') + '' + + '
' + + arts.map((a) => '').join('') + + '
' + : 'no article' + + '
') + + '
'; + } + html += '
'; + host.innerHTML = html; +} + function magToggleContentsView() { - state.contentsView = state.contentsView === 'grid' ? 'list' : 'grid'; + const i = MAG_CONTENTS_VIEW_CYCLE.indexOf(state.contentsView); + state.contentsView = MAG_CONTENTS_VIEW_CYCLE[(i + 1) % MAG_CONTENTS_VIEW_CYCLE.length]; try { localStorage.setItem(MAG_CONTENTS_VIEW_KEY, state.contentsView); } catch (_) {} renderContents(); } @@ -3471,7 +3517,7 @@ async function magInit() { } try { const savedView = localStorage.getItem(MAG_CONTENTS_VIEW_KEY); - if (savedView === 'grid' || savedView === 'list') state.contentsView = savedView; + if (MAG_CONTENTS_VIEW_CYCLE.includes(savedView)) state.contentsView = savedView; } catch (_) {} if (!$('mag-library-list')) return; // section not mounted magLoadLibrary(); diff --git a/static/style.css b/static/style.css index 7ca16ab..75e7b0e 100644 --- a/static/style.css +++ b/static/style.css @@ -4935,6 +4935,10 @@ 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 .mag-card-thumb { height: 120px; } +.mag-card.is-uncovered { border-color: var(--yellow, #d97706); + background: color-mix(in srgb, var(--yellow, #d97706) 6%, var(--surface)); } .mag-audio-export { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 14px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: var(--radius);