diff options
Diffstat (limited to 'src/data/things/album')
| -rw-r--r-- | src/data/things/album/Album.js | 319 | ||||
| -rw-r--r-- | src/data/things/album/TrackSection.js | 16 |
2 files changed, 251 insertions, 84 deletions
diff --git a/src/data/things/album/Album.js b/src/data/things/album/Album.js index f07d552c..4f3dd770 100644 --- a/src/data/things/album/Album.js +++ b/src/data/things/album/Album.js @@ -1,14 +1,18 @@ import {input, V} from '#composite'; import {empty} from '#sugar'; import Thing from '#thing'; +import {getKebabCase} from '#wiki-data'; import { + anyOf, is, + isBoolean, isContributionList, isDate, isExcludingURLsReason, isDirectory, isNumber, + isString, } from '#validators'; import { @@ -29,8 +33,6 @@ import { } from '#yaml'; import {withFlattenedList, withPropertyFromList} from '#composite/data'; -import {withRecontextualizedContributionList, withResolvedContribs} - from '#composite/wiki-data'; import { exitWithoutDependency, @@ -41,6 +43,12 @@ import { } from '#composite/control-flow'; import { + withDirectory, + withRecontextualizedContributionList, + withResolvedContribs, +} from '#composite/wiki-data'; + +import { color, commentatorArtists, constitutibleArtwork, @@ -48,7 +56,6 @@ import { contentString, contributionList, dimensions, - directory, fileExtension, flag, hasArtwork, @@ -77,7 +84,6 @@ export class Album extends Thing { ]; static [Thing.getPropertyDescriptors] = ({ - AdditionalFile, AdditionalName, AlbumArtistContribution, AlbumBannerArtistContribution, @@ -87,6 +93,7 @@ export class Album extends Thing { CommentaryEntry, CreditingSourcesEntry, Group, + MiscellaneousAdditionalFile, MusicVideo, TrackArtistContribution, TrackSection, @@ -99,16 +106,89 @@ export class Album extends Thing { // > Update & expose - Identifying metadata name: name(V('Unnamed Album')), - directory: directory(), + nameDetail: simpleString(), + + nameDetailForTracks: { + flags: {update: true, expose: true}, + + update: {validate: isString}, + + expose: { + dependencies: ['name', 'nameDetail'], + transform: (value, {name, nameDetail}) => + (value + ? value + : nameDetail + ? `${name}, ${nameDetail}` + : name), + }, + }, - directorySuffix: [ + directory: [ + withDirectory({ + directory: + input.updateValue({ + validate(value) { + isDirectory(value); + + if (value === 'vgm') { + throw new Error( + `"vgm" is a reserved directory and can't be used albums`); + } + + return true; + }, + }), + + suffix: 'suffixDirectory', + }), + + exposeDependency('#directory'), + ], + + suffixDirectory: [ + exposeUpdateValueOrContinue({ + validate: input.value( + anyOf(is(false), isDirectory)), + }), + + { + transform: (value, continuation) => + (value === false + ? null + : continuation()), + }, + + { + dependencies: ['nameDetail'], + compute(continuation, {nameDetail}) { + if (nameDetail) { + return getKebabCase(nameDetail); + } + + return continuation(); + }, + }, + + exposeConstant(V(null)), + ], + + directorySuffixForTracks: [ exposeUpdateValueOrContinue({ validate: input.value(isDirectory), }), - exposeDependency('directory'), + { + dependencies: ['directory', 'name', 'nameDetailForTracks'], + compute: ({directory, name, nameDetailForTracks}) => + (nameDetailForTracks === name + ? directory + : getKebabCase(nameDetailForTracks)), + }, ], + suffixTrackDirectoriesByDefault: flag(V(false)), + alwaysReferenceByDirectory: flag(V(false)), referenceTracksByDirectory: [ @@ -125,14 +205,13 @@ export class Album extends Thing { exposeConstant(V('normally')), ], - suffixTrackDirectories: flag(V(false)), - style: [ exposeUpdateValueOrContinue({ validate: input.value(is(...[ 'album', 'single', 'meta', + 'in-game vgm', ])), }), @@ -144,7 +223,8 @@ export class Album extends Thing { additionalNames: thingList(V(AdditionalName)), - date: simpleDate(), + dateReleased: simpleDate(), + datePosted: simpleDate(), dateAddedToWiki: simpleDate(), // > Update & expose - Credits and contributors @@ -188,11 +268,37 @@ export class Album extends Thing { isListedOnHomepage: flag(V(true)), isListedInGalleries: flag(V(true)), - hasTrackNumbers: flag(V(true)), + hasTrackNumbers: [ + exposeUpdateValueOrContinue({ + validate: input.value(isBoolean), + }), + + { + dependencies: ['style'], + compute: ({style}) => + (style === 'in-game vgm' + ? false + : true), + }, + ], + showAlbumInTracksWithoutArtists: flag(V(false)), showTrackSectionInNavBar: flag(V(false)), showArtistsInTrackList: flag(V(true)), - hideDuration: flag(V(false)), + + hideDuration: [ + exposeUpdateValueOrContinue({ + validate: input.value(isBoolean), + }), + + { + dependencies: ['style'], + compute: ({style}) => + (style === 'in-game vgm' + ? true + : false), + }, + ], // > Update & expose - General metadata @@ -212,6 +318,11 @@ export class Album extends Thing { .call(this, 'Cover Artwork'), ], + hasCoverArt: hasArtwork({ + contribs: '_coverArtistContribs', + artworks: '_coverArtworks', + }), + coverArtistContribs: contributionList({ date: 'coverArtDate', artistProperty: input.value('albumCoverArtistContributions'), @@ -300,6 +411,11 @@ export class Album extends Thing { .call(this, 'Wallpaper Artwork'), ], + hasWallpaperArt: hasArtwork({ + contribs: '_wallpaperArtistContribs', + artwork: '_wallpaperArtwork', + }), + wallpaperArtistContribs: contributionList({ class: input.value(AlbumWallpaperArtistContribution), date: 'coverArtDate', @@ -343,6 +459,11 @@ export class Album extends Thing { .call(this, 'Banner Artwork'), ], + hasBannerArt: hasArtwork({ + contribs: '_bannerArtistContribs', + artwork: '_bannerArtwork', + }), + bannerArtistContribs: contributionList({ class: input.value(AlbumBannerArtistContribution), date: 'coverArtDate', @@ -394,7 +515,7 @@ export class Album extends Thing { // > Update & expose - Additional files - additionalFiles: thingList(V(AdditionalFile)), + additionalFiles: thingList(V(MiscellaneousAdditionalFile)), // > Update only @@ -411,22 +532,31 @@ export class Album extends Thing { isAlbum: exposeConstant(V(true)), - commentatorArtists: commentatorArtists(), + nameForReferencingAcrossWiki: [ + { + dependencies: ['alwaysReferenceByDirectory'], + compute: (continuation, {alwaysReferenceByDirectory}) => + (alwaysReferenceByDirectory + ? continuation.exit(null) + : continuation()), + }, - hasCoverArt: hasArtwork({ - contribs: '_coverArtistContribs', - artworks: '_coverArtworks', - }), + exposeDependency('nameForSorting'), + ], - hasWallpaperArt: hasArtwork({ - contribs: '_wallpaperArtistContribs', - artwork: '_wallpaperArtwork', - }), + nameForSorting: [ + { + dependencies: ['name', 'nameDetail'], + compute: (continuation, {name, nameDetail}) => + (nameDetail + ? continuation.exit(`${name} (${nameDetail})`) + : continuation()), + }, - hasBannerArt: hasArtwork({ - contribs: '_bannerArtistContribs', - artwork: '_bannerArtwork', - }), + exposeDependency('name'), + ], + + commentatorArtists: commentatorArtists(), tracks: [ exitWithoutDependency('trackSections', V([])), @@ -435,6 +565,27 @@ export class Album extends Thing { withFlattenedList('#trackSections.tracks'), exposeDependency('#flattenedList'), ], + + date: [ + exposeDependencyOrContinue('dateReleased'), + exposeDependencyOrContinue('datePosted'), + exposeConstant(V(null)), + ], + + dateStyle: [ + exitWithoutDependency('date'), + + { + dependencies: ['_dateReleased', '_datePosted'], + compute: ({ + ['_dateReleased']: dateReleased, + ['_datePosted']: datePosted, + }) => + (dateReleased ? 'released' + : datePosted ? 'posted' + : null), + }, + ] }); static [Thing.getSerializeDescriptors] = ({ @@ -594,9 +745,15 @@ export class Album extends Thing { // Identifying metadata 'Album': {property: 'name'}, + 'Name Detail': {property: 'nameDetail'}, + 'Name Detail For Tracks': {property: 'nameDetailForTracks'}, + 'Directory': {property: 'directory'}, - 'Directory Suffix': {property: 'directorySuffix'}, - 'Suffix Track Directories': {property: 'suffixTrackDirectories'}, + 'Suffix Own Directory': {property: 'suffixDirectory'}, + + 'Directory Suffix': {property: 'directorySuffixForTracks'}, + 'Suffix Track Directories': {property: 'suffixTrackDirectoriesByDefault'}, + 'Always Reference By Directory': {property: 'alwaysReferenceByDirectory'}, 'Reference Tracks By Directory': {property: 'referenceTracksByDirectory'}, @@ -623,15 +780,9 @@ export class Album extends Thing { transform: parseAdditionalNames, }, - 'Date': { - property: 'date', - transform: parseDate, - }, - - 'Date Added': { - property: 'dateAddedToWiki', - transform: parseDate, - }, + 'Date': {property: 'dateReleased', transform: parseDate}, + 'Date Posted': {property: 'datePosted', transform: parseDate}, + 'Date Added': {property: 'dateAddedToWiki', transform: parseDate}, // Credits and contributors @@ -722,6 +873,8 @@ export class Album extends Thing { }), }, + 'Has Cover Art': {property: 'hasCoverArt'}, + 'Cover Artists': { property: 'coverArtistContribs', transform: parseContributors, @@ -752,6 +905,8 @@ export class Album extends Thing { transform: parseDimensions, }, + 'Has Wallpaper Art': {property: 'hasWallpaperArt'}, + 'Wallpaper Artists': { property: 'wallpaperArtistContribs', transform: parseContributors, @@ -764,6 +919,8 @@ export class Album extends Thing { transform: parseWallpaperParts, }, + 'Has Banner Art': {property: 'hasBannerArt'}, + 'Banner Artists': { property: 'bannerArtistContribs', transform: parseContributors, @@ -852,62 +1009,72 @@ export class Album extends Thing { ], }; - getOwnAdditionalFilePath(_file, filename) { - return [ - 'media.albumAdditionalFile', - this.directory, - filename, - ]; + getOwnAdditionalFilePath(file, filename) { + if (file.folder) { + return [ + 'media.albumAdditionalFileInFolder', + this.directory, + file.folder, + filename, + ]; + } else { + return [ + 'media.albumAdditionalFile', + this.directory, + filename, + ]; + } } getOwnArtworkPath(artwork) { + const ext = artwork.fileExtension; + if (artwork === this.bannerArtwork) { - return [ - 'media.albumBanner', - this.directory, - artwork.fileExtension, - ]; + return this.getAlbumArtPath(`banner.${ext}`); } if (artwork === this.wallpaperArtwork) { - if (!empty(this.wallpaperParts)) { + if (empty(this.wallpaperParts)) { + return this.getAlbumArtPath(`bg.${ext}`); + } else { return null; } - - return [ - 'media.albumWallpaper', - this.directory, - artwork.fileExtension, - ]; } - // TODO: using trackCover here is obviously, badly wrong - // but we ought to refactor banners and wallpapers similarly - // (i.e. depend on those intrinsic artwork paths rather than - // accessing media.{albumBanner,albumWallpaper} from content - // or other code directly) - return [ - 'media.trackCover', - this.directory, - + const basename = (artwork.unqualifiedDirectory ? 'cover-' + artwork.unqualifiedDirectory - : 'cover'), + : 'cover'); + + return this.getAlbumArtPath(`${basename}.${ext}`); + } - artwork.fileExtension, - ]; + getWallpaperPartPath(part) { + return this.getAlbumArtPath(part.asset); } getOwnMusicVideoCoverPath(musicVideo) { - // Lala, same shenanigan as above, this is media.trackCover - // where it shouldn't be. - - return [ - 'media.trackCover', - this.directory, - musicVideo.unqualifiedDirectory, - musicVideo.coverArtFileExtension, - ]; + const filename = + musicVideo.unqualifiedDirectory + + `.${musicVideo.coverArtFileExtension}`; + + return this.getAlbumArtPath(filename); + } + + getAlbumArtPath(filename) { + const key = this.#getArtworkPathKey(); + const front = [key, this.directory]; + return [...front, filename]; + } + + #getArtworkPathKey(artwork) { + switch (this.style) { + case 'in-game vgm': + return 'media.vgmAlbumArt'; + + default: + return 'media.albumArt'; + } } // As of writing, albums don't even have a `duration` property... diff --git a/src/data/things/album/TrackSection.js b/src/data/things/album/TrackSection.js index 451f8f7b..00963d1b 100644 --- a/src/data/things/album/TrackSection.js +++ b/src/data/things/album/TrackSection.js @@ -50,22 +50,22 @@ export class TrackSection extends Thing { unqualifiedDirectory: directory(), - directorySuffix: [ + directorySuffixForTracks: [ exposeUpdateValueOrContinue({ validate: input.value(isDirectory), }), - withPropertyFromObject('album', V('directorySuffix')), - exposeDependency('#album.directorySuffix'), + withPropertyFromObject('album', V('directorySuffixForTracks')), + exposeDependency('#album.directorySuffixForTracks'), ], - suffixTrackDirectories: [ + suffixTrackDirectoriesByDefault: [ exposeUpdateValueOrContinue({ validate: input.value(isBoolean), }), - withPropertyFromObject('album', V('suffixTrackDirectories')), - exposeDependency('#album.suffixTrackDirectories'), + withPropertyFromObject('album', V('suffixTrackDirectoriesByDefault')), + exposeDependency('#album.suffixTrackDirectoriesByDefault'), ], color: [ @@ -204,8 +204,8 @@ export class TrackSection extends Thing { static [Thing.yamlDocumentSpec] = { fields: { 'Section': {property: 'name'}, - 'Directory Suffix': {property: 'directorySuffix'}, - 'Suffix Track Directories': {property: 'suffixTrackDirectories'}, + 'Directory Suffix': {property: 'directorySuffixForTracks'}, + 'Suffix Track Directories': {property: 'suffixTrackDirectoriesByDefault'}, 'Color': {property: 'color'}, 'Has Track Numbers': {property: 'hasTrackNumbers'}, |