Expand DNDT, add TrackInline, more tracks
This commit is contained in:
8
src/assets/tracks/dndt-gameplay-trailer.json
Normal file
8
src/assets/tracks/dndt-gameplay-trailer.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"src": "dungeons-and-dining-tables/Dungeons_and_Dining_Tables.mp3",
|
||||
"metadata": {
|
||||
"title": "Gameplay Trailer",
|
||||
"subtitle": "Dungeons and Dining Tables",
|
||||
"extra": "Synthetic Orchestra"
|
||||
}
|
||||
}
|
8
src/assets/tracks/dndt-kindlerest.json
Normal file
8
src/assets/tracks/dndt-kindlerest.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"src": "dungeons-and-dining-tables/Kindlerest.mp3",
|
||||
"metadata": {
|
||||
"title": "Kindlerest",
|
||||
"subtitle": "Dungeons and Dining Tables",
|
||||
"extra": "Synthetic Orchestra"
|
||||
}
|
||||
}
|
8
src/assets/tracks/dndt-pine-for-a-tune.json
Normal file
8
src/assets/tracks/dndt-pine-for-a-tune.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"src": "dungeons-and-dining-tables/Pine_for_a_Tune.mp3",
|
||||
"metadata": {
|
||||
"title": "Pine for a Tune",
|
||||
"subtitle": "Dungeons and Dining Tables",
|
||||
"extra": "Synthetic Orchestra"
|
||||
}
|
||||
}
|
8
src/assets/tracks/dndt-the-couch-troll.json
Normal file
8
src/assets/tracks/dndt-the-couch-troll.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"src": "dungeons-and-dining-tables/The_Couch_Troll.mp3",
|
||||
"metadata": {
|
||||
"title": "The Couch Troll",
|
||||
"subtitle": "Dungeons and Dining Tables",
|
||||
"extra": "Synthetic Orchestra"
|
||||
}
|
||||
}
|
8
src/assets/tracks/dndt-the-couch-trolls-lair.json
Normal file
8
src/assets/tracks/dndt-the-couch-trolls-lair.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"src": "dungeons-and-dining-tables/The_Couch_Trolls_Lair.mp3",
|
||||
"metadata": {
|
||||
"title": "The Couch Troll's Lair",
|
||||
"subtitle": "Dungeons and Dining Tables",
|
||||
"extra": "Synthetic Orchestra"
|
||||
}
|
||||
}
|
@@ -2,10 +2,8 @@
|
||||
// TODO: Handle author, etc., via inclusion of some sort of tag in the quote, either frontmatter tags or simply [author=Person Name]
|
||||
---
|
||||
|
||||
<div class="flex w-full items-center">
|
||||
<blockquote
|
||||
class="border-primary mx-auto my-8 max-w-xl border-l-6 py-2 pl-4 italic"
|
||||
>
|
||||
<div class="my-4 flex w-full items-center px-2 md:px-8">
|
||||
<blockquote class="border-primary mx-auto border-l-6 pl-4 italic">
|
||||
<p class="text-lg font-light"><slot /></p>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
@@ -54,7 +54,7 @@ const initialQueue = await Promise.all(
|
||||
</div>
|
||||
<div
|
||||
id="player:time:progress:played"
|
||||
class="bg-primary absolute top-0 left-0 m-0 h-full p-0"
|
||||
class="from-primary to-primary-50 absolute top-0 left-0 m-0 h-full bg-gradient-to-r p-0"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@@ -342,7 +342,7 @@ const initialQueue = await Promise.all(
|
||||
return { bufferedSeconds: 0, bufferedPercent: 0 };
|
||||
}
|
||||
|
||||
addFromTrackCard(track) {
|
||||
addToQueue(track, immediatePlay = false) {
|
||||
var current = this.playlist[this.index];
|
||||
|
||||
if (
|
||||
@@ -356,7 +356,7 @@ const initialQueue = await Promise.all(
|
||||
this.play();
|
||||
}
|
||||
} else {
|
||||
this.queue(track, true);
|
||||
this.queue(track, immediatePlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,10 @@ import { getAudioDurationInSeconds } from "get-audio-duration";
|
||||
import { join } from "path";
|
||||
const fullFilePath = join(process.cwd(), "public", track.data.src);
|
||||
const duration = await getAudioDurationInSeconds(fullFilePath);
|
||||
|
||||
if (!track.data.card) {
|
||||
throw new Error(`Track with ID "${track.id}" is missing card data.`);
|
||||
}
|
||||
---
|
||||
|
||||
<div
|
||||
@@ -21,7 +25,7 @@ const duration = await getAudioDurationInSeconds(fullFilePath);
|
||||
"relative flex min-h-42 flex-auto hover:cursor-pointer",
|
||||
index < 2 ? "lg:w-1/2" : "sm:w-1/2 md:w-1/3 lg:w-1/4"
|
||||
]}
|
||||
onclick=`window.player.addFromTrackCard({ src: "${track.data.src}", "metadata": ${JSON.stringify(track.data.metadata)}, "duration": "${duration}" })`
|
||||
onclick=`window.player.addToQueue({ src: "${track.data.src}", "metadata": ${JSON.stringify(track.data.metadata)}, "duration": "${duration}" }, true);`
|
||||
>
|
||||
<Image
|
||||
src={track.data.card.image.src}
|
||||
|
34
src/components/TrackInline.astro
Normal file
34
src/components/TrackInline.astro
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
import { getTrackByID } from "@lib/utils";
|
||||
import { Icon } from "astro-icon/components";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { id, class: className, ...attrs } = Astro.props as Props;
|
||||
|
||||
const track = getTrackByID(id);
|
||||
|
||||
if (!track) {
|
||||
throw new Error(`Track with ID "${id}" not found.`);
|
||||
}
|
||||
|
||||
import { getAudioDurationInSeconds } from "get-audio-duration";
|
||||
import { join } from "path";
|
||||
const fullFilePath = join(process.cwd(), "public", track.data.src);
|
||||
const duration = await getAudioDurationInSeconds(fullFilePath);
|
||||
---
|
||||
|
||||
<div
|
||||
class:list={[
|
||||
"text-primary flex items-center transition hover:cursor-pointer hover:text-gray-300",
|
||||
className
|
||||
]}
|
||||
onclick=`window.player.addToQueue({ src: "${track.data.src}", "metadata": ${JSON.stringify(track.data.metadata)}, "duration": "${duration}" }, true);`
|
||||
{...attrs}
|
||||
>
|
||||
<Icon name="fa7-solid:play-circle" class="mr-2 inline-block" />
|
||||
<span class="inline-block">{track.data.metadata.title}</span>
|
||||
</div>
|
@@ -68,23 +68,30 @@ const tracks = defineCollection({
|
||||
subtitle: z.string().optional(),
|
||||
extra: z.string().optional(),
|
||||
artist: z.string().optional().default("Nathan Cummins"),
|
||||
artwork: z.preprocess((val) => `/src/assets/img/tracks/${val}`, image())
|
||||
artwork: z
|
||||
.preprocess((val) => `/src/assets/img/tracks/${val}`, image())
|
||||
.optional()
|
||||
}),
|
||||
autoQueue: z
|
||||
.object({
|
||||
order: z.number()
|
||||
})
|
||||
.optional(),
|
||||
card: z.object({
|
||||
image: z.object({
|
||||
src: z.preprocess((val) => `/src/assets/img/tracks/${val}`, image()),
|
||||
alt: z.string()
|
||||
}),
|
||||
text: z.object({
|
||||
primary: z.string(),
|
||||
secondary: z.string()
|
||||
card: z
|
||||
.object({
|
||||
image: z.object({
|
||||
src: z.preprocess(
|
||||
(val) => `/src/assets/img/tracks/${val}`,
|
||||
image()
|
||||
),
|
||||
alt: z.string()
|
||||
}),
|
||||
text: z.object({
|
||||
primary: z.string(),
|
||||
secondary: z.string()
|
||||
})
|
||||
})
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
});
|
||||
|
||||
|
@@ -1,9 +1,11 @@
|
||||
import type { ImageMetadata } from "astro";
|
||||
import { getImage } from "astro:assets";
|
||||
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { getCollection, type CollectionEntry } from "astro:content";
|
||||
type Project = CollectionEntry<"projects">;
|
||||
|
||||
const tracks = await getCollection("tracks");
|
||||
|
||||
const allProjectOtherImages = import.meta.glob<{ default: ImageMetadata }>(
|
||||
"/src/assets/img/projects/**/*",
|
||||
{ eager: true }
|
||||
@@ -137,3 +139,13 @@ export function slugify(input: string): string {
|
||||
slug = slug.replace(/^-+|-+$/g, "");
|
||||
return slug;
|
||||
}
|
||||
|
||||
export function getTrackByID(id: string): CollectionEntry<"tracks"> | null {
|
||||
for (const track of tracks) {
|
||||
if (track.id === id) {
|
||||
return track;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
Reference in New Issue
Block a user