Compare commits
No commits in common. "8dc24a77637ffd56924d75e8189e963bcaa016d1" and "199a44a8a7102fdd6ca912d7c2f10f834b61cefb" have entirely different histories.
8dc24a7763
...
199a44a8a7
8 changed files with 11 additions and 102 deletions
|
@ -24,9 +24,6 @@
|
|||
.s-navigation--item.is-loading svg, .s-tag.is-loading svg, .s-sidebarwidget.is-loading svg {
|
||||
visibility: hidden;
|
||||
}
|
||||
.s-btn.is-loading:not(.s-btn__icon) svg {
|
||||
display: none;
|
||||
}
|
||||
.s-btn__icon.is-loading {
|
||||
--_li-offset: 0.7em;
|
||||
--_il-size: 1.5em;
|
||||
|
|
38
pug/home.pug
38
pug/home.pug
|
@ -42,52 +42,26 @@ html
|
|||
p.fs-fine (you #[em should] download every mp3, though, because the Bandcamp TOS says they can take away your online access at any time)
|
||||
|
||||
h2 Why?
|
||||
p
|
||||
| I mainly wanted to arrange my collection as labels instead of album covers. I've bought music from a variety of artists, but it's hard to find all of them amidst the enormous backlogs from
|
||||
|
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?filter=Singto+Conley&filter_field=band_name&arrange=album&shape=grid")
|
||||
span.s-tag--sponsor!= icons.get("people-tag", 18)
|
||||
| Singto Conley
|
||||
|
|
||||
| and
|
||||
|
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?filter=lostfrog&filter_field=band_url&arrange=album&shape=grid")
|
||||
span.s-tag--sponsor!= icons.get("flower", 18)
|
||||
| Lost Frog Productions
|
||||
| . Giving each label the same amount of space makes my collection more fun to browse because I'm not scrolling past the same things over and over again.
|
||||
p I mainly wanted to arrange my collection as labels instead of album covers. I've bought music from a variety of artists, but it's hard to find all of them amidst the enormous backlogs from Singto Conley and Lost Frog Productions. Giving each label the same amount of space makes my collection more fun to browse because I'm not scrolling past the same things over and over again.
|
||||
p It's also faster to browse through because there's no "load more", everything shows up instantly.
|
||||
p I also wanted as many different facets as possible for browsing my collection: albums, artists, labels, and tags. I want to be able to jump from one place to another. What else has this artist produced? Who has produced music in these tags? What else have I written reviews for?
|
||||
p Skimming your collection is easy because there's no "load more", everything shows up instantly. The inline music player sticks around while you keep exploring.
|
||||
|
||||
h2 Tips and tricks
|
||||
p
|
||||
| All the little tags under things, like
|
||||
|
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?arrange=album&shape=grid&filter_field=band_url&filter=overheaven")
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?account=cloudrac3r&arrange=album&shape=grid&filter_field=band_url&filter=overheaven")
|
||||
span.s-tag--sponsor!= icons.get("album", 18)
|
||||
| 39
|
||||
|
|
||||
| the number of albums, or
|
||||
|
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?arrange=artist&shape=grid&filter_field=band_url&filter=lostfrog")
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?account=cloudrac3r&arrange=artist&shape=grid&filter_field=band_url&filter=lostfrog")
|
||||
span.s-tag--sponsor!= icons.get("people-tag", 18)
|
||||
| 92
|
||||
|
|
||||
| the artists in a label, are clickable. If you click them it applies a filter and switches tabs to show you who they are.
|
||||
p
|
||||
| While having a filter active, you can click the tabs at the top to use the same filter in a different facet. For example, you can go to the
|
||||
|
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?arrange=tag&shape=grid")
|
||||
span.s-tag--sponsor!= icons.get("label", 18)
|
||||
| tag cloud
|
||||
| , search "breakcore", click it to see all the
|
||||
|
|
||||
a.s-tag.s-tag__sm.bg-black-200(href="/cloudrac3r/?filter=breakcore&filter_field=tag&filter_fuzzy=true&arrange=album&shape=grid")
|
||||
span.s-tag--sponsor!= icons.get("album", 18)
|
||||
| breakcore
|
||||
|
|
||||
| albums - there's a lot, right? Yes, but it's not because I'm enthusiastic about breakcore. From that page, switch to the labels tab. Turns out most of it's just from the same label, so there's not much diversity there.
|
||||
p While having a filter active, you can click the tabs at the top to use the same filter in a different facet. For example, you can go to the #[a(href="/cloudrac3r/?arrange=tag&shape=grid") tag cloud], search "breakcore", click it to #[a(href="/cloudrac3r/?filter=breakcore&filter_field=tag&filter_fuzzy=true&arrange=album&shape=grid") see all the breakcore albums] - there's a lot, right? Yes, but it's not because I'm enthusiastic about breakcore. Switch to #[a(href="/cloudrac3r/?filter=breakcore&filter_field=tag&arrange=label&shape=grid") the labels view]. Most of the breakcore is just from the same label, so there's not actually much diversity there.
|
||||
p The tag cloud view takes this diversity into account automatically. Everything is grouped by label before being counted, to ensure that a large backlog from a single label does not take up an unworthy amount of "space" and crowd out the other singles that you're quite fond of. It's the same with the statistics heat bar. If you have #[a(href="http://localhost:2239/cloudrac3r/?arrange=album&shape=grid&filter_field=band_url&filter=louiezong") all of Louie Zong's albums], they'll only count for one red hot entry rather than over 150 entries.
|
||||
p Don't take the statistics too seriously! Some are a bit silly, like lonely tags, which are tags that only exist on a single item in your collection. Some are best guesses, like monetary value, which doesn't know if you chose to pay more than the minimum price or paid less via a discography discount or album code. Some are just for fun, like diversity, which shows whether you prefer popular or unpopular labels. Each label is one slot in the bar and it gets a hotter colour if it's more popular. Popularity is measured by the average number of other people who bought the same items as you.
|
||||
p Oh, and there's an inline music player which sticks around while you keep exploring.
|
||||
|
||||
footer.mt32.d-flex.fw-wrap.gx8.ai-center
|
||||
a(href="https://cadence.moe") Created by Cadence
|
||||
|
|
|
@ -63,19 +63,3 @@
|
|||
.s-progress--bar.bg-yellow-400(title=`${count.taste[1]} labels with 20-199 fans`)= count.taste[1]
|
||||
.s-progress--bar.bg-orange-400(title=`${count.taste[2]} labels with 200-1999 fans`)= count.taste[2]
|
||||
.s-progress--bar.bg-red-400(title=`${count.taste[3]} labels with >2000 fans`)= count.taste[3]
|
||||
tr.s-sidebarwidget--item
|
||||
th currency
|
||||
td.w100
|
||||
- var totalLabels = count.currencies.reduce((a, c) => a + c[1], 0)
|
||||
- var palette = ["red", "orange", "green", "blue", "purple", "bronze"]
|
||||
- var i = 0
|
||||
.s-progress.d-grid.g2.h4.mtn6(style=`grid-template-columns: ${count.currencies.map(t => t[1] + "fr").join(" ")}`).bg-white.fc-black-400.fs-fine.lh-xxl
|
||||
each c in count.currencies
|
||||
.s-progress--bar.wmn-initial(title=`bought from ${c[1]} labels with ${c[0]}` class=`fc-${palette[i]}-400 bg-${palette[i++]}-400`)
|
||||
- if (i >= palette.length) i = 0
|
||||
if c[1] / totalLabels >= 0.08
|
||||
= c[0]
|
||||
else if c[1] / totalLabels >= 0.06
|
||||
= c[0].slice(0, 2)
|
||||
else
|
||||
= c[0][0]
|
||||
|
|
|
@ -45,15 +45,6 @@ html
|
|||
.ml6 Switch account
|
||||
li.s-menu--divider(role="separator")
|
||||
li.s-menu--title Settings
|
||||
if query && query.show
|
||||
li(role="menuitem")
|
||||
.s-block-link.d-flex.ai-center.py2
|
||||
span.fl-grow1.d-flex.ai-center
|
||||
!= icons.get("eye")
|
||||
.pl6 Showing all items
|
||||
a.s-btn.s-btn__filled.s-btn__sm.d-flex.ai-center(href=and({show: null}))
|
||||
!= icons.get("undo", 16)
|
||||
span.pl6 Undo
|
||||
li(role="menuitem")
|
||||
if arrange === "tag"
|
||||
form.s-block-link.d-flex.ai-center(hx-post="/api/settings/location-tags" hx-trigger="change" hx-indicator="#location-tags-loading" hx-select="#tag-page" hx-target="#tag-page")
|
||||
|
@ -153,9 +144,6 @@ html
|
|||
include collection-stats.pug
|
||||
|
||||
main.fl-grow1
|
||||
if items && items.length >= 1000
|
||||
//- a great deal of performance is spent on htmx's bfcache emulation when navigating away from large pages
|
||||
div(hx-history="false")
|
||||
block view
|
||||
|
||||
#player-container.ps-fixed.r16.ws340.z-modal(class="md:t64 md:l16 md:r16 md:b16" hx-preserve="true")
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
extends includes/layout.pug
|
||||
|
||||
block view
|
||||
.mx-auto.w100.wmx11.fs-body1.d-flex.jc-center#content
|
||||
.s-notice.s-notice__warning
|
||||
.d-flex.gx16.ai-center
|
||||
!= icons.get("warning-triangle")
|
||||
div This page has #{itemCount} items, which might slow down your browser.
|
||||
.d-flex.gx8.mt16
|
||||
button.s-btn.s-btn__filled(hx-get=and({}) hx-headers='{"BCEX-Show": "true"}') Show them anyway
|
||||
a.s-btn.s-btn__outlined(href=and({show: true})) Always show
|
||||
p.mt16 Other things to try:
|
||||
ul.mb4
|
||||
li Search for specific items
|
||||
if arrange !== "label"
|
||||
li View items grouped together, like the #[a(href=and({arrange: "label"})) labels tab]
|
||||
li Use #[a(href=and({shape: "list"}) hx-headers='{"BCEX-Show": "true"}') list view], which may be faster
|
|
@ -1,6 +1,6 @@
|
|||
// @ts-check
|
||||
|
||||
const {defineEventHandler, getQuery, getValidatedQuery, sendRedirect, createError, getValidatedRouterParams, getCookie, getRequestHeader} = require("h3")
|
||||
const {defineEventHandler, getQuery, getValidatedQuery, sendRedirect, createError, getValidatedRouterParams, getCookie} = require("h3")
|
||||
const {router, db, sync} = require("../passthrough")
|
||||
|
||||
/** @type {import("../pug-sync")} */
|
||||
|
@ -73,7 +73,7 @@ router.get("/:account/", defineEventHandler({
|
|||
handler: async event => {
|
||||
const {account} = await getValidatedRouterParams(event, schema.schema.account.parse)
|
||||
try {
|
||||
var {arrange, shape, filter, filter_field, filter_fuzzy, show} = await getValidatedQuery(event, schema.schema.appQuery.parse)
|
||||
var {arrange, shape, filter, filter_field, filter_fuzzy} = await getValidatedQuery(event, schema.schema.appQuery.parse)
|
||||
if (filter_field === "why" && arrange !== "album") throw new Error("filter not compatible with arrangement")
|
||||
} catch (e) {
|
||||
return sendRedirect(event, "?arrange=album&shape=grid", 302)
|
||||
|
@ -125,12 +125,6 @@ router.get("/:account/", defineEventHandler({
|
|||
throw e
|
||||
}
|
||||
|
||||
show ||= getRequestHeader(event, "BCEX-Show")
|
||||
const itemWarningLimit = arrange === "track" ? 5000 : 1000
|
||||
if (items.length >= itemWarningLimit && !show) {
|
||||
return pugSync.render(event, "too-many-items.pug", {itemCount: items.length, account, query})
|
||||
}
|
||||
|
||||
const locals = {
|
||||
items,
|
||||
account,
|
||||
|
|
|
@ -13,21 +13,12 @@ const currencyExchange = new Map([
|
|||
["AUD", 0.63],
|
||||
["BRL", 0.17],
|
||||
["CAD", 0.7],
|
||||
["CZK", 0.045],
|
||||
["CHF", 1.13],
|
||||
["DKK", 0.15],
|
||||
["EUR", 1.08],
|
||||
["GBP", 1.3],
|
||||
["HKD", 0.13],
|
||||
["HUF", 0.0028],
|
||||
["ILS", 0.27],
|
||||
["MXN", 0.05],
|
||||
["JPY", 0.0067],
|
||||
["NOK", 0.1],
|
||||
["NZD", 0.57],
|
||||
["PLN", 0.27],
|
||||
["SEK", 0.1],
|
||||
["SGD", 0.76],
|
||||
["USD", 1],
|
||||
])
|
||||
const currencies = [...currencyExchange.keys()]
|
||||
|
@ -41,7 +32,7 @@ pugSync.beforeInclude("includes/layout.pug", async (from, event, locals) => {
|
|||
pugSync.beforeInclude("includes/collection-stats.pug", async (from, event, {account, currency}) => {
|
||||
let displayCurrency = currency || getCookie(event, "bcex-currency") || ""
|
||||
if (!currencyExchange.has(displayCurrency)) displayCurrency = "NZD"
|
||||
const currencyRoundTo = (currencyExchange.get(displayCurrency) || 1) < 0.01 ? 1000 : 10
|
||||
const currencyRoundTo = displayCurrency === "JPY" ? 1000 : 10
|
||||
|
||||
return {
|
||||
count: {
|
||||
|
@ -60,8 +51,7 @@ pugSync.beforeInclude("includes/collection-stats.pug", async (from, event, {acco
|
|||
return (currencyExchange.get(c.currency) || 0.6) * c.price / (currencyExchange.get(displayCurrency) || 1) / currencyRoundTo
|
||||
}).reduce((a, c) => a + c, 0)) * currencyRoundTo,
|
||||
displayCurrency,
|
||||
taste: db.prepare("with popularity (a) as (select avg(also_collected_count) from item WHERE account = ? group by band_url) select sum(iif(a >= 0 and a < 20, 1, 0)) as cold, sum(iif(a >= 20 and a < 200, 1, 0)) as warm, sum(iif(a >= 200 and a < 2000, 1, 0)) as hot, sum(iif(a >= 2000, 1, 0)) as supernova from popularity").raw().get(account),
|
||||
currencies: db.prepare("select currency, count(*) as count from (select currency, band_url from item where account = ? group by band_url) group by currency order by count desc").raw().all(account)
|
||||
taste: db.prepare("with popularity (a) as (select avg(also_collected_count) from item WHERE account = ? group by band_url) select sum(iif(a >= 0 and a < 20, 1, 0)) as cold, sum(iif(a >= 20 and a < 200, 1, 0)) as warm, sum(iif(a >= 200 and a < 2000, 1, 0)) as hot, sum(iif(a >= 2000, 1, 0)) as supernova from popularity").raw().get(account)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -10,8 +10,7 @@ const schema = {
|
|||
shape: z.enum(["grid", "list"]),
|
||||
filter_field: z.enum(["band_name", "band_url", "item_title", "item_id", "tag", "why"]).optional(),
|
||||
filter: z.string().regex(/^[^%]+$/).optional(),
|
||||
filter_fuzzy: z.enum(["true"]).optional(),
|
||||
show: z.string().optional()
|
||||
filter_fuzzy: z.enum(["true"]).optional()
|
||||
}),
|
||||
account: z.object({
|
||||
account
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue