Player Client and Visual Enhancements

- Redesigned audio player bar to be mobile-friendly
 - Added unloading for track switching (needs to be fixed)
 - Added IsLoading status so loading spinner isn't hanging around when it shouldn't be
 - Normalized styles with scoped files (will further reduce)
 - Layout Cleanup
 - EF fixes (migrations now function for deployment)
 - deploy script updates (new dedicated host)
This commit is contained in:
daniel-c-harvey
2025-09-12 20:37:17 -04:00
parent 73d4b0a9c5
commit 9ac2c9182a
31 changed files with 763 additions and 179 deletions
+4 -2
View File
@@ -33,13 +33,15 @@
<Folder Include="wwwroot\js\" />
</ItemGroup>
<!-- Prevent TypeScript compilation issues during publish -->
<!-- TypeScript configuration following Microsoft recommendations -->
<PropertyGroup>
<TypeScriptCompileOnSaveEnabled>false</TypeScriptCompileOnSaveEnabled>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<TypeScriptESModuleInterop>true</TypeScriptESModuleInterop>
<TypeScriptAllowSyntheticDefaultImports>true</TypeScriptAllowSyntheticDefaultImports>
</PropertyGroup>
<!-- Only copy tsconfig.json to root output, not nested publish folders -->
<!-- Prevent tsconfig.json from being copied to output directories -->
<ItemGroup>
<None Update="tsconfig.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
+21 -27
View File
@@ -21,7 +21,6 @@ interface AudioState {
type ProgressCallback = (currentTime: number) => void;
type EndCallback = () => void;
type LoadProgressCallback = (progress: number) => void;
interface Window {
webkitAudioContext?: typeof AudioContext;
@@ -40,7 +39,6 @@ class AudioPlayer {
private duration: number = 0;
private onProgressCallback: ProgressCallback | null = null;
private onEndCallback: EndCallback | null = null;
private onLoadProgressCallback: LoadProgressCallback | null = null;
private progressInterval: number | null = null;
private bufferChunks: Uint8Array[] = [];
private expectedSize: number = 0;
@@ -72,12 +70,6 @@ class AudioPlayer {
try {
this.bufferChunks.push(audioBlock);
this.currentSize += audioBlock.length;
if (this.expectedSize > 0 && this.onLoadProgressCallback) {
const progress = (this.currentSize / this.expectedSize) * 100;
this.onLoadProgressCallback(Math.min(progress, 100));
}
return { success: true };
} catch (error) {
return { success: false, error: (error as Error).message };
@@ -101,10 +93,6 @@ class AudioPlayer {
this.bufferChunks = [];
this.currentSize = 0;
if (this.onLoadProgressCallback) {
this.onLoadProgressCallback(100);
}
return {
success: true,
duration: this.duration,
@@ -297,8 +285,19 @@ class AudioPlayer {
this.onEndCallback = callback;
}
setOnLoadProgressCallback(callback: LoadProgressCallback): void {
this.onLoadProgressCallback = callback;
unload(): AudioResult {
try {
this.stop();
this.audioBuffer = null;
this.duration = 0;
this.bufferChunks = [];
this.currentSize = 0;
this.expectedSize = 0;
return { success: true };
} catch (error) {
return { success: false, error: (error as Error).message };
}
}
dispose(): void {
@@ -387,6 +386,14 @@ const DeepDrftAudio = {
return player.stop();
},
unload: (playerId: string): AudioResult => {
const player = audioPlayers.get(playerId);
if (!player) {
return { success: false, error: "Player not found" };
}
return player.unload();
},
seek: (playerId: string, position: number): AudioResult => {
const player = audioPlayers.get(playerId);
if (!player) {
@@ -445,19 +452,6 @@ const DeepDrftAudio = {
return { success: true };
},
setOnLoadProgressCallback: (playerId: string, dotNetObjectReference: DotNetObjectReference, methodName: string): AudioResult => {
const player = audioPlayers.get(playerId);
if (!player) {
return { success: false, error: "Player not found" };
}
player.setOnLoadProgressCallback((progress: number) => {
dotNetObjectReference.invokeMethodAsync(methodName, progress);
});
return { success: true };
},
disposePlayer: (playerId: string): AudioResult => {
const player = audioPlayers.get(playerId);
if (player) {
+9 -5
View File
@@ -1,20 +1,24 @@
{
{
"compilerOptions": {
"target": "es2016",
"module": "ES6", // or "ESNext"
"target": "ESNext",
"module": "ESNext",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"outDir": "wwwroot/js"
},
"include": [
"**/*.ts"
"Interop/**/*.ts"
],
"exclude": [
"node_modules",
"bin/**/*",
"obj/**/*"
"obj/**/*",
"publish/**/*"
]
}
@@ -13,6 +13,7 @@
/* Surface Colors */
--deepdrft-surface: rgba(255, 255, 255, 1);
--deepdrft-surface-alpha: rgba(255, 255, 255, 0.9);
--deepdrft-theme-background-gray: rgba(26, 26, 26, 0.5);
/* Theme-aware Variables (Light Mode Default) */
--deepdrft-theme-primary: var(--deepdrft-primary);