@@ -6,41 +6,24 @@ import { setAlbumArtInCache } from "../hooks/useAlbumArt";
66export async function importAudioFiles (
77 audioFiles : Array < { file : File } | File > ,
88 addSong : ( song : Song , file : File ) => Promise < void > ,
9- t : any
9+ t : any ,
1010) {
1111 if ( ! audioFiles || audioFiles . length === 0 ) return ;
1212
1313 const BATCH_SIZE = 10 ;
1414 let successCount = 0 ;
1515 let errorCount = 0 ;
16- let skippedCount = 0 ; // Count skipped duplicates
1716 let currentBatch = 1 ;
1817 const totalBatches = Math . ceil ( audioFiles . length / BATCH_SIZE ) ;
1918
20- // Track unique files to avoid duplicate imports in this session
21- const processedFileIds = new Set < string > ( ) ;
22-
2319 for ( let i = 0 ; i < audioFiles . length ; i += BATCH_SIZE ) {
2420 const batch = audioFiles . slice ( i , i + BATCH_SIZE ) ;
25- toast . loading (
26- t ( "batch.processing" , { currentBatch, totalBatches, successCount } )
27- ) ;
21+ toast . loading ( t ( "batch.processing" , { currentBatch, totalBatches } ) ) ;
2822
2923 // Process sequentially to reduce memory pressure
3024 for ( const audioFile of batch ) {
3125 try {
3226 const file : File = ( audioFile as any ) . file || ( audioFile as File ) ;
33-
34- // Unique ID based on file metadata (name, size, lastModified)
35- const fileId = `${ file . name } -${ file . size } -${ file . lastModified } ` ;
36- if ( processedFileIds . has ( fileId ) ) {
37- // Skip duplicates detected via unique ID
38- console . log ( `Skipping duplicate file: ${ file . name } ` ) ;
39- skippedCount ++ ;
40- continue ;
41- }
42- processedFileIds . add ( fileId ) ; // Mark the file as processed
43-
4427 const metadata = await extractAudioMetadata ( file ) ;
4528 const songId = generateUniqueId ( ) ;
4629
@@ -49,36 +32,31 @@ export async function importAudioFiles(
4932 let processedMimeType = file . type ;
5033
5134 const isFlo =
52- file . name . toLowerCase ( ) . endsWith ( " .flo" ) ||
53- metadata . encoding ?. codec === " flo" ;
35+ file . name . toLowerCase ( ) . endsWith ( ' .flo' ) ||
36+ metadata . encoding ?. codec === ' flo' ;
5437
5538 if ( isFlo ) {
5639 try {
5740 const arrayBuffer = await file . arrayBuffer ( ) ;
58- const isSafari = / ^ ( (? ! c h r o m e | a n d r o i d ) .) * s a f a r i / i. test (
59- navigator . userAgent
60- ) ;
41+ const isSafari = / ^ ( (? ! c h r o m e | a n d r o i d ) .) * s a f a r i / i. test ( navigator . userAgent ) ;
6142
6243 if ( isSafari ) {
6344 // Safari: Pre-decode to WAV for compatibility
6445 const { decodeFloToWav } = await import ( "./refloWavHelper" ) ;
6546 const wavBytes = await decodeFloToWav ( arrayBuffer ) ;
66- const wavBlob = new Blob ( [ wavBytes ] , { type : " audio/wav" } ) ;
47+ const wavBlob = new Blob ( [ wavBytes ] , { type : ' audio/wav' } ) ;
6748 processedFile = new File (
6849 [ wavBlob ] ,
69- file . name . replace ( / \. f l o $ / i, " .wav" ) ,
70- { type : " audio/wav" }
50+ file . name . replace ( / \. f l o $ / i, ' .wav' ) ,
51+ { type : ' audio/wav' }
7152 ) ;
72- processedMimeType = " audio/wav" ;
53+ processedMimeType = ' audio/wav' ;
7354 console . log ( `Pre-decoded flo to WAV for Safari: ${ file . name } ` ) ;
7455 } else {
7556 // Non-Safari: Pre-decode to PCM for Web Audio API
7657 const { decodeFloToAudioBuffer } = await import ( "./floProcessor" ) ;
7758 const audioContext = new AudioContext ( ) ;
78- const audioBuffer = await decodeFloToAudioBuffer (
79- arrayBuffer ,
80- audioContext
81- ) ;
59+ const audioBuffer = await decodeFloToAudioBuffer ( arrayBuffer , audioContext ) ;
8260
8361 // Store as interleaved Float32Array PCM
8462 const frameCount = audioBuffer . length ;
@@ -88,27 +66,25 @@ export async function importAudioFiles(
8866 // Interleave channels
8967 for ( let i = 0 ; i < frameCount ; i ++ ) {
9068 for ( let ch = 0 ; ch < channels ; ch ++ ) {
91- pcmData [ i * channels + ch ] = audioBuffer . getChannelData ( ch ) [
92- i
93- ] ;
69+ pcmData [ i * channels + ch ] = audioBuffer . getChannelData ( ch ) [ i ] ;
9470 }
9571 }
9672
97- const pcmBlob = new Blob ( [ pcmData . buffer ] , { type : " audio/pcm" } ) ;
73+ const pcmBlob = new Blob ( [ pcmData . buffer ] , { type : ' audio/pcm' } ) ;
9874 processedFile = new File (
9975 [ pcmBlob ] ,
100- file . name . replace ( / \. f l o $ / i, " .pcm" ) ,
101- { type : " audio/pcm" }
76+ file . name . replace ( / \. f l o $ / i, ' .pcm' ) ,
77+ { type : ' audio/pcm' }
10278 ) ;
103- processedMimeType = " audio/pcm" ;
79+ processedMimeType = ' audio/pcm' ;
10480
10581 // Store AudioBuffer properties for reconstruction
10682 metadata . encoding = {
10783 ...metadata . encoding ,
10884 sampleRate : audioBuffer . sampleRate ,
10985 channels : audioBuffer . numberOfChannels ,
11086 bitsPerSample : 32 , // Float32
111- codec : " pcm-float32" ,
87+ codec : ' pcm-float32' ,
11288 } ;
11389
11490 // Close the temporary AudioContext
@@ -119,27 +95,22 @@ export async function importAudioFiles(
11995 } catch ( error ) {
12096 console . warn ( "Failed to pre-decode flo file, storing original:" , error ) ;
12197 // Keep original file if pre-decoding fails
122- processedMimeType = " audio/x-flo" ;
98+ processedMimeType = ' audio/x-flo' ;
12399 }
124100 }
125101
126102 // Save album art separately if present
127103 const hasAlbumArt = ! ! metadata . albumArt ;
128104 if ( hasAlbumArt && metadata . albumArt ) {
129- await musicIndexedDbHelper . saveAlbumArt (
130- songId ,
131- metadata . albumArt
132- ) ;
105+ await musicIndexedDbHelper . saveAlbumArt ( songId , metadata . albumArt ) ;
133106 setAlbumArtInCache ( songId , metadata . albumArt ) ;
134107 }
135108
136109 const song : Song = {
137110 id : songId ,
138111 title : metadata . title ,
139112 artist : metadata . artist ,
140- album :
141- metadata . album ||
142- t ( "songInfo.album" , { title : t ( "common.unknownAlbum" ) } ) ,
113+ album : metadata . album || t ( "songInfo.album" , { title : t ( "common.unknownAlbum" ) } ) ,
143114 duration : metadata . duration ,
144115 url : "" , // Will be set by addSong
145116 albumArt : metadata . albumArt , // Keep for immediate display
@@ -171,14 +142,8 @@ export async function importAudioFiles(
171142 }
172143
173144 toast . dismiss ( ) ;
174- // Show accurate results with skipped files count
175145 if ( successCount > 0 ) {
176- toast . success (
177- t ( "filePicker.successImport" , {
178- count : successCount ,
179- skipped : skippedCount ,
180- } )
181- ) ;
146+ toast . success ( t ( "filePicker.successImport" , { count : successCount } ) ) ;
182147 }
183148 if ( errorCount > 0 ) {
184149 toast . error ( t ( "filePicker.failedImport" , { count : errorCount } ) ) ;
0 commit comments