Polishing
This commit is contained in:
		
							parent
							
								
									f8992fc24b
								
							
						
					
					
						commit
						94fce03750
					
				
					 8 changed files with 48 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -3,8 +3,9 @@ function movePlayer() {
 | 
			
		|||
	const playerExists = pc.querySelector("iframe")
 | 
			
		||||
	if (!playerExists) return
 | 
			
		||||
	const pm = document.getElementById("player-marker")
 | 
			
		||||
	pm.style.display = "block"
 | 
			
		||||
	pm.style.height = `${pc.clientHeight}px`
 | 
			
		||||
	pc.style.top = `${Math.round(pm.getBoundingClientRect().top)}px`
 | 
			
		||||
}
 | 
			
		||||
movePlayer()
 | 
			
		||||
document.body.addEventListener("htmx:afterSettle", movePlayer)
 | 
			
		||||
document.body.addEventListener("htmx:load", movePlayer)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,9 @@ block view
 | 
			
		|||
      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")
 | 
			
		||||
            img(loading="lazy" src=item.item_art_url width=210 height=210)
 | 
			
		||||
            .ps-relative
 | 
			
		||||
              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
 | 
			
		||||
          .d-flex.fw-wrap.g4
 | 
			
		||||
            if item.why
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,9 @@ html
 | 
			
		|||
    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%;
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +64,28 @@ html
 | 
			
		|||
      .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;
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +96,7 @@ html
 | 
			
		|||
        flex-shrink: 0;
 | 
			
		||||
      }
 | 
			
		||||
  body.themed.theme-system.overflow-y-scroll(hx-boost="true" hx-swap="outerHTML" hx-target="#page" hx-select="#page")
 | 
			
		||||
    #page
 | 
			
		||||
    #page(hx-history-elt)
 | 
			
		||||
      header.s-topbar.ps-sticky.t0
 | 
			
		||||
        .s-topbar--container.wmx9
 | 
			
		||||
          .s-topbar--logo
 | 
			
		||||
| 
						 | 
				
			
			@ -97,8 +122,8 @@ html
 | 
			
		|||
        main.fl-grow1
 | 
			
		||||
          block view
 | 
			
		||||
 | 
			
		||||
        aside.ws3
 | 
			
		||||
          .ps-sticky.d-flex.fd-column.g12(style="top: 80px")
 | 
			
		||||
        aside.ws340
 | 
			
		||||
          .ps-fixed.ws340.d-flex.fd-column.g12(style="top: 80px")
 | 
			
		||||
            if arrange === "tag"
 | 
			
		||||
              include tag-status.pug
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +145,7 @@ html
 | 
			
		|||
                input(type="hidden" name="shape" value=shape)
 | 
			
		||||
                button.s-btn.s-btn__xs.s-btn__icon.s-btn__outlined.s-btn__muted#search-submit(style="height: 38px")!= icons.get("search")
 | 
			
		||||
 | 
			
		||||
            #player-marker.pe-none.myn6
 | 
			
		||||
            #player-marker.pe-none(style="display: none")
 | 
			
		||||
 | 
			
		||||
            .s-sidebarwidget
 | 
			
		||||
              .s-sidebarwidget--header Collection
 | 
			
		||||
| 
						 | 
				
			
			@ -177,5 +202,5 @@ html
 | 
			
		|||
                      .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]
 | 
			
		||||
 | 
			
		||||
    #player-container.ps-fixed.r16.ws3(hx-preserve="true")
 | 
			
		||||
    #player-container.ps-fixed.r16.ws340(hx-preserve="true")
 | 
			
		||||
      #player
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,14 @@
 | 
			
		|||
if downloader.total > 0 || downloader.outcome
 | 
			
		||||
  #tag-download
 | 
			
		||||
    if !downloader.running && !downloader.outcome
 | 
			
		||||
      form.s-notice.s-notice__info.d-flex.ai-center.p8.gx16.pl16(role="status" hx-target="#tag-download" hx-post="/api/tag-download")
 | 
			
		||||
      form.s-notice.s-notice__info.d-flex.ai-center.p8.gx16.pl16(role="status" hx-target="#tag-download" hx-select="#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-target="#tag-download" hx-get=`/api/tag-download?account=${account}` hx-trigger="every 5s" hx-indicator="null")
 | 
			
		||||
      .s-notice.p16(role="status" hx-target="#tag-download" hx-select="#tag-download" hx-get=`/api/tag-download?account=${account}` hx-trigger="every 5s" hx-indicator="null")
 | 
			
		||||
        .d-flex.gx16.ai-center
 | 
			
		||||
          != icons.get("cloud-download")
 | 
			
		||||
          .fl-grow1 Downloading tags...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.px16(href=`/api/play/${item_type}/${item_id}` hx-target="#player" hx-select="#player" hx-push-url="false").fc-theme-primary!= icons.get("refresh-double")
 | 
			
		||||
      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/`)
 | 
			
		||||
      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)
 | 
			
		||||
      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}`)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ block view
 | 
			
		|||
                  | ☆
 | 
			
		||||
                else
 | 
			
		||||
                  = item.track_number || "-"
 | 
			
		||||
              td: a(href=`/api/play/${item.item_type}/${item.item_id}` hx-target="#player" hx-select="#player" hx-indicator="null" hx-push-url="false")= item.title
 | 
			
		||||
              td: a(href=`/api/play/${item.item_type}/${item.item_id}/${item.track_id}` hx-target="#player" hx-select="#player" hx-indicator="null" hx-push-url="false")= item.title
 | 
			
		||||
              td= item.artist
 | 
			
		||||
              td= item.item_title
 | 
			
		||||
              - let label = item.band_url.replace(/https?:\/\/(.*?)\.bandcamp\.com.*/, "$1")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,12 +25,12 @@ const currencyExchange = new Map([
 | 
			
		|||
const sqls = {
 | 
			
		||||
	album_grid:  "SELECT item.*, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY item_id {ORDER}",
 | 
			
		||||
	album_list:  "SELECT item.*, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY item_id ORDER BY band_url, band_name COLLATE NOCASE, item_title COLLATE NOCASE",
 | 
			
		||||
	artist_grid: "SELECT band_name, count(DISTINCT item_id) AS album_count, group_concat(DISTINCT band_url) AS labels, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_name ORDER BY band_name COLLATE NOCASE",
 | 
			
		||||
	artist_list: "SELECT band_name, count(DISTINCT item_id) AS album_count, band_url, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_name ORDER BY band_name COLLATE NOCASE",
 | 
			
		||||
	label_grid:  "SELECT iif(count(DISTINCT band_name) = 1, band_name, band_url) AS display_name, band_url, count(DISTINCT item_id) AS album_count, count(DISTINCT band_name) AS artist_count, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_url ORDER BY display_name COLLATE NOCASE",
 | 
			
		||||
	label_list:  "SELECT iif(count(DISTINCT band_name) = 1, band_name, band_url) AS display_name, band_url, count(DISTINCT item_id) AS album_count, count(DISTINCT band_name) AS artist_count, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_url ORDER BY display_name COLLATE NOCASE",
 | 
			
		||||
	artist_grid: "SELECT band_name, item_title, count(DISTINCT item_id) AS album_count, group_concat(DISTINCT band_url) AS labels, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_name ORDER BY band_name COLLATE NOCASE",
 | 
			
		||||
	artist_list: "SELECT band_name, item_title, count(DISTINCT item_id) AS album_count, band_url, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_name ORDER BY band_name COLLATE NOCASE",
 | 
			
		||||
	label_grid:  "SELECT item_title, iif(count(DISTINCT band_name) = 1, band_name, band_url) AS display_name, band_url, count(DISTINCT item_id) AS album_count, count(DISTINCT band_name) AS artist_count, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_url ORDER BY display_name COLLATE NOCASE",
 | 
			
		||||
	label_list:  "SELECT item_title, iif(count(DISTINCT band_name) = 1, band_name, band_url) AS display_name, band_url, count(DISTINCT item_id) AS album_count, count(DISTINCT band_name) AS artist_count, count(*) AS track_count, iif(sum(duration) > 3600, cast(total(duration)/3600 AS INTEGER) || 'h ' || cast(total(duration)/60%60 AS INTEGER) || 'm', cast(total(duration)/60 AS INTEGER) || 'm') AS total_duration FROM item INNER JOIN track USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} GROUP BY band_url ORDER BY display_name COLLATE NOCASE",
 | 
			
		||||
	tag_grid:    "SELECT tag, count(*) AS count FROM item_tag INNER JOIN item USING (account, item_id) WHERE account = ? {WHERE} GROUP BY tag, band_url ORDER BY count DESC",
 | 
			
		||||
	tag_list:    "SELECT tag, count(*) AS labels, sum(count) AS albums FROM (SELECT tag, count(*) AS count FROM item_tag INNER JOIN item USING (account, item_id) WHERE account = ? {WHERE} GROUP BY tag, band_url) GROUP BY tag ORDER BY labels DESC",
 | 
			
		||||
	tag_list:    "SELECT item_title, tag, count(*) AS labels, sum(count) AS albums FROM (SELECT item_title, tag, count(*) AS count FROM item_tag INNER JOIN item USING (account, item_id) WHERE account = ? {WHERE} GROUP BY tag, band_url) GROUP BY tag ORDER BY labels DESC",
 | 
			
		||||
	track_list:  "SELECT * FROM track INNER JOIN item USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} ORDER BY band_url, item_title COLLATE NOCASE, track_number"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,10 +10,11 @@ const pugSync = sync.require("../pug-sync")
 | 
			
		|||
 | 
			
		||||
const schema = z.object({
 | 
			
		||||
	item_type: z.enum(["album", "track"]),
 | 
			
		||||
	item_id: z.number({coerce: true})
 | 
			
		||||
	item_id: z.number({coerce: true}),
 | 
			
		||||
	track_id: z.number({coerce: true}).optional()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
router.get("/api/play/:item_type/:item_id", defineEventHandler(async event => {
 | 
			
		||||
router.get("/api/play/:item_type/:item_id/:track_id", defineEventHandler(async event => {
 | 
			
		||||
	const locals = await getValidatedRouterParams(event, schema.parse)
 | 
			
		||||
	return pugSync.render(event, "player.pug", locals)
 | 
			
		||||
}))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue