diff options
-rw-r--r-- | src/content/dependencies/generateAlbumGalleryTrackGrid.js | 6 | ||||
-rw-r--r-- | src/content/dependencies/generateArtistGalleryPage.js | 6 | ||||
-rw-r--r-- | src/content/dependencies/generateCoverGrid.js | 37 | ||||
-rw-r--r-- | src/content/dependencies/generateGroupGalleryPageAlbumGrid.js | 18 | ||||
-rw-r--r-- | src/static/css/site.css | 34 | ||||
-rw-r--r-- | src/static/js/client/index.js | 2 | ||||
-rw-r--r-- | src/static/js/client/reveal-all-grid-control.js | 72 | ||||
-rw-r--r-- | src/strings-default.yaml | 5 |
8 files changed, 174 insertions, 6 deletions
diff --git a/src/content/dependencies/generateAlbumGalleryTrackGrid.js b/src/content/dependencies/generateAlbumGalleryTrackGrid.js index fb5ed7ea..86c35b6f 100644 --- a/src/content/dependencies/generateAlbumGalleryTrackGrid.js +++ b/src/content/dependencies/generateAlbumGalleryTrackGrid.js @@ -77,6 +77,9 @@ export default { ? artwork.artistContribs .map(contrib => contrib.artist.name) : null)), + + allWarnings: + query.artworks.flatMap(artwork => artwork?.contentWarnings), }), slots: { @@ -117,6 +120,9 @@ export default { artists: language.formatUnitList(artists), })), + + revealAllWarnings: + data.allWarnings, }), ]), }; diff --git a/src/content/dependencies/generateArtistGalleryPage.js b/src/content/dependencies/generateArtistGalleryPage.js index 6a24275e..094edc0c 100644 --- a/src/content/dependencies/generateArtistGalleryPage.js +++ b/src/content/dependencies/generateArtistGalleryPage.js @@ -58,6 +58,10 @@ export default { .map(artwork => artwork.artistContribs .filter(contrib => contrib.artist !== artist) .map(contrib => contrib.artist.name)), + + allWarnings: + query.artworks + .flatMap(artwork => artwork.contentWarnings), }), generate: (data, relations, {html, language}) => @@ -93,6 +97,8 @@ export default { artists: language.formatUnitList(names), })), + + revealAllWarnings: data.allWarnings, }), ], diff --git a/src/content/dependencies/generateCoverGrid.js b/src/content/dependencies/generateCoverGrid.js index e94eab05..89371015 100644 --- a/src/content/dependencies/generateCoverGrid.js +++ b/src/content/dependencies/generateCoverGrid.js @@ -1,4 +1,4 @@ -import {stitchArrays} from '#sugar'; +import {empty, stitchArrays, unique} from '#sugar'; export default { contentDependencies: ['generateGridActionLinks'], @@ -41,6 +41,10 @@ export default { lazy: {validate: v => v.anyOf(v.isWholeNumber, v.isBoolean)}, actionLinks: {validate: v => v.sparseArrayOf(v.isHTML)}, + + revealAllWarnings: { + validate: v => v.looseArrayOf(v.isString), + }, }, generate: (relations, slots, {html, language}) => @@ -49,6 +53,37 @@ export default { {[html.onlyIfContent]: true}, [ + !empty((slots.revealAllWarnings ?? []).filter(Boolean)) && + language.encapsulate('misc.coverGrid.revealAll', capsule => + html.tag('div', {class: 'reveal-all-container'}, + ((slots.tab ?? []) + .slice(0, 4) + .some(tab => tab && !html.isBlank(tab))) && + + {class: 'has-nearby-tab'}, + + html.tag('p', {class: 'reveal-all'}, [ + html.tag('a', {href: '#'}, [ + html.tag('span', {class: 'reveal-label'}, + language.$(capsule, 'reveal')), + + html.tag('span', {class: 'conceal-label'}, + {style: 'display: none'}, + language.$(capsule, 'conceal')), + ]), + + html.tag('br'), + + html.tag('span', {class: 'warnings'}, + language.$(capsule, 'warnings', { + warnings: + language.formatUnitList( + unique(slots.revealAllWarnings.filter(Boolean)) + .sort() + .map(warning => html.tag('b', warning))), + })), + ]))), + stitchArrays({ classes: slots.classes, attributes: slots.itemAttributes, diff --git a/src/content/dependencies/generateGroupGalleryPageAlbumGrid.js b/src/content/dependencies/generateGroupGalleryPageAlbumGrid.js index 25e57a67..9167a5ad 100644 --- a/src/content/dependencies/generateGroupGalleryPageAlbumGrid.js +++ b/src/content/dependencies/generateGroupGalleryPageAlbumGrid.js @@ -37,6 +37,12 @@ export default { return album.artistContribs; }), + + artworks: + albums.map(album => + (album.hasCoverArt + ? album.coverArtworks[0] + : null)), }), relations: (relation, query, albums, _group) => ({ @@ -52,11 +58,8 @@ export default { .map(album => relation('linkAlbum', album)), images: - albums - .map(album => - (album.hasCoverArt - ? relation('image', album.coverArtworks[0]) - : relation('image'))) + query.artworks + .map(artwork => relation('image', artwork)), }), data: (query, albums, group) => ({ @@ -69,6 +72,9 @@ export default { tracks: albums.map(album => album.tracks.length), + allWarnings: + query.artworks.flatMap(artwork => artwork?.contentWarnings), + durations: albums.map(album => (album.hideDuration @@ -141,5 +147,7 @@ export default { time: language.formatDuration(duration), }) : null)), + + revealAllWarnings: data.allWarnings, })), }; diff --git a/src/static/css/site.css b/src/static/css/site.css index 5faed373..d85b8283 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -3078,6 +3078,40 @@ video.pixelate, .pixelate video { border: 1px dashed #fff3; } +.grid-listing .reveal-all-container { + flex-basis: 100%; +} + +.grid-listing:not(:has(.grid-item:not([class*="hidden-by-"]))) .reveal-all-container { + display: none; +} + +.grid-listing .reveal-all-container.has-nearby-tab { + margin-bottom: 0.6em; +} + +.grid-listing .reveal-all { + max-width: 400px; + margin: 0.20em auto 0; + text-align: center; +} + +.grid-listing .reveal-all .warnings:not(.reveal-all:hover *) { + opacity: 0.4; +} + +.grid-listing .reveal-all a { + display: inline-block; + margin-bottom: 0.15em; + + text-decoration: underline; + text-decoration-style: dotted; +} + +.grid-listing .reveal-all b { + white-space: nowrap; +} + .grid-item { line-height: 1.2; font-size: 0.9em; diff --git a/src/static/js/client/index.js b/src/static/js/client/index.js index 4ca4700e..016ce9ad 100644 --- a/src/static/js/client/index.js +++ b/src/static/js/client/index.js @@ -19,6 +19,7 @@ import * as imageOverlayModule from './image-overlay.js'; import * as intrapageDotSwitcherModule from './intrapage-dot-switcher.js'; import * as liveMousePositionModule from './live-mouse-position.js'; import * as quickDescriptionModule from './quick-description.js'; +import * as revealAllGridControlModule from './reveal-all-grid-control.js'; import * as scriptedLinkModule from './scripted-link.js'; import * as sidebarSearchModule from './sidebar-search.js'; import * as stickyHeadingModule from './sticky-heading.js'; @@ -44,6 +45,7 @@ export const modules = [ intrapageDotSwitcherModule, liveMousePositionModule, quickDescriptionModule, + revealAllGridControlModule, scriptedLinkModule, sidebarSearchModule, stickyHeadingModule, diff --git a/src/static/js/client/reveal-all-grid-control.js b/src/static/js/client/reveal-all-grid-control.js new file mode 100644 index 00000000..1b362bea --- /dev/null +++ b/src/static/js/client/reveal-all-grid-control.js @@ -0,0 +1,72 @@ +/* eslint-env browser */ + +import {cssProp} from '../client-util.js'; + +export const info = { + id: 'revealAllGridControlInfo', + + revealAllLinks: null, + revealables: null, + + revealLabels: null, + concealLabels: null, +}; + +export function getPageReferences() { + info.revealAllLinks = + Array.from(document.querySelectorAll('.reveal-all a')); + + info.revealables = + info.revealAllLinks + .map(link => link.closest('.grid-listing')) + .map(listing => listing.querySelectorAll('.reveal')); + + info.revealLabels = + info.revealAllLinks + .map(link => link.querySelector('.reveal-label')); + + info.concealLabels = + info.revealAllLinks + .map(link => link.querySelector('.conceal-label')); +} + +export function addPageListeners() { + for (const [index, link] of info.revealAllLinks.entries()) { + link.addEventListener('click', domEvent => { + domEvent.preventDefault(); + handleRevealAllLinkClicked(index); + }); + } +} + +export function addInternalListeners() { + // Don't even think about it. "Reveal all artworks" is a stable control, + // meaning it only changes because the user interacted with it directly. +} + +function handleRevealAllLinkClicked(index) { + const revealables = info.revealables[index]; + const revealLabel = info.revealLabels[index]; + const concealLabel = info.concealLabels[index]; + + const shouldReveal = + (cssProp(revealLabel, 'display') === 'none' + ? false + : true); + + for (const revealable of revealables) { + if (shouldReveal) { + revealable.classList.add('revealed'); + } else { + revealable.classList.remove('revealed'); + } + } + + if (shouldReveal) { + cssProp(revealLabel, 'display', 'none'); + cssProp(concealLabel, 'display', null); + } else { + cssProp(revealLabel, 'display', null); + cssProp(concealLabel, 'display', 'none'); + } +} diff --git a/src/strings-default.yaml b/src/strings-default.yaml index f7fb1f2b..02e1ee31 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -1002,6 +1002,11 @@ misc: # that thing. coverGrid: + revealAll: + reveal: "Reveal all artworks" + conceal: "Conceal all artworks" + warnings: "In this gallery: {WARNINGS}" + noCoverArt: "{ALBUM}" tab: |