forked from globuzma/mentalaradio
First real commit
This commit is contained in:
parent
1947b908a6
commit
107d33c908
30 changed files with 2583 additions and 1 deletions
137
src/App.svelte
Normal file
137
src/App.svelte
Normal file
|
@ -0,0 +1,137 @@
|
|||
<script>
|
||||
import { basePath } from './lib/router.tsx'
|
||||
import menthealeauLogo from './assets/menthealeau.svg'
|
||||
|
||||
let isPlaying = $state(false)
|
||||
let title = $state("")
|
||||
let url = $state("")
|
||||
let imageData = $state("")
|
||||
let loadingSound = $state(false)
|
||||
let firstTimePlaying = $state(true)
|
||||
let startedAudio = $state(new Date())
|
||||
let audioPlayer
|
||||
|
||||
const eventSource = new EventSource(basePath + '/metadata')
|
||||
eventSource.onmessage = function(event) {
|
||||
let receivedData = JSON.parse(event.data)
|
||||
console.log(receivedData)
|
||||
title = receivedData.title
|
||||
url = receivedData.url
|
||||
imageData = receivedData.artwork
|
||||
}
|
||||
|
||||
async function buttonClick() {
|
||||
console.log(audioPlayer.duration)
|
||||
if(isPlaying) {
|
||||
audioPlayer.pause()
|
||||
isPlaying = false
|
||||
} else {
|
||||
if(firstTimePlaying) {
|
||||
loadingSound = true
|
||||
audioPlayer.muted = true
|
||||
audioPlayer.play()
|
||||
startedAudio = new Date()
|
||||
await new Promise(r => setTimeout(r, 3000))
|
||||
audioPlayer.pause()
|
||||
audioPlayer.muted = false
|
||||
loadingSound = false
|
||||
firstTimePlaying = false
|
||||
audioPlayer.currentTime = 0
|
||||
} else {
|
||||
audioPlayer.currentTime = ((new Date().getTime() - startedAudio.getTime()) / 1000) - 3
|
||||
}
|
||||
audioPlayer.play()
|
||||
isPlaying = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="min-w-screen min-h-screen overflow-y-hidden flex flex-col items-center justify-center p-4">
|
||||
<div class="flex -mt-8 md:mt-32 flex-row justify-between w-full max-w-96">
|
||||
<div class="w-0 flex flex-col invisible md:w-fit md:visible items-end gap-4 -rotate-12 md:mb-6 md:-ml-36 md:-mt-16">
|
||||
<span class="speech-bubble arrow-left">Et t'écoutes quoi comme musique ?</span>
|
||||
<span class="speech-bubble arrow-right">Oh ... de tout</span>
|
||||
</div>
|
||||
<img class="w-96 -mb-48 md:w-xl md:-mr-56 md:-mt-64 md:-mb-80" src={menthealeauLogo} alt="Logo d'une menthe à l'eau" />
|
||||
</div>
|
||||
<div class="p-4 bg-[#f97095] rounded-md border-white border-5 drop-shadow-md flex flex-col gap-4 max-w-96 w-full">
|
||||
<h1 class="font-[Momentz] text-white font-bold text-4xl">Menthe à l'eau</h1>
|
||||
<p class="text-white font-[Inter] font-bold">Créée à l'origine pour être un énorme dump de musique en tout genre. Cette playlist est contre toute attente devenue un énorme dump de musique en tout genre. Enjoy the radio. 📻</p>
|
||||
{#if imageData == ""}
|
||||
<div class="block w-full pb-[26%] pt-[26%] flex flex-col items-center justify-center bg-[#ff99b4] rounded-md">
|
||||
<svg class="mr-3 -ml-1 size-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
||||
</div>
|
||||
{:else}
|
||||
<a href={url} target="_blank">
|
||||
<img class="w-full rounded" src={imageData} alt="current song artwork" />
|
||||
</a>
|
||||
{/if}
|
||||
<span class="text-white font-[Inter] font-bold w-full text-ellipsis truncate">{#if title == ""}Loading...{:else}{title}{/if}</span>
|
||||
<audio bind:this={audioPlayer}>
|
||||
<source src={basePath + "/stream"} type="audio/mp3">
|
||||
</audio>
|
||||
<div class="flex flex-col items-center w-full">
|
||||
<div class="bg-[#ff99b4] w-32 rounded-full -mb-12">
|
||||
{#if loadingSound}
|
||||
<svg class="mr-3 -ml-1 w-full animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
||||
{:else}
|
||||
{#if isPlaying}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onclick={buttonClick} class="text-white w-full" viewBox="0 0 24 24"><path fill="currentColor" d="M6 16V8q0-.825.588-1.412T8 6h8q.825 0 1.413.588T18 8v8q0 .825-.587 1.413T16 18H8q-.825 0-1.412-.587T6 16"/></svg>
|
||||
{:else}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onclick={buttonClick} class="text-white w-full" viewBox="0 0 24 24"><path fill="currentColor" d="M8 17.175V6.825q0-.425.3-.713t.7-.287q.125 0 .263.037t.262.113l8.15 5.175q.225.15.338.375t.112.475t-.112.475t-.338.375l-8.15 5.175q-.125.075-.262.113T9 18.175q-.4 0-.7-.288t-.3-.712"/></svg>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-fit h-fit flex mt-12 mb-24 md:mb-12 flex-col visible md:w-0 md:h-0 md:invisible items-end gap-4">
|
||||
<span class="speech-bubble arrow-left">Et t'écoutes quoi comme musique ?</span>
|
||||
<span class="speech-bubble arrow-right">Oh ... De tout.</span>
|
||||
</div>
|
||||
<div class="w-full opacity-50">
|
||||
<span>Crée par Zuma · <a href="#">Source</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.speech-bubble {
|
||||
width: fit-content;
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
background: #FFF;
|
||||
border-radius: .4em;
|
||||
}
|
||||
|
||||
.arrow-right:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 0.969em solid transparent;
|
||||
border-left-color: #FFF;
|
||||
border-right: 0;
|
||||
margin-top: -0.969em;
|
||||
margin-right: -0.7em;
|
||||
}
|
||||
.arrow-left:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 0.969em solid transparent;
|
||||
border-right-color: #FFF;
|
||||
border-left: 0;
|
||||
margin-top: -0.969em;
|
||||
margin-left: -0.7em;
|
||||
}
|
||||
|
||||
:global(body) {
|
||||
background-size: cover;
|
||||
background-image: url('data:image/svg+xml,<svg width="1920" xmlns="http://www.w3.org/2000/svg" height="1080" fill="none"><defs><clipPath id="a" class="frame-clip frame-clip-def"><rect rx="0" ry="0" width="1920" height="1080" transform="matrix(1.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000)"/></clipPath></defs><g clip-path="url(%23a)"><g class="fills"><rect width="1920" height="1080" class="frame-background" transform="matrix(1.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000)" style="fill: rgb(16, 180, 182); fill-opacity: 1;" ry="0" rx="0"/></g><g class="frame-children"><path d="M-407.000,424.309C-127.000,173.309,162.125,206.159,425.000,263.663C553.000,291.663,803.000,413.663,1012.000,391.663C1338.616,357.282,1986.000,270.000,2173.000,444.000C2360.000,618.000,1955.000,946.309,1955.000,946.309L-109.000,949.309L-407.000,424.309Z" style="fill: rgb(18, 187, 190); fill-opacity: 1;" class="fills"/><path d="M-534.000,480.309C-254.000,229.309,35.125,262.159,298.000,319.663C426.000,347.663,676.000,469.663,885.000,447.663C1211.616,413.282,1859.000,326.000,2046.000,500.000C2233.000,674.000,1828.000,1002.309,1828.000,1002.309L-236.000,1005.309L-534.000,480.309Z" style="fill: rgb(52, 191, 196); fill-opacity: 1;" class="fills"/><path d="M-338.000,572.309C-58.000,321.309,231.125,354.159,494.000,411.663C622.000,439.663,872.000,561.663,1081.000,539.663C1407.616,505.282,1886.000,379.309,2073.000,553.309C2260.000,727.309,2024.000,1094.309,2024.000,1094.309L-40.000,1097.309L-338.000,572.309Z" style="fill: rgb(71, 194, 202); fill-opacity: 1;" class="fills"/><path d="M-469.000,629.309C-189.000,378.309,100.125,411.159,363.000,468.663C491.000,496.663,741.000,618.663,950.000,596.663C1276.616,562.282,1755.000,436.309,1942.000,610.309C2129.000,784.309,1893.000,1151.309,1893.000,1151.309L-171.000,1154.309L-469.000,629.309Z" style="fill: rgb(112, 204, 215); fill-opacity: 1;" class="fills"/><path d="M-373.000,741.309C-93.000,490.309,196.125,523.159,459.000,580.663C587.000,608.663,837.000,730.663,1046.000,708.663C1372.616,674.282,1851.000,548.309,2038.000,722.309C2225.000,896.309,1989.000,1263.309,1989.000,1263.309L-75.000,1266.309L-373.000,741.309Z" style="fill: rgb(255, 255, 255); fill-opacity: 1;" class="fills"/><path d="M-350.000,798.646C-70.000,547.646,193.000,571.646,452.000,644.646C711.000,717.646,881.000,886.646,1189.000,772.646C1497.000,658.646,1874.000,605.646,2061.000,779.646C2248.000,953.646,2012.000,1320.646,2012.000,1320.646L-52.000,1323.646L-350.000,798.646Z" style="fill: rgb(253, 196, 127); fill-opacity: 1;" class="fills"/><path d="M-344.000,865.646C-64.000,614.646,199.000,638.646,458.000,711.646C717.000,784.646,887.000,953.646,1195.000,839.646C1503.000,725.646,1880.000,672.646,2067.000,846.646C2254.000,1020.646,2018.000,1387.646,2018.000,1387.646L-46.000,1390.646L-344.000,865.646Z" style="fill: rgb(254, 202, 132); fill-opacity: 1;" class="fills"/><path d="M-372.000,935.000C-92.000,684.000,171.000,708.000,430.000,781.000C689.000,854.000,859.000,1023.000,1167.000,909.000C1475.000,795.000,1852.000,742.000,2039.000,916.000C2226.000,1090.000,1990.000,1457.000,1990.000,1457.000L-74.000,1460.000L-372.000,935.000Z" style="fill: rgb(254, 206, 142); fill-opacity: 1;" class="fills"/></g></g></svg>');
|
||||
}
|
||||
|
||||
</style>
|
27
src/app.css
Normal file
27
src/app.css
Normal file
|
@ -0,0 +1,27 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
@font-face{
|
||||
font-family: 'Momentz';
|
||||
src: url('/fonts/Momentz.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: url('/fonts/Inter-Regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
src: url('/fonts/Inter-Italic.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
src: url('/fonts/Inter-Bold.woff2') format('woff2');
|
||||
}
|
79
src/assets/menthealeau.svg
Normal file
79
src/assets/menthealeau.svg
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="593.60071"
|
||||
height="667.54163"
|
||||
viewBox="-32 -32 593.60071 667.54161"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs6" />
|
||||
<g
|
||||
filter="url(#a)"
|
||||
id="g6"
|
||||
transform="translate(-27.199546,-90.924425)">
|
||||
<defs
|
||||
id="defs3">
|
||||
<filter
|
||||
id="a"
|
||||
x="-0.0082758516"
|
||||
y="-0.0073401053"
|
||||
width="1.0234482"
|
||||
height="1.020797"
|
||||
filterUnits="objectBoundingBox"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feFlood
|
||||
flood-opacity="0"
|
||||
result="BackgroundImageFix"
|
||||
id="feFlood1" />
|
||||
<feColorMatrix
|
||||
in="SourceAlpha"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
id="feColorMatrix1" />
|
||||
<feOffset
|
||||
dx="4"
|
||||
dy="4"
|
||||
id="feOffset1" />
|
||||
<feGaussianBlur
|
||||
stdDeviation="2"
|
||||
id="feGaussianBlur1" />
|
||||
<feColorMatrix
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
|
||||
id="feColorMatrix2" />
|
||||
<feBlend
|
||||
in2="BackgroundImageFix"
|
||||
result="filter_265b8c7a-1d1a-80dd-8005-dbe7b8ea37ba"
|
||||
id="feBlend2"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
in="SourceGraphic"
|
||||
in2="filter_265b8c7a-1d1a-80dd-8005-dbe7b8ea37ba"
|
||||
result="shape"
|
||||
id="feBlend3"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
</defs>
|
||||
<path
|
||||
d="M 74,79.666 229.489,63.764 c 0,0 14.498,-1.017 21.131,7.26 6.285,7.842 6.769,26.2 6.769,26.2 l 30.51,307.195 -31.228,2.19 -27.145,-297.568 c 0,0 -0.528,-10.723 -5.478,-14.186 -3.887,-2.72 -20.662,-0.569 -20.662,-0.569 l -125.462,13.73 z"
|
||||
style="fill:#ffb700;fill-opacity:1"
|
||||
class="fills"
|
||||
id="path3" />
|
||||
<path
|
||||
d="m 372.205,271.622 c 17.68,-76.098 73.026,-129.905 83.018,-126.83 9.993,3.074 4.613,88.396 -2.306,112.225 -0.26,0.896 -2.697,5.717 2.306,3.075 24.106,-12.731 119.029,7.399 124.528,20.754 5.38,13.067 -77.638,43.045 -121.837,37.28 -1.876,-0.245 -2.12,0.267 0,1.922 16.878,13.175 25.751,101.463 16.527,106.075 -11.277,5.638 -83.787,-61.493 -86.093,-84.553 -2.306,-23.06 -13.068,-20.754 -13.837,-24.597 -0.768,-3.843 -4.227,-39.971 -2.306,-45.351 z m 0,0"
|
||||
style="fill:#20a541;fill-opacity:1"
|
||||
class="fills"
|
||||
id="path4" />
|
||||
<path
|
||||
d="m 140.831,223.964 c 0,0 -164.766,396.433 -137.862,412.575 26.904,16.142 150.663,96.851 179.104,78.403 C 210.515,696.494 421.904,338.296 406.53,302.938 391.156,267.579 195.141,169.19 170.543,186.869 c -24.598,17.679 -37.666,57.65 -29.712,37.095 z m 0,0"
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
class="fills"
|
||||
id="path5" />
|
||||
<path
|
||||
d="m 150.129,258.548 c 0,0 -146.245,349.224 -123.795,362.705 22.45,13.481 125.72,80.886 149.453,65.479 23.732,-15.407 200.125,-314.558 187.297,-344.088 -4.739,-10.908 -58.204,8.205 -89.271,-9.529 -27.411,-15.648 -7.611,-66.952 -33.822,-76.867 -24.502,-9.268 -67.572,-15.038 -73.826,-10.539 -20.526,14.765 -16.036,12.839 -16.036,12.839 z"
|
||||
style="fill:#3aff94;fill-opacity:1"
|
||||
class="fills"
|
||||
id="path6" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
1
src/assets/svelte.svg
Normal file
1
src/assets/svelte.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="26.6" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"></path><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"></path></svg>
|
After Width: | Height: | Size: 1.9 KiB |
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
// place files you want to import through the `$lib` alias in this folder.
|
1
src/lib/router.tsx
Normal file
1
src/lib/router.tsx
Normal file
|
@ -0,0 +1 @@
|
|||
export const basePath = (import.meta.env.MODE == "development") ? "http://localhost:8080" : (window.BASE_PATH || "")
|
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
9
src/main.ts
Normal file
9
src/main.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { mount } from 'svelte'
|
||||
import './app.css'
|
||||
import App from './App.svelte'
|
||||
|
||||
const app = mount(App, {
|
||||
target: document.getElementById('app')!,
|
||||
})
|
||||
|
||||
export default app
|
2
src/vite-env.d.ts
vendored
Normal file
2
src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
Loading…
Add table
Add a link
Reference in a new issue