« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/content/dependencies/generateAlbumArtInfoBox.js118
-rw-r--r--src/content/dependencies/generateArtistGroupContributionsInfo.js84
-rw-r--r--src/content/dependencies/generateCoverGrid.js2
-rw-r--r--src/static/css/features.css24
-rw-r--r--src/static/css/search.css9
-rw-r--r--src/strings-default.yaml16
6 files changed, 178 insertions, 75 deletions
diff --git a/src/content/dependencies/generateAlbumArtInfoBox.js b/src/content/dependencies/generateAlbumArtInfoBox.js
index 5491192a..a3b4c02d 100644
--- a/src/content/dependencies/generateAlbumArtInfoBox.js
+++ b/src/content/dependencies/generateAlbumArtInfoBox.js
@@ -1,3 +1,7 @@
+import {basename} from 'node:path';
+
+import {empty} from '#sugar';
+
 export default {
   relations: (relation, album) => ({
     wallpaperArtistContributionsLine:
@@ -11,26 +15,100 @@ export default {
         ? relation('generateReleaseInfoContributionsLine',
             album.bannerArtwork.artistContribs)
         : null),
+
+    linkTemplate:
+      relation('linkTemplate'),
   }),
 
-  generate: (relations, {html, language}) =>
-    language.encapsulate('releaseInfo', capsule =>
-      html.tag('div', {class: 'album-art-info'},
-        {[html.onlyIfContent]: true},
-
-        html.tag('p',
-          {[html.onlyIfContent]: true},
-          {[html.joinChildren]: html.tag('br')},
-
-          [
-            relations.wallpaperArtistContributionsLine?.slots({
-              stringKey: capsule + '.wallpaperArtBy',
-              chronologyKind: 'wallpaperArt',
-            }),
-
-            relations.bannerArtistContributionsLine?.slots({
-              stringKey: capsule + '.bannerArtBy',
-              chronologyKind: 'bannerArt',
-            }),
-          ]))),
+  data: (album) => ({
+    wallpaperImagePath:
+      (album.wallpaperArtwork && empty(album.wallpaperParts)
+        ? album.wallpaperArtwork.path
+        : null),
+
+    wallpaperPartPaths:
+      album.wallpaperParts
+        .filter(part => part.asset)
+        .map(part => ['media.albumWallpaperPart', album.directory, part.asset]),
+
+    bannerImagePath:
+      (album.bannerArtwork
+        ? album.bannerArtwork.path
+        : null),
+  }),
+
+  generate: (data, relations, {html, language}) =>
+    html.tag('div', {class: 'album-art-info'},
+      {[html.onlyIfContent]: true},
+      {[html.joinChildren]: html.tag('hr', {class: 'cute'})},
+
+      [
+        language.encapsulate('releaseInfo', capsule =>
+          html.tag('p',
+            {[html.onlyIfContent]: true},
+            {[html.joinChildren]: html.tag('br')},
+
+            [
+              relations.wallpaperArtistContributionsLine?.slots({
+                stringKey: capsule + '.wallpaperArtBy',
+                chronologyKind: 'wallpaperArt',
+              }),
+
+              relations.bannerArtistContributionsLine?.slots({
+                stringKey: capsule + '.bannerArtBy',
+                chronologyKind: 'bannerArt',
+              }),
+            ])),
+
+        language.encapsulate('misc.downloadLayoutMedia', downloadCapsule =>
+          html.tag('p',
+            {[html.onlyIfContent]: true},
+            {[html.joinChildren]: html.tag('br')},
+
+            [
+              language.encapsulate(downloadCapsule, workingCapsule => {
+                const workingOptions = {};
+
+                let any = false;
+
+                if (data.wallpaperImagePath) {
+                  any = true;
+                  workingCapsule += '.withWallpaper';
+                  workingOptions.wallpaper =
+                    relations.linkTemplate.clone().slots({
+                      path: data.wallpaperImagePath,
+                      content: language.$(downloadCapsule, 'wallpaper'),
+                    });
+                }
+
+                if (data.bannerImagePath) {
+                  any = true;
+                  workingCapsule += '.withBanner';
+                  workingOptions.banner =
+                    relations.linkTemplate.clone().slots({
+                      path: data.bannerImagePath,
+                      content: language.$(downloadCapsule, 'banner'),
+                    });
+                }
+
+                if (any) {
+                  return language.$(workingCapsule, workingOptions);
+                } else {
+                  return html.blank();
+                }
+              }),
+
+              language.$(downloadCapsule, 'withWallpaperParts', {
+                [language.onlyIfOptions]: ['parts'],
+
+                parts:
+                  language.formatUnitList(
+                    data.wallpaperPartPaths.map(path =>
+                      relations.linkTemplate.clone().slots({
+                        path,
+                        content: language.sanitize(basename(path.at(-1))),
+                      }))),
+              }),
+            ])),
+      ]),
 };
diff --git a/src/content/dependencies/generateArtistGroupContributionsInfo.js b/src/content/dependencies/generateArtistGroupContributionsInfo.js
index 6940053f..72ce0944 100644
--- a/src/content/dependencies/generateArtistGroupContributionsInfo.js
+++ b/src/content/dependencies/generateArtistGroupContributionsInfo.js
@@ -195,50 +195,46 @@ export default {
               : slots.title))),
 
         html.tag('dd', {class: topLevelClasses},
-          html.tag('ul', {class: 'group-contributions-table'},
-            {role: 'list'},
-
-            (slots.sort === 'count'
-              ? stitchArrays({
-                  group: relations.groupLinksSortedByCount,
-                  count: getCounts(data.groupCountsSortedByCount),
-                  duration:
-                    getDurations(
-                      data.groupDurationsSortedByCount,
-                      data.groupDurationsApproximateSortedByCount),
-                }).map(({group, count, duration}) =>
-                    language.encapsulate(capsule, 'item', capsule =>
-                      html.tag('li',
-                        html.tag('div', {class: 'group-contributions-row'}, [
-                          group,
-                          html.tag('span', {class: 'group-contributions-metrics'},
-                            // When sorting by count, duration details aren't necessarily
-                            // available for all items.
-                            (slots.showBothColumns && duration
-                              ? language.$(capsule, 'countDurationAccent', {count, duration})
-                              : language.$(capsule, 'countAccent', {count}))),
-                        ]))))
-
-              : stitchArrays({
-                  group: relations.groupLinksSortedByDuration,
-                  count: getCounts(data.groupCountsSortedByDuration),
-                  duration:
-                    getDurations(
-                      data.groupDurationsSortedByDuration,
-                      data.groupDurationsApproximateSortedByDuration),
-                }).map(({group, count, duration}) =>
-                    language.encapsulate(capsule, 'item', capsule =>
-                      html.tag('li',
-                        html.tag('div', {class: 'group-contributions-row'}, [
-                          group,
-                          html.tag('span', {class: 'group-contributions-metrics'},
-                            // Count details are always available, since they're just the
-                            // number of contributions directly. And duration details are
-                            // guaranteed for every item when sorting by duration.
-                            (slots.showBothColumns
-                              ? language.$(capsule, 'durationCountAccent', {duration, count})
-                              : language.$(capsule, 'durationAccent', {duration}))),
-                        ]))))))),
+          html.tag('table', {class: 'group-contributions-table'},
+            (stitchArrays(
+              (slots.sort === 'count'
+                ? {
+                    group: relations.groupLinksSortedByCount,
+                    count: getCounts(data.groupCountsSortedByCount),
+                    duration:
+                      getDurations(
+                        data.groupDurationsSortedByCount,
+                        data.groupDurationsApproximateSortedByCount),
+                  }
+                : {
+                    group: relations.groupLinksSortedByDuration,
+                    count: getCounts(data.groupCountsSortedByDuration),
+                    duration:
+                      getDurations(
+                        data.groupDurationsSortedByDuration,
+                        data.groupDurationsApproximateSortedByDuration),
+                  })
+            )).map(({group, count, duration}) =>
+                language.encapsulate(capsule, 'item', capsule =>
+                  html.tag('tr', [
+                    html.tag('td', {class: 'group-contributions-link-cell'},
+                      html.tag('span', group)),
+
+                    html.tag('td', {class: 'group-contributions-metrics-cell'},
+                      (slots.sort === 'count'
+                          // When sorting by count, duration details aren't necessarily
+                          // available for all items.
+                        ? (slots.showBothColumns && duration
+                            ? language.$(capsule, 'countDurationAccent', {count, duration})
+                            : language.$(capsule, 'countAccent', {count}))
+
+                          // Count details are always available, since they're just the
+                          // number of contributions directly. And duration details are
+                          // guaranteed for every item when sorting by duration.
+                        : (slots.showBothColumns
+                            ? language.$(capsule, 'durationCountAccent', {duration, count})
+                            : language.$(capsule, 'durationAccent', {duration})))),
+                  ]))))),
       ]);
     }),
 };
diff --git a/src/content/dependencies/generateCoverGrid.js b/src/content/dependencies/generateCoverGrid.js
index 091833a9..6f87b54c 100644
--- a/src/content/dependencies/generateCoverGrid.js
+++ b/src/content/dependencies/generateCoverGrid.js
@@ -187,7 +187,7 @@ export default {
 
        : !html.isBlank(relations.bottomCaption)
           ? html.tag('p', {class: 'grid-caption'},
-              slots.caption)
+              slots.bottomCaption)
 
           : html.blank()),
       ]),
diff --git a/src/static/css/features.css b/src/static/css/features.css
index c811c753..410bf5b9 100644
--- a/src/static/css/features.css
+++ b/src/static/css/features.css
@@ -566,7 +566,8 @@
   }
 
   #artwork-column .album-art-info {
-    margin: 10px min(15px, 1vw) 15px;
+    margin: 10px min(15px, 1vw) 18px;
+    z-index: 2;
   }
 
   #artwork-column .cover-artwork:not(:first-child),
@@ -1218,21 +1219,26 @@
   }
 }
 
-/* Group-contributions tables */
+/* Group contributions tables */
 
 @layer layout {
   .group-contributions-table {
-    display: inline-block;
+    margin-left: 40px;
+    border-collapse: collapse;
   }
 
-  .group-contributions-table .group-contributions-row {
-    display: flex;
-    justify-content: space-between;
+  .group-contributions-table td {
+    padding: 0 0 4px 0;
   }
 
-  .group-contributions-table .group-contributions-metrics {
-    margin-left: 1.5ch;
+  .group-contributions-table .group-contributions-link-cell {
+    display: list-item;
+  }
+
+  .group-contributions-table .group-contributions-metrics-cell {
+    padding-left: 1.5ch;
     white-space: nowrap;
+    text-align: right;
   }
 }
 
@@ -1954,7 +1960,7 @@
     /* Slight stretching past the bottom of the screen seems
      * to make resizing the window (and "revealing" that area)
      * a bit smoother.
-     */
+     *....../
     position: fixed;
     bottom: -20px;
     left: 0;
diff --git a/src/static/css/search.css b/src/static/css/search.css
index 3c56eed6..409e12df 100644
--- a/src/static/css/search.css
+++ b/src/static/css/search.css
@@ -49,10 +49,17 @@
 }
 
 @layer interaction {
-  .wiki-search-sidebar-box.showing-results ~ .sidebar:not(:hover) {
+  .wiki-search-sidebar-box.showing-results ~ .sidebar:not(:hover),
+  .wiki-search-sidebar-box.showing-results ~ .sidebar-box-joiner {
     opacity: 0.8;
     filter: brightness(0.85);
   }
+
+  .wiki-search-sidebar-box.showing-results ~ .sidebar:hover + .sidebar-box-joiner,
+  .wiki-search-sidebar-box.showing-results ~ .sidebar-box-joiner:has(+ .sidebar:hover) {
+    opacity: revert-layer;
+    filter: revert-layer;
+  }
 }
 
 /* Label and input elements */
diff --git a/src/strings-default.yaml b/src/strings-default.yaml
index ed8f236f..9868745c 100644
--- a/src/strings-default.yaml
+++ b/src/strings-default.yaml
@@ -639,6 +639,22 @@ misc:
     cue: "Crediting sources"
     sticky: "Crediting sources:"
 
+  downloadLayoutMedia:
+    withWallpaper: >-
+      Wiki files: {WALLPAPER}
+
+    withBanner: >-
+      Wiki files: {BANNER}
+
+    withWallpaper.withBanner: >-
+      Wiki files: {WALLPAPER}, {BANNER}
+
+    withWallpaperParts: >-
+      Wallpaper: {PARTS}
+
+    wallpaper: "Wallpaper"
+    banner: "Banner"
+
   # external:
   #   Links which will generally bring you somewhere off of the wiki.
   #   The list of sites is hard-coded into the wiki software, so it