From 754d37c457092f9aca96fe91b20a3ad8c295d274 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sun, 20 Oct 2024 20:08:07 -0300 Subject: content: generateTrackListItem Turns out yeah, these are worth combining. --- .../dependencies/generateAlbumTrackListItem.js | 155 +++++---------------- .../generateAlbumTrackListMissingDuration.js | 35 ----- src/content/dependencies/generateTrackList.js | 56 ++------ src/content/dependencies/generateTrackListItem.js | 106 ++++++++++++++ .../generateTrackListMissingDuration.js | 35 +++++ 5 files changed, 190 insertions(+), 197 deletions(-) delete mode 100644 src/content/dependencies/generateAlbumTrackListMissingDuration.js create mode 100644 src/content/dependencies/generateTrackListItem.js create mode 100644 src/content/dependencies/generateTrackListMissingDuration.js diff --git a/src/content/dependencies/generateAlbumTrackListItem.js b/src/content/dependencies/generateAlbumTrackListItem.js index 851bf32e..a42dcb66 100644 --- a/src/content/dependencies/generateAlbumTrackListItem.js +++ b/src/content/dependencies/generateAlbumTrackListItem.js @@ -1,74 +1,36 @@ -import {compareArrays, empty} from '#sugar'; - export default { - contentDependencies: [ - 'generateAlbumTrackListMissingDuration', - 'generateArtistCredit', - 'linkTrack', - ], - - extraDependencies: ['getColors', 'html', 'language'], - - query(track, album) { - const query = {}; - - query.duration = track.duration ?? 0; + contentDependencies: ['generateTrackListItem'], + extraDependencies: ['html'], - query.trackHasDuration = !!track.duration; + query: (track, album) => ({ + trackHasDuration: + !!track.duration, - query.sectionHasDuration = + sectionHasDuration: !album.trackSections .some(section => section.tracks.every(track => !track.duration) && - section.tracks.includes(track)); - - query.albumHasDuration = - album.tracks.some(track => track.duration); - - return query; - }, - - relations(relation, query, track) { - const relations = {}; - - relations.credit = - relation('generateArtistCredit', - track.artistContribs, - track.album.artistContribs); - - relations.trackLink = - relation('linkTrack', track); - - if (!query.trackHasDuration) { - relations.missingDuration = - relation('generateAlbumTrackListMissingDuration'); - } - - return relations; - }, + section.tracks.includes(track)), - data(query, track, album) { - const data = {}; + albumHasDuration: + album.tracks.some(track => track.duration), + }), - data.duration = query.duration; - data.trackHasDuration = query.trackHasDuration; - data.sectionHasDuration = query.sectionHasDuration; - data.albumHasDuration = query.albumHasDuration; + relations: (relation, query, track) => ({ + item: + relation('generateTrackListItem', + track, + track.album.artistContribs), + }), - if (track.color !== album.color) { - data.color = track.color; - } + data: (query, track, album) => ({ + trackHasDuration: query.trackHasDuration, + sectionHasDuration: query.sectionHasDuration, + albumHasDuration: query.albumHasDuration, - data.showArtists = - !empty(track.artistContribs) && - (empty(album.artistContribs) || - !compareArrays( - track.artistContribs.map(contrib => contrib.artist), - album.artistContribs.map(contrib => contrib.artist), - {checkOrder: false})); - - return data; - }, + colorize: + track.color !== album.color, + }), slots: { collapseDurationScope: { @@ -79,60 +41,19 @@ export default { }, }, - generate: (data, relations, slots, {getColors, html, language}) => - language.encapsulate('trackList.item', itemCapsule => - html.tag('li', - data.color && - {style: `--primary-color: ${getColors(data.color).primary}`}, - - language.encapsulate(itemCapsule, workingCapsule => { - const workingOptions = {}; - - workingOptions.track = - relations.trackLink - .slot('color', false); - - const collapseDuration = - (slots.collapseDurationScope === 'track' - ? !data.trackHasDuration - : slots.collapseDurationScope === 'section' - ? !data.sectionHasDuration - : slots.collapseDurationScope === 'album' - ? !data.albumHasDuration - : false); - - if (!collapseDuration) { - workingCapsule += '.withDuration'; - workingOptions.duration = - (data.trackHasDuration - ? language.$(itemCapsule, 'withDuration.duration', { - duration: - language.formatDuration(data.duration), - }) - : relations.missingDuration); - } - - const artistCapsule = language.encapsulate(itemCapsule, 'withArtists'); - - relations.credit.setSlots({ - normalStringKey: - artistCapsule + '.by', - - featuringStringKey: - artistCapsule + '.featuring', - - normalFeaturingStringKey: - artistCapsule + '.by.featuring', - }); - - if (!html.isBlank(relations.credit)) { - workingCapsule += '.withArtists'; - workingOptions.by = - html.tag('span', {class: 'by'}, - html.metatag('chunkwrap', {split: ','}, - html.resolve(relations.credit))); - } - - return language.$(workingCapsule, workingOptions); - }))), + generate: (data, relations, slots) => + relations.item.slots({ + showArtists: true, + + showDuration: + (slots.collapseDurationScope === 'track' + ? data.trackHasDuration + : slots.collapseDurationScope === 'section' + ? data.sectionHasDuration + : slots.collapseDurationScope === 'album' + ? data.albumHasDuration + : true), + + color: data.colorize, + }), }; diff --git a/src/content/dependencies/generateAlbumTrackListMissingDuration.js b/src/content/dependencies/generateAlbumTrackListMissingDuration.js deleted file mode 100644 index b5917982..00000000 --- a/src/content/dependencies/generateAlbumTrackListMissingDuration.js +++ /dev/null @@ -1,35 +0,0 @@ -export default { - contentDependencies: ['generateTextWithTooltip', 'generateTooltip'], - extraDependencies: ['html', 'language'], - - relations: (relation) => ({ - textWithTooltip: - relation('generateTextWithTooltip'), - - tooltip: - relation('generateTooltip'), - }), - - generate: (relations, {html, language}) => - language.encapsulate('trackList.item.withDuration', itemCapsule => - language.encapsulate(itemCapsule, 'duration', durationCapsule => - relations.textWithTooltip.slots({ - attributes: {class: 'missing-duration'}, - customInteractionCue: true, - - text: - language.$(durationCapsule, { - duration: - html.tag('span', {class: 'text-with-tooltip-interaction-cue'}, - language.$(durationCapsule, 'missing')), - }), - - tooltip: - relations.tooltip.slots({ - attributes: {class: 'missing-duration-tooltip'}, - - content: - language.$(durationCapsule, 'missing.info'), - }), - }))), -}; diff --git a/src/content/dependencies/generateTrackList.js b/src/content/dependencies/generateTrackList.js index 2d6e9a85..19e2efeb 100644 --- a/src/content/dependencies/generateTrackList.js +++ b/src/content/dependencies/generateTrackList.js @@ -1,55 +1,21 @@ -import {stitchArrays} from '#sugar'; - export default { - contentDependencies: ['generateArtistCredit', 'linkTrack'], - - extraDependencies: ['html', 'language'], + contentDependencies: ['generateTrackListItem'], + extraDependencies: ['html'], relations: (relation, tracks) => ({ - trackLinks: + items: tracks - .map(track => relation('linkTrack', track)), - - artistCredits: - tracks - .map(track => - relation('generateArtistCredit', track.artistContribs, [])), + .map(track => relation('generateTrackListItem', track, [])), }), - generate: (relations, {html, language}) => + generate: (relations, {html}) => html.tag('ul', {[html.onlyIfContent]: true}, - stitchArrays({ - trackLink: relations.trackLinks, - artistCredit: relations.artistCredits, - }).map(({trackLink, artistCredit}) => - html.tag('li', - language.encapsulate('trackList.item', itemCapsule => - language.encapsulate(itemCapsule, workingCapsule => { - const workingOptions = {track: trackLink}; - - const artistCapsule = language.encapsulate(itemCapsule, 'withArtists'); - - artistCredit.setSlots({ - normalStringKey: - artistCapsule + '.by', - - featuringStringKey: - artistCapsule + '.featuring', - - normalFeaturingStringKey: - artistCapsule + '.by.featuring', - }); - - if (!html.isBlank(artistCredit)) { - workingCapsule += '.withArtists'; - workingOptions.by = - html.tag('span', {class: 'by'}, - html.metatag('chunkwrap', {split: ','}, - html.resolve(artistCredit))); - } - - return language.$(workingCapsule, workingOptions); - }))))), + relations.items.map(item => + item.slots({ + showArtists: true, + showDuration: false, + color: true, + }))), }; diff --git a/src/content/dependencies/generateTrackListItem.js b/src/content/dependencies/generateTrackListItem.js new file mode 100644 index 00000000..36e56717 --- /dev/null +++ b/src/content/dependencies/generateTrackListItem.js @@ -0,0 +1,106 @@ +export default { + contentDependencies: [ + 'generateArtistCredit', + 'generateColorStyleAttribute', + 'generateTrackListMissingDuration', + 'linkTrack', + ], + + extraDependencies: ['html', 'language'], + + relations: (relation, track, contextContributions) => ({ + trackLink: + relation('linkTrack', track), + + credit: + relation('generateArtistCredit', + track.artistContribs, + contextContributions), + + colorStyle: + relation('generateColorStyleAttribute', track.color), + + missingDuration: + (track.duration + ? null + : relation('generateTrackListMissingDuration')), + }), + + data: (track, _contextContributions) => ({ + duration: + track.duration ?? 0, + + trackHasDuration: + !!track.duration, + }), + + slots: { + // showArtists enables showing artists *at all.* It doesn't take precedence + // over behavior which automatically collapses (certain) artists because of + // provided context contributions. + showArtists: { + type: 'boolean', + default: true, + }, + + // If true and the track doesn't have a duration, a missing-duration cue + // will be displayed instead. + showDuration: { + type: 'boolean', + default: false, + }, + + color: { + type: 'boolean', + default: true, + }, + }, + + generate: (data, relations, slots, {html, language}) => + language.encapsulate('trackList.item', itemCapsule => + html.tag('li', + slots.color && + relations.colorStyle.slot('context', 'primary-only'), + + language.encapsulate(itemCapsule, workingCapsule => { + const workingOptions = {}; + + workingOptions.track = + relations.trackLink + .slot('color', false); + + if (slots.showDuration) { + workingCapsule += '.withDuration'; + workingOptions.duration = + (data.trackHasDuration + ? language.$(itemCapsule, 'withDuration.duration', { + duration: + language.formatDuration(data.duration), + }) + : relations.missingDuration); + } + + const artistCapsule = language.encapsulate(itemCapsule, 'withArtists'); + + relations.credit.setSlots({ + normalStringKey: + artistCapsule + '.by', + + featuringStringKey: + artistCapsule + '.featuring', + + normalFeaturingStringKey: + artistCapsule + '.by.featuring', + }); + + if (!html.isBlank(relations.credit)) { + workingCapsule += '.withArtists'; + workingOptions.by = + html.tag('span', {class: 'by'}, + html.metatag('chunkwrap', {split: ','}, + html.resolve(relations.credit))); + } + + return language.$(workingCapsule, workingOptions); + }))), +}; diff --git a/src/content/dependencies/generateTrackListMissingDuration.js b/src/content/dependencies/generateTrackListMissingDuration.js new file mode 100644 index 00000000..b5917982 --- /dev/null +++ b/src/content/dependencies/generateTrackListMissingDuration.js @@ -0,0 +1,35 @@ +export default { + contentDependencies: ['generateTextWithTooltip', 'generateTooltip'], + extraDependencies: ['html', 'language'], + + relations: (relation) => ({ + textWithTooltip: + relation('generateTextWithTooltip'), + + tooltip: + relation('generateTooltip'), + }), + + generate: (relations, {html, language}) => + language.encapsulate('trackList.item.withDuration', itemCapsule => + language.encapsulate(itemCapsule, 'duration', durationCapsule => + relations.textWithTooltip.slots({ + attributes: {class: 'missing-duration'}, + customInteractionCue: true, + + text: + language.$(durationCapsule, { + duration: + html.tag('span', {class: 'text-with-tooltip-interaction-cue'}, + language.$(durationCapsule, 'missing')), + }), + + tooltip: + relations.tooltip.slots({ + attributes: {class: 'missing-duration-tooltip'}, + + content: + language.$(durationCapsule, 'missing.info'), + }), + }))), +}; -- cgit 1.3.0-6-gf8a5