diff --git a/db/strimserve.db.bak b/db/strimserve.db.bak new file mode 100644 index 0000000..f9e68f4 Binary files /dev/null and b/db/strimserve.db.bak differ diff --git a/package-lock.json b/package-lock.json index 16a6363..0df2331 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "isomorphic-dompurify": "^2.0.0", "prettier": "^2.8.0", "prettier-plugin-svelte": "^2.8.1", + "sqids": "^0.3.0", "svelte": "^4.0.0", "svelte-check": "^3.0.1", "svelte-select": "^5.6.1", @@ -3477,6 +3478,11 @@ "node": ">=0.10.0" } }, + "node_modules/sqids": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/sqids/-/sqids-0.3.0.tgz", + "integrity": "sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw==" + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", diff --git a/package.json b/package.json index b7640ae..2181519 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "isomorphic-dompurify": "^2.0.0", "prettier": "^2.8.0", "prettier-plugin-svelte": "^2.8.1", + "sqids": "^0.3.0", "svelte": "^4.0.0", "svelte-check": "^3.0.1", "svelte-select": "^5.6.1", diff --git a/scripts/generate_iconfont_subset.sh b/scripts/generate_iconfont_subset.sh index 3a6a5e6..12e7186 100755 --- a/scripts/generate_iconfont_subset.sh +++ b/scripts/generate_iconfont_subset.sh @@ -14,6 +14,9 @@ unicodePoints=( "e04e" # volume_mute "e04d" # volume_down "e050" # volume_up + "e01f" # fast_forward + "e83a" # star_border + "e838" # star ) unicodeStr=$( IFS=, diff --git a/src/lib/stores.js b/src/lib/stores.js index 6ec80d5..2607d1b 100644 --- a/src/lib/stores.js +++ b/src/lib/stores.js @@ -1,7 +1,19 @@ import { writable } from 'svelte/store'; +import { browser } from '$app/environment'; export const currentStream = writable({}); export const currentSongIndex = writable(0); + +export const favoritedStreams = writable( + new Set(JSON.parse((browser && localStorage.getItem('favoritedStreams')) || '[]')) +); + +if (browser) { + favoritedStreams.subscribe((val) => { + localStorage.setItem('favoritedStreams', JSON.stringify(Array.from(val))); + }); +} + export const tagList = [ 'acoustic', 'electronic', @@ -50,7 +62,6 @@ function locationOf(element, array, start, end) { export function getSongAtTime(currentTime) { return locationOf(currentTime, timestampList) - 1; - } // less operations needed when doing regular lookups @@ -58,19 +69,17 @@ export function updateCurrentSong(currentTime, songIndex) { function updateCurrentSongRecurse(songIndex) { if (currentTime >= timestampList[songIndex + 2]) { return updateCurrentSongRecurse(songIndex + 1); - } - else if (currentTime < timestampList[songIndex + 1]) { + } else if (currentTime < timestampList[songIndex + 1]) { return updateCurrentSongRecurse(songIndex - 1); } return songIndex; } currentSongIndex.set(updateCurrentSongRecurse(songIndex)); - } export function updateCurrentStream(stream) { currentStream.set(stream); - timestampList = [-Infinity, ...stream.tracks.map(track => track[0]), Infinity]; + timestampList = [-Infinity, ...stream.tracks.map((track) => track[0]), Infinity]; currentSongIndex.set(0); } diff --git a/src/lib/utils.js b/src/lib/utils.js new file mode 100644 index 0000000..aeee289 --- /dev/null +++ b/src/lib/utils.js @@ -0,0 +1,37 @@ +import Sqids from 'sqids'; + +let sqids = new Sqids({ minLength: 6 }); + +export function hashcode(str) { + for (var i = 0, h = 9; i < str.length; ) h = Math.imul(h ^ str.charCodeAt(i++), 9 ** 9); + return h ^ (h >>> 9); +} + +// for mnemonic display +export function shorthandCode(str) { + return sqids.encode([hashcode(str) & 0xffff]); +} + +// for tag display +export function hashColor(str) { + const hash = hashcode(str); + return `hsl(${hash % 360}, ${65 + (hash % 30) + 1}%, ${85 + (hash % 10) + 1}%)`; +} + +export function formatSecondsToHms(s) { + s = Number(s); + var h = Math.floor(s / 3600); + var m = Math.ceil((s % 3600) / 60); + + var hDisplay = h > 0 ? h + (h == 1 ? ' hr' : ' hrs') + (m > 0 ? ', ' : '') : ''; + var mDisplay = m > 0 ? m + (m == 1 ? ' min' : ' mins') : ''; + return hDisplay + mDisplay; +} + +export function formatDate(unix_timestamp) { + return new Date(unix_timestamp).toISOString().split('T')[0]; +} + +export function formatTrackTime(s) { + return new Date(s * 1000).toISOString().slice(11, 19); +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index df85229..4ef93cd 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -5,6 +5,7 @@ margin: 0; padding: 0; background: url(/assets/tile.png) repeat fixed; + overflow-y: hidden; } * { @@ -18,6 +19,13 @@ src: url('/fonts/MaterialIcons-Regular-subset.woff2') format('woff2'); } + @font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 300; + src: url('/fonts/Montserrat-Light.woff2') format('woff2'); + } + .material-icons { font-family: 'Material Icons'; font-weight: normal; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index dccb81d..a686f39 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1 +1,8 @@ -lol + diff --git a/src/routes/streams/+layout.svelte b/src/routes/streams/+layout.svelte index 8d2fa52..dcfdfc1 100644 --- a/src/routes/streams/+layout.svelte +++ b/src/routes/streams/+layout.svelte @@ -21,6 +21,7 @@ overflow-wrap: break-word; margin: 0.5em; scrollbar-gutter: stable; + scrollbar-width: thin; } #content { diff --git a/src/routes/streams/Sidebar.svelte b/src/routes/streams/Sidebar.svelte index 9c08763..da86587 100644 --- a/src/routes/streams/Sidebar.svelte +++ b/src/routes/streams/Sidebar.svelte @@ -1,30 +1,17 @@ -

streams

- -
+
+
-
- -
+ + {formatDate(stream['stream_date'])} + + {formatSecondsToHms(stream['length_seconds'])} + + + + + + + {/each} + diff --git a/src/routes/streams/TagSelect.svelte b/src/routes/streams/TagSelect.svelte index 0c01062..3f7027f 100644 --- a/src/routes/streams/TagSelect.svelte +++ b/src/routes/streams/TagSelect.svelte @@ -1,71 +1,72 @@ - {item.label} - -
+
+ +
diff --git a/src/routes/streams/[stream_id]/+page.svelte b/src/routes/streams/[stream_id]/+page.svelte index ad1d099..69d12b3 100644 --- a/src/routes/streams/[stream_id]/+page.svelte +++ b/src/routes/streams/[stream_id]/+page.svelte @@ -2,7 +2,6 @@ import StreamPage from './StreamPage.svelte'; import MetadataEditor from './MetadataEditor.svelte'; import Player from './Player.svelte'; - import { page } from '$app/stores'; import { dev } from '$app/environment'; import { currentStream, updateCurrentStream } from '$lib/stores.js'; @@ -25,7 +24,7 @@ diff --git a/src/routes/streams/[stream_id]/MetadataEditor.svelte b/src/routes/streams/[stream_id]/MetadataEditor.svelte index 61406ab..7a36243 100644 --- a/src/routes/streams/[stream_id]/MetadataEditor.svelte +++ b/src/routes/streams/[stream_id]/MetadataEditor.svelte @@ -3,6 +3,7 @@ import { tagList } from '$lib/stores.js'; export let original; + let tagMap = new Map(); // Create a mapping of tags and their checked status @@ -53,7 +54,6 @@ diff --git a/src/routes/streams/[stream_id]/StreamPage.svelte b/src/routes/streams/[stream_id]/StreamPage.svelte index 8a6967c..1bfb318 100644 --- a/src/routes/streams/[stream_id]/StreamPage.svelte +++ b/src/routes/streams/[stream_id]/StreamPage.svelte @@ -1,5 +1,6 @@ +
+

{formattedStreamDate}

+

ID: {shorthandCode($currentStream.id)}

+
Tags: {$currentStream.tags.join(', ')}
+
+
{@html carta.renderSSR($currentStream.description || 'No description available.')}
-
+
{#each $currentStream.tracks as track, i} - jumpToTrack(track[0])} class:current={i == $currentSongIndex}> - - - + + + + {/each}
TimestampArtistTitle
{prettyPrintTime(track[0])}{track[1]}{track[2]}
{formatTrackTime(track[0])} + + {track[1]}{track[2]}
diff --git a/static/assets/mascot-dithered-alt.png b/static/assets/mascot-dithered-alt.png new file mode 100755 index 0000000..13c92a1 Binary files /dev/null and b/static/assets/mascot-dithered-alt.png differ diff --git a/static/assets/mascot-dithered.png b/static/assets/mascot-dithered.png new file mode 100755 index 0000000..17f0e1c Binary files /dev/null and b/static/assets/mascot-dithered.png differ diff --git a/static/assets/mascot-glitched.png b/static/assets/mascot-glitched.png new file mode 100755 index 0000000..697a409 Binary files /dev/null and b/static/assets/mascot-glitched.png differ diff --git a/static/assets/mascot.png b/static/assets/mascot.png new file mode 100644 index 0000000..358b33c Binary files /dev/null and b/static/assets/mascot.png differ diff --git a/static/assets/result.png b/static/assets/result.png new file mode 100644 index 0000000..67ce056 Binary files /dev/null and b/static/assets/result.png differ diff --git a/static/fonts/MaterialIcons-Regular-subset.woff2 b/static/fonts/MaterialIcons-Regular-subset.woff2 index a305571..acd3da0 100644 Binary files a/static/fonts/MaterialIcons-Regular-subset.woff2 and b/static/fonts/MaterialIcons-Regular-subset.woff2 differ diff --git a/static/fonts/Montserrat-Light.woff2 b/static/fonts/Montserrat-Light.woff2 new file mode 100644 index 0000000..70cfdee Binary files /dev/null and b/static/fonts/Montserrat-Light.woff2 differ