refactor(api): make audio tagging and decryption async to avoid UI blocking

This commit is contained in:
2025-10-03 11:09:06 -04:00
parent 14a5b50942
commit 0ef56c3bed
4 changed files with 44 additions and 22 deletions

View File

@@ -81,6 +81,7 @@ export async function downloadTrack(
const reader = response.body!.getReader();
const chunks: Uint8Array[] = [];
let downloadedBytes = 0;
let lastReportedPercentage = 0;
while (true) {
const { done, value } = await reader.read();
@@ -89,15 +90,19 @@ export async function downloadTrack(
chunks.push(value);
downloadedBytes += value.length;
// Call progress callback
// Call progress callback every 5%
if (onProgress && totalSize > 0) {
const percentage = (downloadedBytes / totalSize) * 100;
console.log(`[Download Progress] ${downloadedBytes}/${totalSize} bytes (${percentage.toFixed(1)}%)`);
onProgress({
downloaded: downloadedBytes,
total: totalSize,
percentage
});
const roundedPercentage = Math.floor(percentage / 5) * 5;
if (roundedPercentage > lastReportedPercentage || percentage === 100) {
lastReportedPercentage = roundedPercentage;
onProgress({
downloaded: downloadedBytes,
total: totalSize,
percentage
});
}
}
}
@@ -111,20 +116,23 @@ export async function downloadTrack(
console.log(`Downloaded ${encryptedData.length} bytes, encrypted: ${isCrypted}`);
// Yield to the browser to keep UI responsive
await new Promise(resolve => setTimeout(resolve, 0));
// Decrypt if needed
let decryptedData: Uint8Array;
if (isCrypted) {
console.log('Decrypting track using Rust...');
console.log('Decrypting track...');
// Use the provided decryption track ID (for fallback tracks) or the original track ID
const trackIdForDecryption = decryptionTrackId || track.id.toString();
const trackIdForDecryption = decryptionTrackId ? decryptionTrackId.toString() : track.id.toString();
console.log(`Decrypting with track ID: ${trackIdForDecryption}`);
// Call Rust decryption function
const decrypted = await invoke<number[]>('decrypt_deezer_track', {
data: Array.from(encryptedData),
// Call Rust decryption function - Tauri returns Vec<u8> as number[]
const decryptedArray = await invoke<number[]>('decrypt_deezer_track', {
data: encryptedData,
trackId: trackIdForDecryption
});
decryptedData = new Uint8Array(decrypted);
decryptedData = new Uint8Array(decryptedArray);
} else {
decryptedData = encryptedData;
}

View File

@@ -90,14 +90,12 @@ export async function tagAudioFile(
): Promise<void> {
const metadata = convertToTaggingMetadata(track);
// Convert Uint8Array to regular array for JSON serialization
const coverArray = coverData ? Array.from(coverData) : undefined;
// Tauri handles Uint8Array -> Vec<u8> conversion automatically
try {
await invoke('tag_audio_file', {
path: filePath,
metadata,
coverData: coverArray,
coverData,
embedLyrics,
});
} catch (error) {