feat(device-sync): USB/SD card sync page (WIP)

Adds a new Device Sync page for transferring music from Navidrome to
USB drives or SD cards. Sidebar entry is hidden by default.

- Four new Tauri commands: sync_track_to_device, compute_sync_paths,
  list_device_dir_files, delete_device_file
- Filename template engine with cross-platform path sanitization
- 4-concurrent-worker download, live progress via device:sync:progress event
- Persistent source list (albums/playlists/artists) with checkbox deletion
- Expandable artist tree in browser panel (per-album selection)
- i18n: DE + EN complete; other locales have stub keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-14 00:02:13 +02:00
parent 58f99ae846
commit 17a5c92174
15 changed files with 1341 additions and 2 deletions
+28
View File
@@ -25,6 +25,7 @@ export const esTranslation = {
mostPlayed: 'Más Reproducidos',
radio: 'Radio por Internet',
folderBrowser: 'Explorar Carpetas',
deviceSync: 'Sincronizar dispositivo',
libraryScope: 'Ámbito de biblioteca',
allLibraries: 'Todas las bibliotecas',
expandPlaylists: 'Expandir listas',
@@ -1024,4 +1025,31 @@ export const esTranslation = {
empty: 'Carpeta vacía',
error: 'Error al cargar',
},
deviceSync: {
title: 'Sincronizar dispositivo',
targetFolder: 'Carpeta de destino',
noFolderChosen: 'Ninguna carpeta seleccionada',
chooseFolder: 'Elegir…',
filenameTemplate: 'Plantilla de nombre de archivo',
templateHint: 'Variables: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}',
cleanupButton: 'Eliminar archivos fuera de la selección',
cleanupNothingToDelete: 'Nada que eliminar — el dispositivo ya está sincronizado.',
confirmCleanup: '¿Eliminar {{count}} archivo(s) del dispositivo que no están en la selección actual? ¿Continuar?',
cleanupComplete: '{{count}} archivo(s) eliminado(s) del dispositivo.',
selectedSources: 'Fuentes seleccionadas',
noSourcesSelected: 'No hay fuentes seleccionadas. Haz clic en elementos del navegador para agregarlos.',
clearAll: 'Limpiar todo',
tabPlaylists: 'Listas de reproducción',
tabAlbums: 'Álbumes',
tabArtists: 'Artistas',
searchPlaceholder: 'Buscar…',
syncButton: 'Sincronizar al dispositivo',
cancel: 'Cancelar',
noTargetDir: 'Por favor, elige primero una carpeta de destino.',
noSources: 'Por favor, selecciona al menos una fuente.',
noTracks: 'No se encontraron pistas en las fuentes seleccionadas.',
fetchError: 'Error al obtener pistas del servidor.',
syncComplete: 'Sincronización completada.',
dismiss: 'Cerrar',
},
};