@@ -63,30 +66,46 @@ function renderTrack(track) {
}
// Update track information fields.
- document.getElementById('track-name').innerHTML =
- `
${track.name || 'Unknown Track'}`;
+ const trackNameEl = document.getElementById('track-name');
+ if (trackNameEl) {
+ trackNameEl.innerHTML =
+ `
${track.name || 'Unknown Track'}`;
+ }
- document.getElementById('track-artist').innerHTML =
- `By ${track.artists?.map(a =>
- `
${a?.name || 'Unknown Artist'}`
- ).join(', ') || 'Unknown Artist'}`;
+ const trackArtistEl = document.getElementById('track-artist');
+ if (trackArtistEl) {
+ trackArtistEl.innerHTML =
+ `By ${track.artists?.map((a: any) =>
+ `
${a?.name || 'Unknown Artist'}`
+ ).join(', ') || 'Unknown Artist'}`;
+ }
- document.getElementById('track-album').innerHTML =
- `Album:
${track.album?.name || 'Unknown Album'} (${track.album?.album_type || 'album'})`;
+ const trackAlbumEl = document.getElementById('track-album');
+ if (trackAlbumEl) {
+ trackAlbumEl.innerHTML =
+ `Album:
${track.album?.name || 'Unknown Album'} (${track.album?.album_type || 'album'})`;
+ }
- document.getElementById('track-duration').textContent =
- `Duration: ${msToTime(track.duration_ms || 0)}`;
+ const trackDurationEl = document.getElementById('track-duration');
+ if (trackDurationEl) {
+ trackDurationEl.textContent =
+ `Duration: ${msToTime(track.duration_ms || 0)}`;
+ }
- document.getElementById('track-explicit').textContent =
- track.explicit ? 'Explicit' : 'Clean';
+ const trackExplicitEl = document.getElementById('track-explicit');
+ if (trackExplicitEl) {
+ trackExplicitEl.textContent =
+ track.explicit ? 'Explicit' : 'Clean';
+ }
const imageUrl = (track.album?.images && track.album.images[0])
? track.album.images[0].url
: '/static/images/placeholder.jpg';
- document.getElementById('track-album-image').src = imageUrl;
+ const trackAlbumImageEl = document.getElementById('track-album-image') as HTMLImageElement;
+ if (trackAlbumImageEl) trackAlbumImageEl.src = imageUrl;
// --- Insert Home Button (if not already present) ---
- let homeButton = document.getElementById('homeButton');
+ let homeButton = document.getElementById('homeButton') as HTMLButtonElement;
if (!homeButton) {
homeButton = document.createElement('button');
homeButton.id = 'homeButton';
@@ -103,7 +122,7 @@ function renderTrack(track) {
});
// --- Move the Download Button from #actions into #track-header ---
- let downloadBtn = document.getElementById('downloadTrackBtn');
+ let downloadBtn = document.getElementById('downloadTrackBtn') as HTMLButtonElement;
if (downloadBtn) {
// Remove the parent container (#actions) if needed.
const actionsContainer = document.getElementById('actions');
@@ -139,7 +158,7 @@ function renderTrack(track) {
// Make the queue visible to show the download
downloadQueue.toggleVisibility(true);
})
- .catch(err => {
+ .catch((err: any) => {
showError('Failed to queue track download: ' + (err?.message || 'Unknown error'));
downloadBtn.disabled = false;
downloadBtn.innerHTML = `

`;
@@ -148,13 +167,14 @@ function renderTrack(track) {
}
// Reveal the header now that track info is loaded.
- document.getElementById('track-header').classList.remove('hidden');
+ const trackHeaderEl = document.getElementById('track-header');
+ if (trackHeaderEl) trackHeaderEl.classList.remove('hidden');
}
/**
* Converts milliseconds to minutes:seconds.
*/
-function msToTime(duration) {
+function msToTime(duration: number) {
if (!duration || isNaN(duration)) return '0:00';
const minutes = Math.floor(duration / 60000);
@@ -165,7 +185,7 @@ function msToTime(duration) {
/**
* Displays an error message in the UI.
*/
-function showError(message) {
+function showError(message: string) {
const errorEl = document.getElementById('error');
if (errorEl) {
errorEl.textContent = message || 'An error occurred';
@@ -176,7 +196,7 @@ function showError(message) {
/**
* Starts the download process by calling the centralized downloadQueue method
*/
-async function startDownload(url, type, item) {
+async function startDownload(url: string, type: string, item: any) {
if (!url || !type) {
showError('Missing URL or type for download');
return;
@@ -188,7 +208,7 @@ async function startDownload(url, type, item) {
// Make the queue visible after queueing
downloadQueue.toggleVisibility(true);
- } catch (error) {
+ } catch (error: any) {
showError('Download failed: ' + (error?.message || 'Unknown error'));
throw error;
}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..34db1e4
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "es2017", // Specify ECMAScript target version
+ "module": "ES2020", // Specify module code generation
+ "strict": true, // Enable all strict type-checking options
+ "noImplicitAny": false, // Allow implicit 'any' types
+ "esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules
+ "skipLibCheck": true, // Skip type checking of declaration files
+ "forceConsistentCasingInFileNames": true // Disallow inconsistently-cased references to the same file.
+ },
+ "include": [
+ "static/js/**/*.ts" // Specifies the TypeScript files to be included in compilation
+ ],
+ "exclude": [
+ "node_modules" // Specifies an array of filenames or patterns that should be skipped when resolving include.
+ ]
+}
\ No newline at end of file