feat: recent tracks

This commit is contained in:
Cory Dransfeldt 2024-04-07 11:56:43 -07:00
parent 9ba4931ca3
commit ca94df3b61
No known key found for this signature in database
7 changed files with 92 additions and 10 deletions

View file

@ -20,7 +20,7 @@ export const img = async (
sizes = '90vw', sizes = '90vw',
formats = ['avif', 'webp', 'jpeg'] formats = ['avif', 'webp', 'jpeg']
) => { ) => {
const widths = [200, 320, 570, 880, 1024, 1248].filter(width => width <= maxWidth); const widths = [80, 200, 320, 570, 880, 1024, 1248].filter(width => width <= maxWidth);
const metadata = await Image(src, { const metadata = await Image(src, {
widths: [...widths], widths: [...widths],
formats: [...formats], formats: [...formats],

View file

@ -1,6 +1,6 @@
{ {
"name": "coryd.dev", "name": "coryd.dev",
"version": "9.7.1", "version": "9.8.0",
"description": "The source for my personal site. Built using 11ty.", "description": "The source for my personal site. Built using 11ty.",
"type": "module", "type": "module",
"scripts": { "scripts": {

View file

@ -3,14 +3,14 @@ import artistCapitalizationPatches from '../json/artist-capitalization-patches.j
export const artistCapitalization = (artist) => artistCapitalizationPatches[artist?.toLowerCase()] || artist export const artistCapitalization = (artist) => artistCapitalizationPatches[artist?.toLowerCase()] || artist
const sanitizeMediaString = (string) => string.normalize('NFD').replace(/[\u0300-\u036f\u2010—\.\?\(\)\[\]\{\}]/g, '').replace(/\.{3}/g, '').replace(/A©|é/g, 'e'); const sanitizeMediaString = (string) => string.normalize('NFD').replace(/[\u0300-\u036f\u2010—\.\?\(\)\[\]\{\}]/g, '').replace(/\.{3}/g, '').replace(/A©|é/g, 'e');
const artistSanitizedKey = (artist) => `${sanitizeMediaString(artist).replace(/\s+/g, '-').toLowerCase()}`
const albumSanitizedKey = (album) => `${sanitizeMediaString(album).replace(/\s+/g, '-').toLowerCase()}-${sanitizeMediaString(album.replace(/[:\/\\,'']+/g
, '').replace(/\s+/g, '-').toLowerCase())}`
export const buildChart = (tracks, artists, albums, nowPlaying = {}) => { export const buildChart = (tracks, artists, albums, nowPlaying = {}) => {
const artistsData = {} const artistsData = {}
const albumsData = {} const albumsData = {}
const tracksData = {} const tracksData = {}
const artistSanitizedKey = (artist) => `${sanitizeMediaString(artist).replace(/\s+/g, '-').toLowerCase()}`
const albumSanitizedKey = (album) => `${sanitizeMediaString(album).replace(/\s+/g, '-').toLowerCase()}-${sanitizeMediaString(album.replace(/[:\/\\,'']+/g
, '').replace(/\s+/g, '-').toLowerCase())}`
const objectToArraySorted = (inputObject) => Object.values(inputObject).sort((a, b) => b.plays - a.plays) const objectToArraySorted = (inputObject) => Object.values(inputObject).sort((a, b) => b.plays - a.plays)
tracks.forEach(track => { tracks.forEach(track => {
@ -74,4 +74,16 @@ export const buildChart = (tracks, artists, albums, nowPlaying = {}) => {
topTracks: topTracksData, topTracks: topTracksData,
nowPlaying nowPlaying
} }
}
export const buildTracksWithArt = (tracks, albums) => {
tracks.forEach(track => {
track['image'] = albums[albumSanitizedKey(track['album'])]?.['image'] || `https://cdn.coryd.dev/albums/${sanitizeMediaString(track['artist']).replace(/\s+/g, '-').toLowerCase()}-${sanitizeMediaString(track['album'].replace(/[:\/\\,'']+/g
, '').replace(/\s+/g, '-').toLowerCase())}.jpg`
track['url'] = (artists[artistSanitizedKey(track['artist'])]?.['mbid'] && artists[artistSanitizedKey(track['artist'])]?.['mbid'] !== '') ? `http://musicbrainz.org/artist/${artists[artistSanitizedKey(track['artist'])]?.['mbid']}` : `https://musicbrainz.org/search?query=${track['artist'].replace(
/\s+/g,
'+'
)}&type=artist`
})
return tracks
} }

View file

@ -1,12 +1,14 @@
import { readFile } from 'fs/promises' import { readFile } from 'fs/promises'
import { buildChart } from './helpers/music.js' import { buildChart, buildTracksWithArt } from './helpers/music.js'
export default async function () { export default async function () {
const monthChart = JSON.parse(await readFile('./src/_data/json/scrobbles-month-chart.json', 'utf8')); const monthChart = JSON.parse(await readFile('./src/_data/json/scrobbles-month-chart.json', 'utf8'));
const threeMonthChart = JSON.parse(await readFile('./src/_data/json/scrobbles-three-month-chart.json', 'utf8')); const threeMonthChart = JSON.parse(await readFile('./src/_data/json/scrobbles-three-month-chart.json', 'utf8'));
const artists = JSON.parse(await readFile('./src/_data/json/artists-map.json', 'utf8')); const artists = JSON.parse(await readFile('./src/_data/json/artists-map.json', 'utf8'));
const albums = JSON.parse(await readFile('./src/_data/json/albums-map.json', 'utf8')); const albums = JSON.parse(await readFile('./src/_data/json/albums-map.json', 'utf8'));
const recent = JSON.parse(await readFile('./src/_data/json/scrobbles-window.json', 'utf8'))['data'].reverse().splice(0,10)
return { return {
recent: buildTracksWithArt(recent, albums),
month: buildChart(monthChart['data'], artists, albums), month: buildChart(monthChart['data'], artists, albums),
threeMonthChart: buildChart(threeMonthChart['data'], artists, albums), threeMonthChart: buildChart(threeMonthChart['data'], artists, albums),
} }

View file

@ -59,12 +59,16 @@ layout: default
Tracks Tracks
</h2> </h2>
<div class="now__section--header-buttons client-side"> <div class="now__section--header-buttons client-side">
<button class="small active" data-toggle="tracks-window">This week</button> <button class="small active" data-toggle="tracks-recent">Recent</button>
<button class="small secondary" data-toggle="tracks-window">This week</button>
<button class="small secondary" data-toggle="tracks-month">This month</button> <button class="small secondary" data-toggle="tracks-month">This month</button>
<button class="small secondary" data-toggle="tracks-three-months">3 months</button> <button class="small secondary" data-toggle="tracks-three-months">3 months</button>
</div> </div>
</div> </div>
<div id="tracks-window"> <div id="tracks-recent">
{% render "partials/now/tracks-recent.liquid", data:musicCharts.recent %}
</div>
<div class="hidden" id="tracks-window">
{% render "partials/now/track-chart.liquid", data:music.topTracks.data, mostPlayed:music.topTracks.mostPlayed %} {% render "partials/now/track-chart.liquid", data:music.topTracks.data, mostPlayed:music.topTracks.mostPlayed %}
</div> </div>
<div class="hidden" id="tracks-month"> <div class="hidden" id="tracks-month">

View file

@ -0,0 +1,25 @@
{% if data.size > 0 %}
{% capture css %}
{% render "../../../assets/styles/components/track-chart.css" %}
{% endcapture %}
<style>{{ css}}</style>
{% endif %}
<div class="track__chart">
{% for item in data limit: 10 %}
{% capture alt %}{{ item.track }} by {{ item.track }}{% endcapture %}
<div class="track__chart--item">
<div class="track__chart--meta">
{% image item.image, alt, '', 'lazy', 80 %}
<div class="track__chart--meta--text">
<div class="track__chart--title">{{ item.track }}</div>
<div class="track__chart--artists">
<a href="{{ item.url }}">{{ item.artist }}</a>
</div>
</div>
</div>
<div class="track__chart--timestamp">
{{ item.timestamp | date: "%B %-d, %-I:%M%p", "America/Los_Angeles" }}
</div>
</div>
{% endfor %}
</div>

View file

@ -1,7 +1,12 @@
.track__chart--item { .track__chart--item {
justify-content: space-between;
}
.track__chart--item,
.track__chart--meta {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; align-items: center;
} }
.track__chart--item:not(:last-of-type) { .track__chart--item:not(:last-of-type) {
@ -29,12 +34,46 @@
.track__chart--title { .track__chart--title {
font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold);
}
.track__chart--title,
.track__chart--artists {
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
.track__chart--artists { .track__chart--artists,
.track__chart--timestamp {
font-size: var(--font-size-sm); font-size: var(--font-size-sm);
line-height: var(--line-height-sm); line-height: var(--line-height-sm);
}
.track__chart--item img {
border: 1px solid var(--accent-color);
border-radius: var(--rounded-md);
}
.track__chart--item img,
.track__chart--item picture {
width: calc(var(--sizing-3xl) * 1.5);
height: calc(var(--sizing-3xl) * 1.5);
}
.track__chart--meta {
justify-content: start;
gap: var(--sizing-md);
max-width: calc(70% - var(--sizing-lg));
}
.track__chart--meta--text {
display: flex;
flex-direction: column;
justify-content: start;
max-width: 85%;
}
.track__chart--timestamp {
margin-left: var(--sizing-lg);
text-align: right;
} }