Optimise
This commit is contained in:
parent
94fce03750
commit
ee0cd08cf3
10 changed files with 150 additions and 95 deletions
21
icons.js
21
icons.js
|
@ -13,4 +13,25 @@ function get(name, height = 20) {
|
|||
return utils.iconToHTML(body, attributes)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
function useTemplate(name) {
|
||||
if (Array.isArray(name)) {
|
||||
return name.map(useTemplate).join("")
|
||||
}
|
||||
const {body} = utils.iconToSVG(iconoir.icons.icons[name])
|
||||
return `<svg hidden><symbol id="n-${name}">${body}</symbol></svg>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {number} [height]
|
||||
*/
|
||||
function use(name, height = 20) {
|
||||
return `<svg width=${height} height=${height} viewBox="0 0 24 24"><use xlink:href=#n-${name} /></svg>`
|
||||
}
|
||||
|
||||
module.exports.get = get
|
||||
module.exports.useTemplate = useTemplate
|
||||
module.exports.use = use
|
||||
|
|
84
public/style.css
Normal file
84
public/style.css
Normal file
|
@ -0,0 +1,84 @@
|
|||
.ws340 {
|
||||
width: 340px;
|
||||
}
|
||||
.themed {
|
||||
--theme-base-primary-color-h: 191;
|
||||
--theme-base-primary-color-s: 37%;
|
||||
--theme-base-primary-color-l: 48%;
|
||||
--theme-dark-primary-color-h: 191;
|
||||
--theme-dark-primary-color-s: 45%;
|
||||
--theme-dark-primary-color-l: 60%;
|
||||
}
|
||||
.s-navigation--item.is-loading svg, .s-tag.is-loading svg, .s-sidebarwidget.is-loading svg {
|
||||
visibility: hidden;
|
||||
}
|
||||
.s-btn__icon.is-loading {
|
||||
--_li-offset: 0.7em;
|
||||
--_il-size: 1.5em;
|
||||
}
|
||||
.s-btn__icon.is-loading svg {
|
||||
display: none;
|
||||
}
|
||||
.s-navigation__toggle.s-navigation {
|
||||
--_na-item-bg: var(--black-150);
|
||||
}
|
||||
.duration-last-col td:last-child {
|
||||
text-align: right;
|
||||
white-space: pre;
|
||||
}
|
||||
.s-tag {
|
||||
white-space: normal;
|
||||
}
|
||||
.s-sidebarwidget th {
|
||||
font-weight: normal;
|
||||
color: var(--black-400);
|
||||
text-align: right;
|
||||
}
|
||||
.wc-hl {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
button.s-link.is-loading {
|
||||
padding-left: 2.2em;
|
||||
}
|
||||
|
||||
/* album covers are done with styles instead of attributes to reduce bytes of html needing to be downloaded and parsed */
|
||||
.cover {
|
||||
--_li-fc: var(--black);
|
||||
--_li-fc-visited: var(--black-400);
|
||||
display: block;
|
||||
}
|
||||
.cover p {
|
||||
font-size: var(--fs-body3);
|
||||
margin-top: 4px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
.cover picture {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
.cover svg {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: 1s ease-out;
|
||||
color: var(--black);
|
||||
}
|
||||
.cover:hover svg {
|
||||
transition: 1.5s ease-out 0.7s;
|
||||
opacity: 1;
|
||||
}
|
||||
.cover img {
|
||||
transition: 1s ease-out;
|
||||
}
|
||||
.cover:hover img {
|
||||
transition: 2s ease-out 0.7s;
|
||||
opacity: 0.3;
|
||||
}
|
|
@ -5,29 +5,30 @@ block title
|
|||
|
||||
block view
|
||||
.mx-auto.w100.wmx11.fs-body1#content
|
||||
!= icons.useTemplate(["star-solid", "play-solid", "music-note", "compact-disc", "people-tag", "flower"])
|
||||
.d-grid.gx8.gy12.jc-center.break-word(style="grid-template-columns: repeat(auto-fit, 210px)")
|
||||
each item in items
|
||||
div
|
||||
a.s-link.album-grid-link(href=`/api/play/${item.item_type}/${item.item_id}` hx-target="#player" hx-select="#player" hx-indicator="null" hx-push-url="false")
|
||||
.ps-relative
|
||||
a.cover(href=`/api/play/${item.item_type}/${item.item_id}` hx-target="#player" hx-select="#player" hx-indicator="null" hx-push-url="false")
|
||||
picture
|
||||
img(loading="lazy" src=item.item_art_url width=210 height=210)
|
||||
.album-grid-link__play!= icons.get("play-solid", 64)
|
||||
p.fs-body3.mb8= item.item_title
|
||||
!= icons.use("play-solid", 64)
|
||||
p= item.item_title
|
||||
.d-flex.fw-wrap.g4
|
||||
if item.why
|
||||
a.s-tag.s-tag__xs.fc-orange-400(title=item.why href=and({filter_field: "why", filter: "reviewed"}))
|
||||
!= icons.get("star-solid", 16)
|
||||
!= icons.use("star-solid", 16)
|
||||
if hasFullTrackData
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "item_id", filter: item.item_id, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("music-note", 16)
|
||||
span.s-tag--sponsor!= icons.use("music-note", 16)
|
||||
= item.track_count
|
||||
span.s-tag.s-tag__xs
|
||||
span.s-tag--sponsor!= icons.get("compact-disc", 16)
|
||||
span.s-tag--sponsor!= icons.use("compact-disc", 16)
|
||||
= item.total_duration
|
||||
a.s-tag.s-tag__xs(href=and({filter_field: "band_name", filter: item.band_name, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("people-tag", 16)
|
||||
span.s-tag--sponsor!= icons.use("people-tag", 16)
|
||||
= item.band_name
|
||||
- let label = item.band_url.replace(/https?:\/\/(.*?)\.bandcamp\.com.*/, "$1")
|
||||
a.s-tag.s-tag__xs(href=and({filter_field: "band_url", filter: label, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("flower", 16)
|
||||
span.s-tag--sponsor!= icons.use("flower", 16)
|
||||
= label
|
||||
|
|
|
@ -5,6 +5,7 @@ block title
|
|||
|
||||
block view
|
||||
.mx-auto.w100.wmx9.fs-body1#content
|
||||
!= icons.useTemplate(["flower", "compact-disc", "music-note", "album"])
|
||||
.d-flex.fd-column.g4
|
||||
each item in items
|
||||
.d-flex.g4
|
||||
|
@ -12,19 +13,19 @@ block view
|
|||
.fs-headline1= item.band_name
|
||||
.d-flex.fw-wrap.g4
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "album", filter_field: "band_name", filter: item.band_name, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("album", 16)
|
||||
span.s-tag--sponsor!= icons.use("album", 16)
|
||||
= item.album_count
|
||||
if hasFullTrackData
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "band_name", filter: item.band_name, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("music-note", 16)
|
||||
span.s-tag--sponsor!= icons.use("music-note", 16)
|
||||
= item.track_count
|
||||
span.s-tag.s-tag__xs
|
||||
span.s-tag--sponsor!= icons.get("compact-disc", 16)
|
||||
span.s-tag--sponsor!= icons.use("compact-disc", 16)
|
||||
= item.total_duration
|
||||
- let labels = item.labels.split("|").map(x => x.replace(/https?:\/\/(.*?)\.bandcamp\.com.*/, "$1"))
|
||||
each label in labels
|
||||
a.s-tag.s-tag__xs(href=and({filter_field: "band_url", filter: label, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("flower", 16)
|
||||
span.s-tag--sponsor!= icons.use("flower", 16)
|
||||
= label
|
||||
each preview in item.previews
|
||||
a.d-flex(href=`/api/play/${preview.item_type}/${preview.item_id}` hx-target="#player" hx-select="#player" hx-indicator="null" hx-push-url="false")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.s-notice.s-notice__success
|
||||
#collection-sync.s-notice.s-notice__success
|
||||
.d-flex.ai-center.gx16
|
||||
!= icons.get("check-circle")
|
||||
.fl-grow1 Imported #{storedItemCount}/#{count} purchases and #{storedTrackCount} tracks.
|
||||
|
|
|
@ -20,81 +20,11 @@ html
|
|||
title#title= title
|
||||
link(rel="icon" href="/favicon.png")
|
||||
link(rel="stylesheet" type="text/css" href="/static/stacks.min.css")
|
||||
link(rel="stylesheet" type="text/css" href="/static/style.css")
|
||||
script(src="/static/htmx.js")
|
||||
script(src="/static/wordcloud.js")
|
||||
script(defer src="/static/player-marker.js")
|
||||
meta(name="htmx-config" content='{"requestClass":"is-loading"}')
|
||||
style.
|
||||
.ws340 {
|
||||
width: 340px;
|
||||
}
|
||||
.themed {
|
||||
--theme-base-primary-color-h: 191;
|
||||
--theme-base-primary-color-s: 37%;
|
||||
--theme-base-primary-color-l: 48%;
|
||||
--theme-dark-primary-color-h: 191;
|
||||
--theme-dark-primary-color-s: 45%;
|
||||
--theme-dark-primary-color-l: 60%;
|
||||
}
|
||||
.s-navigation--item.is-loading svg, .s-tag.is-loading svg, .s-sidebarwidget.is-loading svg {
|
||||
visibility: hidden;
|
||||
}
|
||||
.s-btn__icon.is-loading {
|
||||
--_li-offset: 0.7em;
|
||||
--_il-size: 1.5em;
|
||||
}
|
||||
.s-btn__icon.is-loading svg {
|
||||
display: none;
|
||||
}
|
||||
.s-navigation__toggle.s-navigation {
|
||||
--_na-item-bg: var(--black-150);
|
||||
}
|
||||
.duration-last-col td:last-child {
|
||||
text-align: right;
|
||||
white-space: pre;
|
||||
}
|
||||
.s-tag {
|
||||
white-space: normal;
|
||||
}
|
||||
.s-sidebarwidget th {
|
||||
font-weight: normal;
|
||||
color: var(--black-400);
|
||||
text-align: right;
|
||||
}
|
||||
.album-grid-link {
|
||||
--_li-fc: var(--black);
|
||||
--_li-fc-visited: var(--black-400);
|
||||
display: block;
|
||||
}
|
||||
.album-grid-link__play {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
color: #000;
|
||||
opacity: 0;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: 1s ease-out;
|
||||
}
|
||||
.album-grid-link img {
|
||||
transition: 1s ease-out;
|
||||
}
|
||||
.album-grid-link:hover img {
|
||||
transition: 2s ease-out 0.7s;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.album-grid-link:hover .album-grid-link__play {
|
||||
transition: 2s ease-out 0.7s;
|
||||
opacity: 1;
|
||||
}
|
||||
.wc-hl {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
body.themed.theme-system.overflow-y-scroll(hx-boost="true" hx-swap="outerHTML" hx-target="#page" hx-select="#page")
|
||||
#page(hx-history-elt)
|
||||
header.s-topbar.ps-sticky.t0
|
||||
|
@ -122,7 +52,7 @@ html
|
|||
main.fl-grow1
|
||||
block view
|
||||
|
||||
aside.ws340
|
||||
aside.ws340.fl-shrink0
|
||||
.ps-fixed.ws340.d-flex.fd-column.g12(style="top: 80px")
|
||||
if arrange === "tag"
|
||||
include tag-status.pug
|
||||
|
@ -147,8 +77,14 @@ html
|
|||
|
||||
#player-marker.pe-none(style="display: none")
|
||||
|
||||
#collection-sync.d-none
|
||||
|
||||
.s-sidebarwidget
|
||||
.s-sidebarwidget--header Collection
|
||||
.s-sidebarwidget--action
|
||||
input(type="hidden" name="account" value=account)
|
||||
button.s-link(hx-post="/api/load-collection" hx-target="#collection-sync" hx-select="#collection-sync" hx-include="previous input") Sync
|
||||
|
||||
table.s-sidebarwidget--content.s-sidebarwidget__items
|
||||
tr.s-sidebarwidget--item
|
||||
th items
|
||||
|
|
|
@ -5,6 +5,7 @@ block title
|
|||
|
||||
block view
|
||||
.mx-auto.w100.wmx9.fs-body1#content
|
||||
!= icons.useTemplate(["album", "people-tag", "music-note", "compact-disc"])
|
||||
.d-flex.fd-column.g4
|
||||
each item in items
|
||||
.d-flex.g4
|
||||
|
@ -14,17 +15,17 @@ block view
|
|||
.fs-headline1= label
|
||||
.d-flex.fw-wrap.g4
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "album", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("album", 16)
|
||||
span.s-tag--sponsor!= icons.use("album", 16)
|
||||
= item.album_count
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "artist", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("people-tag", 16)
|
||||
= item.artist_count
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "artist", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.use("people-tag", 16)
|
||||
= item.artist_count
|
||||
if hasFullTrackData
|
||||
a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null}))
|
||||
span.s-tag--sponsor!= icons.get("music-note", 16)
|
||||
span.s-tag--sponsor!= icons.use("music-note", 16)
|
||||
= item.track_count
|
||||
span.s-tag.s-tag__xs
|
||||
span.s-tag--sponsor!= icons.get("compact-disc", 16)
|
||||
span.s-tag--sponsor!= icons.use("compact-disc", 16)
|
||||
= item.total_duration
|
||||
each preview in item.previews
|
||||
a.d-flex(href=`/api/play/${preview.item_type}/${preview.item_id}` hx-target="#player" hx-select="#player" hx-indicator="null" hx-push-url="false")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#player
|
||||
.s-sidebarwidget(style="overflow: hidden")
|
||||
div(style="margin: -1px; margin-bottom: -11px").ps-relative
|
||||
a.ps-absolute.bg-white.bar0.t0.r0.s-btn.s-btn__icon.s-btn__muted.s-btn__sm.px12(href=`/api/play/${item_type}/${item_id}` hx-target="#player" hx-select="#player" hx-push-url="false").fc-theme-primary!= icons.get("refresh-double", 18)
|
||||
a.ps-absolute.bg-white.bar0.t0.r0.s-btn.s-btn__icon.s-btn__muted.s-btn__sm.px12(href=`/api/play/${item_type}/${item_id}` hx-target="#player" hx-select="#player" hx-push-url="false" title="reload embedded player").fc-theme-primary!= icons.get("refresh-double", 18)
|
||||
iframe(style="border: 0; width: 100%; height: 424px;" src=`https://bandcamp.com/EmbeddedPlayer/${item_type}=${item_id}/size=large/bgcol=ffffff/linkcol=63b2cc/artwork=none/transparent=true/track=${track_id}`)
|
||||
|
|
|
@ -14,7 +14,10 @@ const schema = z.object({
|
|||
track_id: z.number({coerce: true}).optional()
|
||||
})
|
||||
|
||||
router.get("/api/play/:item_type/:item_id/:track_id", defineEventHandler(async event => {
|
||||
const play = defineEventHandler(async event => {
|
||||
const locals = await getValidatedRouterParams(event, schema.parse)
|
||||
return pugSync.render(event, "player.pug", locals)
|
||||
}))
|
||||
})
|
||||
|
||||
router.get("/api/play/:item_type/:item_id/", play)
|
||||
router.get("/api/play/:item_type/:item_id/:track_id", play)
|
||||
|
|
8
start.js
8
start.js
|
@ -49,6 +49,14 @@ router.get("/static/stacks.min.css", defineEventHandler({
|
|||
}
|
||||
}))
|
||||
|
||||
router.get("/static/style.css", defineEventHandler({
|
||||
onBeforeResponse: pugSync.compressResponse,
|
||||
handler: async event => {
|
||||
defaultContentType(event, "text/css")
|
||||
return fs.promises.readFile("public/style.css", "utf-8")
|
||||
}
|
||||
}))
|
||||
|
||||
router.get("/static/htmx.js", defineEventHandler({
|
||||
onBeforeResponse: pugSync.compressResponse,
|
||||
handler: async event => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue