|
@@ -420,24 +420,46 @@ const Browser = (() => {
|
|
|
|
|
|
|
|
// ===== Upload =====
|
|
// ===== Upload =====
|
|
|
|
|
|
|
|
- async function handleFileUpload(e) {
|
|
|
|
|
- const files = Array.from(e.target.files);
|
|
|
|
|
|
|
+ async function uploadFiles(files) {
|
|
|
if (files.length === 0) return;
|
|
if (files.length === 0) return;
|
|
|
- e.target.value = '';
|
|
|
|
|
-
|
|
|
|
|
- for (const file of files) {
|
|
|
|
|
- showUploadToast(`Uploading ${file.name}...`);
|
|
|
|
|
|
|
+ const total = files.length;
|
|
|
|
|
+ let failed = 0;
|
|
|
|
|
+
|
|
|
|
|
+ for (let i = 0; i < files.length; i++) {
|
|
|
|
|
+ const file = files[i];
|
|
|
|
|
+ showUploadToast(total > 1
|
|
|
|
|
+ ? `Uploading ${i + 1}/${total}: ${file.name}`
|
|
|
|
|
+ : `Uploading ${file.name}…`);
|
|
|
try {
|
|
try {
|
|
|
await API.uploadTrack(file, selectedDirId, null);
|
|
await API.uploadTrack(file, selectedDirId, null);
|
|
|
- showToast(`Uploaded: ${file.name}`, 'success');
|
|
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
- showToast(`Error uploading ${file.name}: ${err.message}`, 'error');
|
|
|
|
|
|
|
+ failed++;
|
|
|
|
|
+ showToast(`Failed: ${file.name} — ${err.message}`, 'error');
|
|
|
|
|
+ // Let the error toast show briefly before moving on
|
|
|
|
|
+ await new Promise(r => setTimeout(r, 1200));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- hideUploadToast();
|
|
|
|
|
|
|
+
|
|
|
|
|
+ const ok = total - failed;
|
|
|
|
|
+ if (total === 1) {
|
|
|
|
|
+ failed ? hideUploadToast() : showToast('Uploaded successfully', 'success');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ showToast(
|
|
|
|
|
+ failed === 0
|
|
|
|
|
+ ? `Uploaded ${ok} file${ok !== 1 ? 's' : ''}`
|
|
|
|
|
+ : `Uploaded ${ok}/${total} — ${failed} failed`,
|
|
|
|
|
+ failed ? 'error' : 'success'
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
await reload();
|
|
await reload();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ async function handleFileUpload(e) {
|
|
|
|
|
+ const files = Array.from(e.target.files);
|
|
|
|
|
+ e.target.value = '';
|
|
|
|
|
+ await uploadFiles(files);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function setupDropZone() {
|
|
function setupDropZone() {
|
|
|
const mapContainer = document.getElementById('map-container');
|
|
const mapContainer = document.getElementById('map-container');
|
|
|
mapContainer.addEventListener('dragover', (e) => {
|
|
mapContainer.addEventListener('dragover', (e) => {
|
|
@@ -456,18 +478,7 @@ const Browser = (() => {
|
|
|
e.preventDefault();
|
|
e.preventDefault();
|
|
|
mapContainer.classList.remove('drag-over');
|
|
mapContainer.classList.remove('drag-over');
|
|
|
const files = Array.from(e.dataTransfer.files).filter(f => f.name.toLowerCase().endsWith('.gpx'));
|
|
const files = Array.from(e.dataTransfer.files).filter(f => f.name.toLowerCase().endsWith('.gpx'));
|
|
|
- if (files.length === 0) return;
|
|
|
|
|
- for (const file of files) {
|
|
|
|
|
- showUploadToast(`Uploading ${file.name}...`);
|
|
|
|
|
- try {
|
|
|
|
|
- await API.uploadTrack(file, selectedDirId, null);
|
|
|
|
|
- showToast(`Uploaded: ${file.name}`, 'success');
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- showToast(`Error: ${err.message}`, 'error');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- hideUploadToast();
|
|
|
|
|
- await reload();
|
|
|
|
|
|
|
+ await uploadFiles(files);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|