@freqhole/playlistz 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/config.json +11 -0
- package/.changeset/nice-wolves-thank.md +5 -0
- package/.freqhole-versions.json +4 -0
- package/.github/copilot-instructions.md +201 -0
- package/.github/workflows/changesets.yml +50 -0
- package/.github/workflows/npm-publish.yml +124 -0
- package/.github/workflows/pr-checks.yml +103 -0
- package/README.md +30 -0
- package/build-component.js +141 -0
- package/build-zip-bundle-lib.js +44 -0
- package/config/playwright.config.ts +47 -0
- package/config/vite.config.ts +44 -0
- package/config/vitest.config.ts +39 -0
- package/dist/assets/automerge_wasm_bg-Cik4BF9l.wasm +0 -0
- package/dist/assets/index-CbOXzGiA.js +216 -0
- package/dist/assets/index-CbOXzGiA.js.map +1 -0
- package/dist/assets/index-TvJ6RFpy.css +1 -0
- package/dist/assets/midden-DceCrT_L.js +2 -0
- package/dist/assets/midden-DceCrT_L.js.map +1 -0
- package/dist/assets/midden_bg-BLhfGIU-.wasm +0 -0
- package/dist/index.html +55 -0
- package/dist/sw.js +134 -0
- package/docs/AUTOMERGE_P2P_PLAN.md +233 -0
- package/docs/COLLABORATIVE_SHARING_PLAN.md +188 -0
- package/docs/E2E_TESTID_PLAN.md +234 -0
- package/docs/IROH_P2P_PLAN.md +302 -0
- package/docs/ROADMAP.md +695 -0
- package/docs/TODO.md +167 -0
- package/docs/bundle-embedding-plan.md +134 -0
- package/docs/standalone-refactor.md +184 -0
- package/e2e/all-playlists.spec.ts +220 -0
- package/e2e/audio-player.spec.ts +226 -0
- package/e2e/collaborative-features.spec.ts +229 -0
- package/e2e/contexts.ts +238 -0
- package/e2e/edit-panel.spec.ts +87 -0
- package/e2e/fixtures/bare-glitch-1s.m4a +0 -0
- package/e2e/fixtures/bare-glitch-1s.mp3 +0 -0
- package/e2e/fixtures/bare-glitch-1s.ogg +0 -0
- package/e2e/fixtures/chord-stack-3s.wav +0 -0
- package/e2e/fixtures/cover-anim.gif +0 -0
- package/e2e/fixtures/cover-blue.png +0 -0
- package/e2e/fixtures/cover-checkers.png +0 -0
- package/e2e/fixtures/cover-gradient.jpg +0 -0
- package/e2e/fixtures/cover-mono.gif +0 -0
- package/e2e/fixtures/cover-noise.png +0 -0
- package/e2e/fixtures/cover-plasma.webp +0 -0
- package/e2e/fixtures/cover-portrait.jpg +0 -0
- package/e2e/fixtures/cover-red.png +0 -0
- package/e2e/fixtures/cover-thumb.jpg +0 -0
- package/e2e/fixtures/cover-wide.webp +0 -0
- package/e2e/fixtures/generate.mjs +257 -0
- package/e2e/fixtures/long-drone-90s.mp3 +0 -0
- package/e2e/fixtures/noisy-binaural-8s.mp3 +0 -0
- package/e2e/fixtures/tagged-a3-4s.m4a +0 -0
- package/e2e/fixtures/tagged-a3-4s.mp3 +0 -0
- package/e2e/fixtures/tagged-a3-4s.ogg +0 -0
- package/e2e/fixtures/tagged-c5-3s.m4a +0 -0
- package/e2e/fixtures/tagged-c5-3s.mp3 +0 -0
- package/e2e/fixtures/tagged-c5-3s.ogg +0 -0
- package/e2e/fixtures/tagged-f4-6s.m4a +0 -0
- package/e2e/fixtures/tagged-f4-6s.mp3 +0 -0
- package/e2e/fixtures/tagged-f4-6s.ogg +0 -0
- package/e2e/fixtures/tone-220hz-10s.wav +0 -0
- package/e2e/fixtures/tone-440hz-2s.wav +0 -0
- package/e2e/fixtures/tone-880hz-5s.wav +0 -0
- package/e2e/fixtures/tone-stereo-3s.wav +0 -0
- package/e2e/fixtures/user-provided/README.md +1 -0
- package/e2e/helpers/app.ts +143 -0
- package/e2e/helpers/hooks.ts +133 -0
- package/e2e/helpers/index.ts +12 -0
- package/e2e/helpers/media.ts +125 -0
- package/e2e/helpers.ts +10 -0
- package/e2e/p2p-collaboration.spec.ts +356 -0
- package/e2e/p2p-multi-peer.spec.ts +723 -0
- package/e2e/p2p-states.spec.ts +302 -0
- package/e2e/playback.spec.ts +56 -0
- package/e2e/playlist-crud.spec.ts +126 -0
- package/e2e/share-link-autoplay.spec.ts +129 -0
- package/e2e/sharing-access.spec.ts +205 -0
- package/e2e/sharing.spec.ts +195 -0
- package/e2e/song-cache-state.spec.ts +202 -0
- package/e2e/zip-bundle.spec.ts +855 -0
- package/eslint.config.js +114 -0
- package/index.html +54 -0
- package/package.json +119 -0
- package/public/sw.js +134 -0
- package/scripts/use-local.mjs +37 -0
- package/scripts/use-published.mjs +37 -0
- package/src/App.tsx +9 -0
- package/src/cli/check.ts +164 -0
- package/src/cli/generate.ts +184 -0
- package/src/cli/http.ts +88 -0
- package/src/cli/index.ts +65 -0
- package/src/cli/init.ts +18 -0
- package/src/components/AllPlaylistsPanel.tsx +713 -0
- package/src/components/AudioPlayer.tsx +122 -0
- package/src/components/MarqueeText.tsx +101 -0
- package/src/components/PlaylistCoverModal.tsx +519 -0
- package/src/components/PlaylistEditPanel.tsx +803 -0
- package/src/components/PlaylistSharePanel.tsx +1020 -0
- package/src/components/ShareLinkKnockPanel.tsx +144 -0
- package/src/components/SharePanel.tsx +584 -0
- package/src/components/SongEditModal.tsx +453 -0
- package/src/components/SongEditPanel.tsx +578 -0
- package/src/components/SongRow.tsx +689 -0
- package/src/components/index.tsx +494 -0
- package/src/components/playlist/index.tsx +1203 -0
- package/src/context/PlaylistzContext.tsx +74 -0
- package/src/dev-hooks.ts +35 -0
- package/src/hooks/createDocIndexQuery.ts +53 -0
- package/src/hooks/createDocStore.test.ts +303 -0
- package/src/hooks/createDocStore.ts +90 -0
- package/src/hooks/useDragAndDrop.test.ts +474 -0
- package/src/hooks/useDragAndDrop.ts +400 -0
- package/src/hooks/useImageModal.test.ts +174 -0
- package/src/hooks/useImageModal.ts +201 -0
- package/src/hooks/usePlaylistManager.test.ts +453 -0
- package/src/hooks/usePlaylistManager.ts +685 -0
- package/src/hooks/usePlaylistsQuery.test.tsx +120 -0
- package/src/hooks/usePlaylistsQuery.ts +44 -0
- package/src/hooks/useSongState.test.ts +236 -0
- package/src/hooks/useSongState.ts +114 -0
- package/src/hooks/useUIState.ts +71 -0
- package/src/index.tsx +18 -0
- package/src/services/audioService.dev.ts +22 -0
- package/src/services/audioService.test.ts +1226 -0
- package/src/services/audioService.ts +1395 -0
- package/src/services/automergeRepo.test.ts +269 -0
- package/src/services/automergeRepo.ts +226 -0
- package/src/services/blobTransferService.dev.ts +119 -0
- package/src/services/blobTransferService.test.ts +441 -0
- package/src/services/blobTransferService.ts +702 -0
- package/src/services/docIndexService.test.ts +179 -0
- package/src/services/docIndexService.ts +118 -0
- package/src/services/fileProcessingService.test.ts +554 -0
- package/src/services/fileProcessingService.ts +239 -0
- package/src/services/imageService.test.ts +701 -0
- package/src/services/imageService.ts +365 -0
- package/src/services/indexedDBService.integration.test.ts +104 -0
- package/src/services/indexedDBService.test.ts +202 -0
- package/src/services/indexedDBService.ts +436 -0
- package/src/services/offlineService.test.ts +661 -0
- package/src/services/offlineService.ts +382 -0
- package/src/services/p2pService.test.ts +305 -0
- package/src/services/p2pService.ts +344 -0
- package/src/services/playlistDocService.test.ts +448 -0
- package/src/services/playlistDocService.ts +707 -0
- package/src/services/playlistDownloadService.test.ts +674 -0
- package/src/services/playlistDownloadService.ts +389 -0
- package/src/services/sharingService.test.ts +812 -0
- package/src/services/sharingService.ts +1073 -0
- package/src/services/sharingState.ts +161 -0
- package/src/services/songReactivity.test.ts +620 -0
- package/src/services/songReactivity.ts +145 -0
- package/src/services/standaloneService.test.ts +1025 -0
- package/src/services/standaloneService.ts +588 -0
- package/src/services/streamingAudioService.test.ts +275 -0
- package/src/services/streamingAudioService.ts +166 -0
- package/src/styles.css +428 -0
- package/src/test-setup.ts +547 -0
- package/src/types/global.d.ts +40 -0
- package/src/types/playlist.ts +99 -0
- package/src/utils/hashUtils.ts +41 -0
- package/src/utils/log.ts +97 -0
- package/src/utils/m3u.test.ts +172 -0
- package/src/utils/m3u.ts +136 -0
- package/src/utils/mockData.ts +166 -0
- package/src/utils/standaloneTemplates.test.ts +175 -0
- package/src/utils/standaloneTemplates.ts +83 -0
- package/src/utils/swTemplate.ts +84 -0
- package/src/utils/timeUtils.ts +166 -0
- package/src/utils/typeGuards.ts +171 -0
- package/src/web-component.tsx +98 -0
- package/src/zip-bundle/index.ts +7 -0
- package/src/zip-bundle/m3u.ts +45 -0
- package/src/zip-bundle/types.ts +50 -0
- package/src/zip-bundle/utils.ts +33 -0
- package/src/zip-bundle/zipBuilder.ts +309 -0
- package/tailwind.config.js +55 -0
- package/tsconfig.json +43 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { createSignal } from "solid-js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Global Song Reactivity System
|
|
5
|
+
*
|
|
6
|
+
* This module provides a reactive signal system that notifies all interested
|
|
7
|
+
* components when songs are updated in the database. This solves the issue
|
|
8
|
+
* where SongRow components don't immediately reflect changes after editing.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* - Import `songUpdateTrigger` in components that need to react to song changes
|
|
12
|
+
* - Import `triggerSongUpdate` in services that modify songs
|
|
13
|
+
* - Call `triggerSongUpdate()` after any song database operation
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Global signal that increments whenever any song is updated
|
|
17
|
+
const [songUpdateTrigger, setSongUpdateTrigger] = createSignal(0);
|
|
18
|
+
|
|
19
|
+
// Map to track which songs have been updated (for debugging and optimization)
|
|
20
|
+
const updatedSongs = new Map<string, number>();
|
|
21
|
+
|
|
22
|
+
// Map of song-specific signals for targeted reactivity
|
|
23
|
+
const songSpecificSignals = new Map<
|
|
24
|
+
string,
|
|
25
|
+
ReturnType<typeof createSignal<number>>
|
|
26
|
+
>();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Reactive signal that triggers whenever any song is updated.
|
|
30
|
+
* Components can access this signal to know when to refetch song data.
|
|
31
|
+
*/
|
|
32
|
+
export { songUpdateTrigger };
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Trigger a global song update notification.
|
|
36
|
+
* Call this after any song modification operation.
|
|
37
|
+
*
|
|
38
|
+
* @param songId - Optional song ID for tracking specific song updates
|
|
39
|
+
*/
|
|
40
|
+
export function triggerSongUpdate(songId?: string): void {
|
|
41
|
+
setSongUpdateTrigger((prev) => prev + 1);
|
|
42
|
+
|
|
43
|
+
if (songId) {
|
|
44
|
+
updatedSongs.set(songId, Date.now());
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get the current update trigger value.
|
|
50
|
+
* Useful for creating reactive dependencies.
|
|
51
|
+
*/
|
|
52
|
+
export function getSongUpdateTrigger(): number {
|
|
53
|
+
return songUpdateTrigger();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check when a specific song was last updated.
|
|
58
|
+
* Returns timestamp or undefined if song hasn't been tracked.
|
|
59
|
+
*/
|
|
60
|
+
export function getLastUpdateTime(songId: string): number | undefined {
|
|
61
|
+
return updatedSongs.get(songId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get or create a song-specific reactivity signal
|
|
66
|
+
*/
|
|
67
|
+
export function getSongSpecificTrigger(songId: string): () => number {
|
|
68
|
+
if (!songSpecificSignals.has(songId)) {
|
|
69
|
+
songSpecificSignals.set(songId, createSignal(0));
|
|
70
|
+
}
|
|
71
|
+
const [getter] = songSpecificSignals.get(songId)!;
|
|
72
|
+
return getter;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Trigger update for a specific song only
|
|
77
|
+
*/
|
|
78
|
+
export function triggerSpecificSongUpdate(songId: string): void {
|
|
79
|
+
if (songSpecificSignals.has(songId)) {
|
|
80
|
+
const [, setter] = songSpecificSignals.get(songId)!;
|
|
81
|
+
setter((prev) => prev + 1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Also update the tracking map
|
|
85
|
+
updatedSongs.set(songId, Date.now());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Clear the update history (useful for cleanup or testing).
|
|
90
|
+
*/
|
|
91
|
+
export function clearUpdateHistory(): void {
|
|
92
|
+
updatedSongs.clear();
|
|
93
|
+
songSpecificSignals.clear();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get update statistics for debugging.
|
|
98
|
+
*/
|
|
99
|
+
export function getUpdateStats() {
|
|
100
|
+
return {
|
|
101
|
+
totalUpdates: songUpdateTrigger(),
|
|
102
|
+
trackedSongs: updatedSongs.size,
|
|
103
|
+
recentUpdates: Array.from(updatedSongs.entries())
|
|
104
|
+
.sort(([, a], [, b]) => b - a)
|
|
105
|
+
.slice(0, 10), // Last 10 updates
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Enhanced trigger function with metadata for complex scenarios.
|
|
111
|
+
*
|
|
112
|
+
* @param options - Update options
|
|
113
|
+
*/
|
|
114
|
+
export function triggerSongUpdateWithOptions(options: {
|
|
115
|
+
songId?: string;
|
|
116
|
+
type?: "edit" | "create" | "delete" | "reorder";
|
|
117
|
+
metadata?: Record<string, unknown>;
|
|
118
|
+
specificOnly?: boolean; // Only trigger specific song, not global
|
|
119
|
+
}): void {
|
|
120
|
+
const { songId, specificOnly = false } = options;
|
|
121
|
+
|
|
122
|
+
if (songId && specificOnly) {
|
|
123
|
+
// Only trigger the specific song update
|
|
124
|
+
triggerSpecificSongUpdate(songId);
|
|
125
|
+
} else {
|
|
126
|
+
// Use the existing global trigger behavior
|
|
127
|
+
triggerSongUpdate(songId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Development helpers
|
|
132
|
+
if (
|
|
133
|
+
typeof globalThis !== "undefined" &&
|
|
134
|
+
(globalThis as Record<string, unknown>).__DEV__
|
|
135
|
+
) {
|
|
136
|
+
// Expose debugging functions to window in development
|
|
137
|
+
(globalThis as Record<string, unknown>).__songReactivity = {
|
|
138
|
+
getSongUpdateTrigger,
|
|
139
|
+
getUpdateStats,
|
|
140
|
+
clearUpdateHistory,
|
|
141
|
+
triggerSongUpdate,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Song reactivity debugging available at window.__songReactivity
|
|
145
|
+
}
|