Skip to content

Commit 8ede8d9

Browse files
lgtm (#89)
* lgtm * chore: bump version --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent da1cc7a commit 8ede8d9

File tree

8 files changed

+140
-53
lines changed

8 files changed

+140
-53
lines changed

MyMusicClientSveltePwa/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MyMusicClientSveltePwa/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "mymusicclientsveltepwa",
33
"private": true,
4-
"version": "0.1.11-beta",
4+
"version": "0.1.12",
55
"type": "module",
66
"scripts": {
77
"dev": "vite --host",

MyMusicClientSveltePwa/src/App.svelte

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
import { onMount, onDestroy, setContext } from "svelte";
66
import { get, writable } from "svelte/store";
7-
import { initializeRouteService, pathName, navigateTo, component, componentParams } from "./lib/scripts/routeService.js";
7+
import { initializeRouteService, pathName, navigateTo, component as currentView, componentParams } from "./lib/scripts/routeService.js";
88
import PlayerBar from "./lib/components/PlayerBar.svelte";
99
import Modals from "./lib/components/Modals.svelte";
1010
import { initializePlaylistService, deleteCurrentPlaylist } from "./lib/scripts/playlistService.js";
@@ -14,7 +14,7 @@
1414
import SearchBar from "./lib/components/SearchBar.svelte";
1515
1616
$: $pathName;
17-
$: $component;
17+
$: $currentView;
1818
1919
// @ts-ignore
2020
export const version = __APP_VERSION__;
@@ -33,7 +33,7 @@
3333
}
3434
3535
onMount(() => {
36-
component.subscribe((value) => {
36+
currentView.subscribe((value) => {
3737
// Whenever the component changes, enable auto scroll
3838
preventAutoScroll()
3939
});
@@ -59,6 +59,7 @@
5959
<header class="top-bar">
6060
<div class="top-bar-title text-center">MyMusicBox<span style="font-size: 0.8rem;">(v{version})</span></div>
6161
<div class="row">
62+
<!-- Configurable via js/storage/options etc per page / component -->
6263
<div class="col-12 mt-2 justify-content-center">
6364
<!-- Search Bar -->
6465
<SearchBar />
@@ -69,7 +70,7 @@
6970
<!-- Scrollable Content -->
7071
<main class="{($autoScroll ? "scrollable-content" :"none-scrollable-content")} ">
7172
<div class="container-fluid">
72-
<svelte:component this={$component} {...$componentParams} />
73+
<svelte:component this={$currentView} {...$componentParams} />
7374
</div>
7475
</main>
7576

MyMusicClientSveltePwa/src/lib/components/Playlist.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
songCount = getCachedPlaylistSongs(playlist.id).length;
2424
});
2525
</script>
26-
2726
{#if playlist}
2827
<!-- Playlist Card -->
2928
<!-- svelte-ignore a11y_click_events_have_key_events -->
@@ -38,7 +37,7 @@
3837
</article>
3938
</div>
4039
{:else}
41-
<p>No playlist available.</p>
40+
<p>No playlist founnd with id: {playlist.id}.</p>
4241
{/if}
4342

4443
<style>

MyMusicClientSveltePwa/src/lib/components/SearchBar.svelte

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,54 @@
11
<script>
22
// @ts-nocheck
33
import { searchQuery } from "../scripts/util";
4+
import { getSearchQueryFromStorage, setSearchQueryInStorage } from "../scripts/storageService";
5+
import { onMount } from "svelte";
6+
import { component } from "../scripts/routeService";
7+
8+
let query = '';
9+
10+
onMount(() => {
11+
// Initialize the search query from storage
12+
const storedQuery = getSearchQueryFromStorage();
13+
if (storedQuery && storedQuery.length > 0) {
14+
searchQuery.set(storedQuery);
15+
query = storedQuery;
16+
}
17+
18+
// There is a x on right side of the input that triggers a 'search' event when clicked
19+
// it cleares the input but we also need to clear our stores and storage... :))))) javaScript
20+
document.getElementById('search-input').addEventListener('search', (e) => {
21+
searchQuery.set('');
22+
setSearchQueryInStorage('');
23+
query = '';
24+
});
25+
26+
// update component on search query change
27+
component.subscribe(() => {
28+
searchQuery.set(getSearchQueryFromStorage());
29+
});
30+
});
431
</script>
532

633
<div class="search border border-1 border-dark" role="search" aria-label="Search music">
734
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
835
<path stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" d="M21 21l-4.35-4.35" />
936
<circle cx="11" cy="11" r="6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
1037
</svg>
11-
<input
38+
<input
39+
id="search-input"
40+
bind:value={query}
1241
type="search"
13-
on:keydown={(e) => {
14-
searchQuery.set(e.target.value);
42+
on:keyup={(e) => {
43+
setSearchQueryInStorage(query);
44+
searchQuery.set(query);
45+
}}
46+
on:change={(e) => {
47+
console.log("change event", e);
48+
setSearchQueryInStorage(query);
49+
searchQuery.set(query);
1550
}}
16-
placeholder="Search music #not working jet..."
51+
placeholder="Search and you shall find..."
1752
aria-label="Search"
1853
/>
1954
</div>

MyMusicClientSveltePwa/src/lib/pages/Playlists.svelte

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,64 @@
77
import SongComponent from "../components/Song.svelte";
88
import VirtualList from "@sveltejs/svelte-virtual-list/VirtualList.svelte";
99
import Song from "../components/Song.svelte";
10+
import { searchQuery } from "../scripts/util.js";
1011
11-
const updateIntervalTimeOutInMs = 750; // Update every 750 ms
12+
const updateIntervalTimeOutInMs = 250; // Update every 250 ms 1/4 of a second
1213
let intervalId;
1314
let updating = false;
1415
let start;
1516
let end;
1617
17-
export let playlistId = -1;
18-
let visibleCount = 100;
19-
20-
function loadMore() {
21-
visibleCount += 100;
22-
}
23-
2418
let songs = writable([]);
2519
let readableSongs = [];
20+
let visibleSongs = writable([]);
21+
let searchQueryUnsubscribe;
22+
let filter = "";
23+
24+
let componentParameters = $props();
25+
let playlistId = componentParameters["playlistId"];
2626
2727
onMount(() => {
28+
searchQueryUnsubscribe = searchQuery.subscribe((value) => {
29+
if (!value) {
30+
filter = "";
31+
visibleSongs.set(readableSongs);
32+
return;
33+
}
34+
35+
visibleSongs.set(readableSongs.filter((song) => song.name.toLowerCase().includes(value.toLowerCase())));
36+
37+
filter = value;
38+
});
39+
2840
let auto = getContext("preventAutoScroll");
2941
auto(null);
3042
3143
songs.set(getCachedPlaylistSongs(playlistId));
3244
setContext("playOrPauseSong", playOrPause);
3345
readableSongs = getCachedPlaylistSongs(playlistId);
3446
47+
// This is javascript and it might break, it might not until we look in to the box like shrowdinger's cat, but for bugs
48+
// @me-not-having-the-enegy-to-write-a-better-filter-function
49+
if (filter && filter.length > 0) {
50+
visibleSongs.set(readableSongs.filter((song) => song.name.toLowerCase().includes(filter.toLowerCase())));
51+
} else {
52+
visibleSongs.set(readableSongs);
53+
}
54+
3555
intervalId = setInterval(() => {
3656
if (updating) return; // Prevent multiple updates at the same time
3757
updating = true;
3858
readableSongs = getCachedPlaylistSongs(playlistId);
59+
60+
// This is javascript and it might break, it might not until we look in to the box like shrowdinger's cat, but for bugs
61+
// @me-not-having-the-enegy-to-write-a-better-filter-function
62+
if (filter && filter.length > 0) {
63+
visibleSongs.set(readableSongs.filter((song) => song.name.toLowerCase().includes(filter.toLowerCase())));
64+
} else {
65+
visibleSongs.set(readableSongs);
66+
}
67+
3968
songs.set(readableSongs);
4069
updateCurrentPlaylist(playlistId);
4170
updating = false;
@@ -49,28 +78,29 @@
4978
5079
onDestroy(() => {
5180
clearInterval(intervalId);
81+
if (searchQueryUnsubscribe) searchQueryUnsubscribe(); // stop listening
5282
});
5383
</script>
5484

55-
{#if readableSongs.length > 0}
56-
<!-- <p>showing items {start}-{end}</p> -->
57-
<div class='container-cs border border-dark'>
58-
<VirtualList items={readableSongs} bind:start bind:end let:item>
59-
<SongComponent song={item} {playlistId} />
60-
</VirtualList>
61-
</div>
85+
{#if $visibleSongs && $visibleSongs.length > 0}
86+
<!-- <p>showing items {start}-{end}</p> -->
87+
<div class="container-cs border border-dark">
88+
<VirtualList items={$visibleSongs} let:item>
89+
<SongComponent song={item} playlistId={componentParameters["playlistId"]} />
90+
</VirtualList>
91+
</div>
6292
{:else}
63-
<p>No songs in playlist.</p>
93+
<p>No songs found in playlist.</p>
6494
{/if}
6595

6696
<style>
67-
.container-cs {
97+
.container-cs {
6898
background: #2a2a2a;
69-
border-top: 1px solid #333;
70-
border-bottom: 1px solid #333;
71-
/* min-height: calc(100vh - 30vh); */
72-
height: calc(100vh - 35vh);
99+
border-top: 1px solid #333;
100+
border-bottom: 1px solid #333;
101+
/* min-height: calc(100vh - 30vh); */
102+
height: calc(100vh - 35vh);
73103
padding-right: unset;
74104
padding-left: unset;
75-
}
105+
}
76106
</style>

MyMusicClientSveltePwa/src/lib/scripts/storageService.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const CurrentSongIndexKey = "currentSongIndex";
1010
const CurrentShuffeldPlaylistKey = "currentShuffledPlaylist";
1111
const CurrentSongTimeKey = "currentSongTime";
1212
const ConfigKey = "appConfig";
13+
const ConfigKeySearchQyery = "searchQuery";
1314

1415
export let appConfiguration = writable(getConfiguration());
1516

@@ -18,6 +19,14 @@ export function setConfiguration(config) {
1819
setItem(ConfigKey, config);
1920
}
2021

22+
export function setSearchQueryInStorage(query) {
23+
setItem(ConfigKeySearchQyery, query);
24+
}
25+
26+
export function getSearchQueryFromStorage() {
27+
return getItem(ConfigKeySearchQyery) || '';
28+
}
29+
2130
export function setCachedPlaylists(playlists) {
2231
setItem(PlaylistsKey, playlists);
2332
}

MyMusicClientSveltePwa/src/lib/scripts/util.js

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { writable } from "svelte/store";
22

3-
export let searchQuery = writable();
3+
export let searchQuery = writable('');
44

55
// Mulberry32 PRNG
66
function mulberry32(seed) {
77
return function () {
88
let t = (seed += 0x6d2b79f5);
99
t = Math.imul(t ^ (t >>> 15), t | 1);
1010
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
11-
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
11+
return ((t ^ (t >>> 16)) >>> 0) / 4294967296;
1212
};
1313
}
1414

@@ -25,45 +25,58 @@ function generateSeed() {
2525

2626
// Fisher-Yates shuffle with optional seed
2727
export function shuffleArray(array) {
28-
const seed = generateSeed();
29-
const rng = mulberry32(seed);
30-
31-
for (let i = array.length - 1; i > 0; i--) {
32-
const j = Math.floor(rng() * (i + 1));
28+
const rng = mulberry32(generateSeed());
29+
let i = array.length;
30+
while (i > 1) {
31+
const j = Math.floor(rng() * i--);
3332
[array[i], array[j]] = [array[j], array[i]];
3433
}
35-
3634
return array;
3735
}
3836

3937
export function getSearchParameters() {
40-
const searchParams = new URLSearchParams(window.location.search);
4138
const result = {};
42-
for (const [key, value] of searchParams.entries()) {
43-
if (result[key]) {
44-
// If key already exists, convert to array or push into existing array
45-
result[key] = Array.isArray(result[key]) ? [...result[key], parseValue(value)] : [result[key], parseValue(value)];
39+
for (const [key, value] of new URLSearchParams(window.location.search)) {
40+
const parsed = parseValue(value);
41+
if (key in result) {
42+
result[key] = Array.isArray(result[key]) ? [...result[key], parsed] : [result[key], parsed];
4643
} else {
47-
result[key] = parseValue(value);
44+
result[key] = parsed;
4845
}
4946
}
5047
return result;
5148
}
5249

50+
/**
51+
* Parses a string value to its appropriate type.
52+
* @param {string} value
53+
* @returns {boolean|number|string|null|undefined}
54+
*/
5355
export function parseValue(value) {
5456
if (value === "true") return true;
5557
if (value === "false") return false;
56-
if (!isNaN(value) && value.trim() !== "") return Number(value);
58+
if (value == null) return value;
59+
const trimmed = value.trim();
60+
if (/^-?\d+(\.\d+)?$/.test(trimmed)) return Number(trimmed);
5761
return value;
5862
}
5963

64+
/**
65+
* Creates a URL search string from an object of parameters.
66+
* @param {Object} params
67+
* @returns {string}
68+
*/
6069
export function createSearchParameters(params) {
6170
const searchParams = new URLSearchParams();
6271
for (const key in params) {
63-
if (Array.isArray(params[key])) {
64-
params[key].forEach((value) => searchParams.append(key, value));
72+
const val = params[key];
73+
if (val == null) continue;
74+
if (Array.isArray(val)) {
75+
for (const v of val) searchParams.append(key, v);
76+
} else if (typeof val === "object") {
77+
searchParams.set(key, JSON.stringify(val));
6578
} else {
66-
searchParams.set(key, params[key]);
79+
searchParams.set(key, val);
6780
}
6881
}
6982
return searchParams.toString();

0 commit comments

Comments
 (0)