Multiple accounts support, load tags online

This commit is contained in:
Cadence Ember 2025-04-02 17:03:03 +13:00
parent cd2827791f
commit 26ea869285
14 changed files with 295 additions and 124 deletions

View file

@ -20,5 +20,5 @@ block view
= 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}))
span.s-tag--sponsor!= icons.get("component", 16)
span.s-tag--sponsor!= icons.get("flower", 16)
= label

View file

@ -20,7 +20,7 @@ block view
- 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}))
span.s-tag--sponsor!= icons.get("component", 16)
span.s-tag--sponsor!= icons.get("flower", 16)
= label
each preview in item.previews
a.d-flex(href=preview.item_url)

20
pug/home.pug Normal file
View file

@ -0,0 +1,20 @@
doctype html
html
head
meta(charset="utf-8")
<meta name="viewport" content="width=device-width, initial-scale=1" />
title BC Explorer
link(rel="stylesheet" type="text/css" href="/static/stacks.min.css")
body.themed.theme-system.overflow-y-scroll
header.s-topbar.ps-sticky.t0
.s-topbar--container.wmx9
.s-topbar--logo
!= icons.get("compass-solid", 24)
.ml4 BC Explorer
.mx-auto.wmx9.py24.px16.g24.s-prose
h1 Select profile
- const names = select("account", "account").pluck().all()
ul
each name in names
li: a(href=`/${name}/`)= name

View file

@ -63,14 +63,15 @@ html
ul.s-navigation
li: +navi("arrange", "album", "album", "Album")
li: +navi("arrange", "artist", "people-tag", "Artist")
li: +navi("arrange", "label", "component", "Label")
li: +navi("arrange", "label", "flower", "Label")
//- asana, flower, component, circle-spark, rhombus, sphere, union-alt, color-wheel, community, combine
li: +navi("arrange", "tag", "label", "Tag")
li: +navi("arrange", "track", "music-note", "Track")
.px16
nav
ul.s-navigation.s-navigation__toggle.g0
li: +navi("shape", "grid").brr0!= icons.get("view-grid")
li: +navi("shape", "list").blr0!= icons.get("table-rows")
li: +navi("shape", "list").blr0!= icons.get("align-justify")
.fl-grow1
#player(hx-preserve)
button.s-btn.s-btn__outlined.s-btn__xs!= icons.get("play")
@ -80,12 +81,17 @@ html
block view
div
.ps-sticky.d-flex.fd-column.g12(style="top: 80px")
.ps-sticky.d-flex.fd-column.g12.wmx4(style="top: 80px")
if arrange === "tag"
include tag-status.pug
if filter
.s-sidebarwidget.s-sidebarwidget__blue.d-flex.ai-center.gx16.jc-space-between.p8.pl16
!= icons.get("search")
div Searching for #[strong= filter]
.fl-grow1
.fl-shrink0!= icons.get("search")
.fl-grow1= `Searching for `
if filter_field === "item_id"
strong= items[0].item_title
else
strong= filter
a.s-btn.s-notice--btn(href=and({filter: null, filter_field: null})) Clear
.s-sidebarwidget.wmn3
.s-sidebarwidget--header Collection

View file

@ -0,0 +1,32 @@
if downloader.total > 0
.d-flex.jc-center#tag-download
if !downloader.running && !downloader.outcome
form.s-notice.s-notice__info.d-flex.ai-center.p8.gx16.pl16(role="status" hx-swap="outerHTML" hx-target="#tag-download" hx-post="/api/tag-download")
!= icons.get("info-circle")
div Tag data needs to be downloaded. This will take a while.
input(type="hidden" name="account" value=account)
button.s-btn.s-btn__outlined Download now
else if !downloader.outcome
.s-notice.p16(role="status" hx-swap="outerHTML" hx-target="#tag-download" hx-get=`/api/tag-download?account=${account}` hx-trigger="every 5s")
.d-flex.gx16.ai-center
!= icons.get("cloud-download")
div Downloading tags...
p.mt12 You can keep using BC Explorer while this continues in the background.
.s-progress.mt16
.s-progress--bar(style=`width: ${downloader.processed/downloader.total*100}%`)
.d-flex.jc-space-between.fs-fine
span= downloader.processed
span= downloader.total
else if downloader.outcome === "Success"
.s-notice.s-notice__success.p8.gx16.pl16.d-flex.ai-center.wmn3
!= icons.get("cloud-check")
.fl-grow1 Tags downloaded.
- downloadManager.resolve(account)
a.s-btn.s-btn__outlined(href="") Refresh
else
.s-notice.s-notice__danger.p8.gx16.pl16.d-flex.ai-center.wmn3
!= icons.get("cloud-xmark")
.fl-grow1= downloader.outcome

View file

@ -4,46 +4,42 @@ block view
script
| var items =
!= JSON.stringify(items)
| ; var filter_field =
!= JSON.stringify(filter_field || null)
.mx-auto.w100.wmx11.fs-body1
if !items.length
.d-flex.jc-center
.s-notice.d-flex.ai-center.p8.gx16.pl16(role="status")
!= icons.get("info-circle")
div Tag data needs to be downloaded. This will take a while.
button.s-btn.s-btn__outlined Download now
#content(style="cursor: default")
script.
setTimeout(() => {
const content = document.getElementById("content")
content.style.height = `${Math.round(Math.min(content.clientWidth, window.innerHeight)*0.8)}px`
const dark = window.matchMedia?.("(prefers-color-scheme: dark)").matches
WordCloud(content, {
list: items,
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif',
fontWeight: "bold",
color: dark ? "random-light": "random-dark",
minSize: 4,
gridSize: Math.round(content.clientWidth / 200),
weightFactor: size => size * content.clientWidth / 180,
rotateRatio: 0,
click: item => {
const highlightedItem = document.querySelector(".wc-hl")?.textContent || item[0]
const newURL = new URL(location)
newURL.searchParams.set("filter", highlightedItem)
newURL.searchParams.set("filter_field", "tag")
newURL.searchParams.set("arrange", "label")
location = newURL
}
.word-cloud(style="cursor: default")
script.
setTimeout(() => {
const content = document.querySelector(".word-cloud")
content.style.height = `${Math.round(Math.min(content.clientWidth, window.innerHeight)*0.8)}px`
const dark = window.matchMedia?.("(prefers-color-scheme: dark)").matches
WordCloud(content, {
list: items,
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif',
fontWeight: "bold",
color: dark ? "random-light": "random-dark",
minSize: 4,
gridSize: Math.round(content.clientWidth / 200),
weightFactor: size => size * content.clientWidth / 180,
rotateRatio: 0,
click: item => {
const highlightedItem = document.querySelector(".wc-hl")?.textContent || item[0]
const newURL = new URL(location)
newURL.searchParams.set("filter", highlightedItem)
newURL.searchParams.set("filter_field", "tag")
newURL.searchParams.set("arrange", filter_field ? "album" : "label")
location = newURL
}
})
content.style.background = "none"
content.addEventListener("wordcloudstop", () => {
for (const child of content.children) {
child.addEventListener("mouseenter", () => {
child.classList.add("wc-hl")
})
child.addEventListener("mouseleave", () => {
child.classList.remove("wc-hl")
})
}
})
})
content.addEventListener("wordcloudstop", () => {
for (const child of content.children) {
child.addEventListener("mouseenter", () => {
child.classList.add("wc-hl")
})
child.addEventListener("mouseleave", () => {
child.classList.remove("wc-hl")
})
}
})
})