refactor(device-sync): G.74 — extract helpers + legacy template + fetcher + BrowserRow (cluster) (#641)

Four-cut cluster opening the DeviceSync refactor. 1289 → 1186 LOC
(−103).

deviceSyncHelpers — uuid, formatBytes, trackToSyncInfo (with the
albumArtist-fallback-to-artist logic and the optional playlist
context the Rust sync command consumes), plus the SourceTab /
SyncStatus / RemovableDrive / SyncTrackMaybePlaylist types.

deviceSyncLegacyTemplate — sanitizeComponent (matches Rust's
sanitize_path_component) + OldTemplateTrack + applyLegacyTemplate.
Lives apart from the general helpers because it's only used by the
migration-preview flow and pulls in IS_WINDOWS for path separator.

fetchTracksForSource — single async helper that loads the songs for
a DeviceSyncSource (playlist / album / artist). Artist sources fan
out into parallel getAlbum requests (Navidrome handles them
concurrently; the old sequential loop was a ~7 s blocker on
50-album artists).

BrowserRow — small button row component used by the source-picker
list (playlists / albums / artists tabs).

DeviceSync drops the inline definitions plus the direct getAlbum /
getPlaylist / getArtist imports that only fetchTracksForSource
needed. Pure code move — no behaviour change.
This commit is contained in:
Frank Stellmacher
2026-05-13 14:57:15 +02:00
committed by GitHub
parent 6f8dd73448
commit 31542c9923
5 changed files with 138 additions and 119 deletions
+24
View File
@@ -0,0 +1,24 @@
import React from 'react';
import { CheckCircle2 } from 'lucide-react';
interface Props {
name: string;
meta?: string;
selected: boolean;
onToggle: () => void;
indent?: boolean;
}
export default function BrowserRow({ name, meta, selected, onToggle, indent }: Props) {
return (
<button className={`device-sync-browser-row${selected ? ' selected' : ''}${indent ? ' indent' : ''}`} onClick={onToggle}>
<span className="device-sync-row-check">
{selected ? <CheckCircle2 size={14} /> : <span className="device-sync-row-circle" />}
</span>
<span className="device-sync-row-name">
{name}
{meta && <span className="device-sync-row-artist"> · {meta}</span>}
</span>
</button>
);
}