feat(DeviceDetailOverlay): improve media set detection logic and optimize state management
This commit is contained in:
parent
de303e9327
commit
5c28a69055
|
|
@ -125,33 +125,40 @@ export default function DeviceDetailOverlay({
|
|||
}
|
||||
};
|
||||
|
||||
// Prefer an explicit .lst-derived mediaSet stored in config; fall back to pattern detection.
|
||||
const [mediaSetFiles, setMediaSetFiles] = useState<MediaSetEntry[] | null>(null);
|
||||
const prevDeviceNumberRef = useRef(device.number);
|
||||
const detectTokenRef = useRef(0);
|
||||
|
||||
// Cancel any in-flight detection and reset when navigating to a different device.
|
||||
useEffect(() => {
|
||||
const deviceChanged = prevDeviceNumberRef.current !== device.number;
|
||||
prevDeviceNumberRef.current = device.number;
|
||||
++detectTokenRef.current;
|
||||
setMediaSetFiles(null);
|
||||
}, [device.number]);
|
||||
|
||||
// Sync config-backed media_set to display state whenever it is set explicitly
|
||||
// (e.g. after a playlist is mounted).
|
||||
useEffect(() => {
|
||||
if (Array.isArray(deviceData.media_set) && deviceData.media_set.length > 1) {
|
||||
setMediaSetFiles(deviceData.media_set as MediaSetEntry[]);
|
||||
return;
|
||||
}
|
||||
// Don't run pattern detection when switching devices — only when the URL
|
||||
// is actively being changed within the same device.
|
||||
if (deviceChanged || !deviceData.url) { setMediaSetFiles(null); return; }
|
||||
const match = (deviceData.url as string).match(/^(.+?)(\d+)(\.[^.]+)$/);
|
||||
if (!match) { setMediaSetFiles(null); return; }
|
||||
}, [deviceData.media_set]);
|
||||
|
||||
// Pattern-detect sibling numbered files for the given URL. Called only when
|
||||
// the user actively sets a URL — never on overlay load or device switch.
|
||||
const detectMediaSet = async (url: string) => {
|
||||
const token = ++detectTokenRef.current;
|
||||
setMediaSetFiles(null);
|
||||
const match = url.match(/^(.+?)(\d+)(\.[^.]+)$/);
|
||||
if (!match) return;
|
||||
const [, prefix, , ext] = match;
|
||||
const candidates: string[] = [];
|
||||
for (let i = 1; i <= 10; i++) candidates.push(`${prefix}${i}${ext}`);
|
||||
let cancelled = false;
|
||||
Promise.all(candidates.map(f => stat(f).then(r => r !== null).catch(() => false))).then(flags => {
|
||||
const flags = await Promise.all(
|
||||
candidates.map(f => stat(f).then(r => r !== null).catch(() => false))
|
||||
);
|
||||
if (detectTokenRef.current !== token) return;
|
||||
const found = candidates.filter((_, i) => flags[i]);
|
||||
if (!cancelled) setMediaSetFiles(found.length > 1 ? found : null);
|
||||
});
|
||||
return () => { cancelled = true; };
|
||||
}, [device.number, deviceData.url, deviceData.media_set]);
|
||||
setMediaSetFiles(found.length > 1 ? found : null);
|
||||
};
|
||||
|
||||
const switchMedia = (file: string) => {
|
||||
const path = getDevicePath();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user