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
@@ -24,6 +24,7 @@ export const frTranslation = {
mostPlayed: 'Les plus joués',
radio: 'Radio Internet',
folderBrowser: 'Explorateur de dossiers',
deviceSync: 'Sync appareil',
libraryScope: 'Portée de la bibliothèque',
allLibraries: 'Toutes les bibliothèques',
expandPlaylists: 'Développer les playlists',
@@ -1019,4 +1020,31 @@ export const frTranslation = {
empty: 'Dossier vide',
error: 'Échec du chargement',
},
deviceSync: {
title: 'Sync appareil',
targetFolder: 'Dossier cible',
noFolderChosen: 'Aucun dossier sélectionné',
chooseFolder: 'Choisir…',
filenameTemplate: 'Modèle de nom de fichier',
templateHint: 'Variables : {artist}, {album}, {title}, {track_number}, {disc_number}, {year}',
cleanupButton: 'Supprimer les fichiers absents',
cleanupNothingToDelete: 'Rien à supprimer — l\'appareil est déjà synchronisé.',
confirmCleanup: 'Supprimer {{count}} fichier(s) de l\'appareil qui ne font pas partie de la sélection actuelle. Continuer ?',
cleanupComplete: '{{count}} fichier(s) supprimé(s) de l\'appareil.',
selectedSources: 'Sources sélectionnées',
noSourcesSelected: 'Aucune source sélectionnée. Cliquez sur des éléments dans le navigateur pour les ajouter.',
clearAll: 'Tout effacer',
tabPlaylists: 'Listes de lecture',
tabAlbums: 'Albums',
tabArtists: 'Artistes',
searchPlaceholder: 'Rechercher…',
syncButton: 'Synchroniser vers l\'appareil',
cancel: 'Annuler',
noTargetDir: 'Veuillez d\'abord choisir un dossier cible.',
noSources: 'Veuillez sélectionner au moins une source.',
noTracks: 'Aucune piste trouvée dans les sources sélectionnées.',
fetchError: 'Échec du chargement des pistes depuis le serveur.',
syncComplete: 'Synchronisation terminée.',
dismiss: 'Fermer',
},
};