aboutsummaryrefslogtreecommitdiffstats
path: root/static
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2023-08-06 12:57:55 +0100
committerLeonardo Bishop <me@leonardobishop.com>2023-08-06 12:57:55 +0100
commit31569d1a78a0731ef9efc7d462ec39acd428d588 (patch)
tree8a17373f8b950c2e93872da293216e359403595b /static
parentccb8ef7183e6d7af7bde4bb398c27379fdc7089f (diff)
Add spotify page
Diffstat (limited to 'static')
-rw-r--r--static/css/globalstyles.css4
-rw-r--r--static/css/spotify.css88
-rw-r--r--static/css/variables.css3
-rw-r--r--static/images/blank-album-cover.pngbin0 -> 2580 bytes
-rw-r--r--static/scripts/spotify.js114
5 files changed, 204 insertions, 5 deletions
diff --git a/static/css/globalstyles.css b/static/css/globalstyles.css
index 9fbb974..b6da1f9 100644
--- a/static/css/globalstyles.css
+++ b/static/css/globalstyles.css
@@ -10,6 +10,10 @@ html, body {
font-family: var(--font-sans-serif);
}
+.small {
+ font-size: 0.8rem;
+}
+
#main-container {
display: flex;
flex-direction: row;
diff --git a/static/css/spotify.css b/static/css/spotify.css
new file mode 100644
index 0000000..a3cde4d
--- /dev/null
+++ b/static/css/spotify.css
@@ -0,0 +1,88 @@
+#music-player {
+ display: flex;
+ flex-direction: row;
+ gap: 1rem;
+ padding: 1rem;
+ border: 1px solid var(--color-soft-outline);
+ background-color: var(--color-soft-fill);
+}
+
+#song-album-art {
+ width: 5rem;
+}
+
+#track {
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ gap: 0.2rem;
+}
+
+#song-title {
+ color: var(--color-text);
+ font-size: 1rem;
+}
+
+#song-details, #song-artist, #song-album {
+ color: var(--color-text-muted);
+}
+
+#song-progress-bar {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ color: var(--color-text-muted);
+ width: 100%;
+ gap: 0.5rem;
+}
+
+#song-progress-bar-fill {
+ position: relative;
+ height: 4px;
+ flex-grow: 1;
+}
+
+#song-progress-bar-background {
+ background-color: var(--color-soft-fill);
+ height: 4px;
+ border-radius: 2px;
+ width: 100%;
+}
+
+#song-progress-bar-thumb {
+ background-color: var(--color-text-link);
+ height: 4px;
+ border-radius: 2px;
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+
+#metadata {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ gap: 0.5rem;
+ margin: 0.5rem 0;
+}
+
+#connection-status {
+ color: var(--color-text-muted);
+ display: flex;
+ flex-direction: row;
+ align-items: baseline;
+ gap: 0.3rem;
+ flex-grow: 1;
+}
+
+#connection-status-indicator {
+ display: inline-block;
+ background-color: #ff4136;
+ border-radius: 50%;
+ width: 0.5rem;
+ height: 0.5rem;
+}
+
+#open-in-spotify {
+ display: none;
+}
diff --git a/static/css/variables.css b/static/css/variables.css
index 123ee30..5d8610f 100644
--- a/static/css/variables.css
+++ b/static/css/variables.css
@@ -16,6 +16,9 @@
--color-text-muted: #aaa;
--color-text-link: #ff851b;
--color-text-link-bg: rgba(255, 133, 27, 0.2);
+
+ --color-soft-outline: rgba(255, 255, 255, 0.2);
+ --color-soft-fill: rgba(255, 255, 255, 0.05);
--color-scrollbar: rgba(255, 255, 255, 0.4);
}
diff --git a/static/images/blank-album-cover.png b/static/images/blank-album-cover.png
new file mode 100644
index 0000000..aff14e2
--- /dev/null
+++ b/static/images/blank-album-cover.png
Binary files differ
diff --git a/static/scripts/spotify.js b/static/scripts/spotify.js
index e6551a8..7c62150 100644
--- a/static/scripts/spotify.js
+++ b/static/scripts/spotify.js
@@ -1,12 +1,116 @@
+const connectedColor = '#2ECC40';
+const connectingColor = '#FF851B';
+const disconnectedColor = '#FF4136';
+
+const websocketUrl = 'ws://wailt.leonardobishop.com/';
+
+let progressMillis;
+let durationMillis;
+
+let predictProgressInterval;
+
+const msToTime = (duration) => {
+ const seconds = Math.floor((duration / 1000) % 60);
+ const minutes = Math.floor((duration / (1000 * 60)) % 60);
+
+ return `${minutes}:${seconds.toString().padStart(2, '0')}`;
+}
+
+const setProgress = (progressMillis, durationMillis) => {
+ const progressPercent = durationMillis == 0 ? 0 : Math.min((progressMillis / durationMillis) * 100, 100);
+
+ const songProgress = document.getElementById('song-progress');
+ const songDuration = document.getElementById('song-duration');
+ const songProgressBarThumb = document.getElementById('song-progress-bar-thumb');
+
+ const progressTime = msToTime(progressMillis);
+ const durationTime = msToTime(durationMillis);
+
+ songProgress.innerHTML = progressTime;
+ songDuration.innerHTML = durationTime;
+ songProgressBarThumb.style.width = `${progressPercent}%`;
+}
+
+const predictProgress = () => {
+ progressMillis = Math.min(durationMillis, progressMillis + 1000);
+ setProgress(progressMillis, durationMillis);
+}
+
+const setDefaultData = () => {
+ const songTitle = document.getElementById('song-title');
+ const songArtist = document.getElementById('song-artist');
+ const songAlbum = document.getElementById('song-album');
+ const songAlbumArt = document.getElementById('song-album-art');
+
+ songTitle.innerHTML = 'No song playing';
+ songArtist.innerHTML = '';
+ songAlbum.innerHTML = '';
+ songAlbumArt.src = '/images/blank-album-cover.png';
+
+ setProgress(0, 0);
+}
+
+const setOpenInSpotify = (songUrl) => {
+ const openInSpotify = document.getElementById('open-in-spotify');
+ if (songUrl) {
+ openInSpotify.href = songUrl;
+ openInSpotify.style.display = 'block';
+ } else {
+ openInSpotify.style.display = 'none';
+ }
+}
+
const connectWebsocket = () => {
- document.getElementById('connection-status').innerHTML = "Connecting...";
- let url = new URL(window.location.href);
- url.protocol = url.protocol.replace('http', 'ws');
- const socket = new WebSocket(url);
+ const connectionStatus = document.getElementById('connection-status-text');
+ const connectionStatusIndicator = document.getElementById('connection-status-indicator');
+ const onDisconnect = () => {
+ connectionStatus.innerHTML = "Disconnected";
+ connectionStatusIndicator.style.backgroundColor = disconnectedColor;
+ setDefaultData();
+ clearInterval(predictProgressInterval);
+ }
+ const onConnect = () => {
+ connectionStatus.innerHTML = "Connected";
+ connectionStatusIndicator.style.backgroundColor = connectedColor;
+ }
+
+ connectionStatus.innerHTML = "Connecting";
+ connectionStatusIndicator.style.backgroundColor = connectingColor;
+
+ const songTitle = document.getElementById('song-title');
+ const songArtist = document.getElementById('song-artist');
+ const songAlbum = document.getElementById('song-album');
+ const songAlbumArt = document.getElementById('song-album-art');
+
+ const updateData = (data) => {
+ clearInterval(predictProgressInterval);
+ progressMillis = data.progress;
+ durationMillis = data.duration;
+
+ songTitle.innerHTML = data.title;
+ songArtist.innerHTML = data.artist;
+ songAlbum.innerHTML = data.album;
+ songAlbumArt.src = data.albumArt || '/images/blank-album-cover.png';
+
+ setProgress(progressMillis, durationMillis);
+ setOpenInSpotify(data.url);
+
+ if (data.state === 'playing') {
+ predictProgressInterval = setInterval(predictProgress, 1000);
+ }
+ }
+
+ const socket = new WebSocket(websocketUrl);
+
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
- console.log(data);
+ updateData(data);
}
+
+ socket.addEventListener('open', onConnect);
+ socket.addEventListener('close', onDisconnect);
+ socket.addEventListener('error', onDisconnect);
}
+document.addEventListener("DOMContentLoaded", setDefaultData);
document.addEventListener("DOMContentLoaded", connectWebsocket);