fix(integration): repair capture and magnet loading states

- advance the Browser Companion to the published handoff fix
- show Fetching state while optional magnet metadata is loading
- surface failed magnet metadata without blocking transfer-ready magnets
- preserve regression coverage for cross-layer state transitions
This commit is contained in:
NimBold
2026-08-27 01:54:48 +03:30
parent 62e60938e8
commit 7fb05e87da
4 changed files with 60 additions and 6 deletions
+18 -5
View File
@@ -48,6 +48,8 @@ import {
reconcileDownloadRows,
refreshFailedMetadataRows,
isMagnetUrl,
isAddDownloadMetadataLoading,
isAddDownloadMetadataError,
isMetadataRefreshableRow,
selectExactMediaSelection,
updateRowIfCurrent,
@@ -2273,17 +2275,19 @@ export const AddDownloadsModal = () => {
</span>
) : null}
</div>
<div className={`flex-1 font-mono ${item.status === 'loading' ? 'text-text-muted/50' : 'text-text-muted'}`}>{item.size || t($ => $.addDownloads.unknown)}</div>
<div className={`flex-[1.5] font-medium ${item.status === 'metadata-error' || item.status === 'invalid' ? 'text-red-500' : item.status === 'loading' ? 'text-orange-400' : 'text-blue-500'}`}>
{item.status === 'loading' ? (
<div className={`flex-1 font-mono ${isAddDownloadMetadataLoading(item) ? 'text-text-muted/50' : 'text-text-muted'}`}>{item.size || t($ => $.addDownloads.unknown)}</div>
<div className={`flex-[1.5] font-medium ${isAddDownloadMetadataError(item) || item.status === 'invalid' ? 'text-red-500' : isAddDownloadMetadataLoading(item) ? 'text-orange-400' : 'text-blue-500'}`}>
{isAddDownloadMetadataLoading(item) ? (
<div className="flex items-center gap-1.5">
<RefreshCw size={12} className="animate-spin" /> {item.isPlaylist ? t($ => $.addDownloads.fetchingPlaylist) : t($ => $.addDownloads.fetching)}
</div>
) : (
item.status === 'fallback'
? t($ => $.addDownloads.fallback)
: item.status === 'metadata-error'
? item.metadataBlockedReason === 'unsafe-url' ? t($ => $.addDownloads.unsafeUrl) : item.isPlaylist ? t($ => $.addDownloads.playlistFailed) : item.isMedia ? t($ => $.addDownloads.metadataFailed) : t($ => $.addDownloads.fallback)
: isAddDownloadMetadataError(item)
? item.status === 'metadata-error'
? item.metadataBlockedReason === 'unsafe-url' ? t($ => $.addDownloads.unsafeUrl) : item.isPlaylist ? t($ => $.addDownloads.playlistFailed) : item.isMedia ? t($ => $.addDownloads.metadataFailed) : t($ => $.addDownloads.fallback)
: t($ => $.addDownloads.metadataFailed)
: item.status === 'invalid'
? t($ => $.addDownloads.invalid)
: t($ => $.addDownloads.ready)
@@ -2351,6 +2355,15 @@ export const AddDownloadsModal = () => {
);
})}
</div>
) : isAddDownloadMetadataLoading(parsedItems[selectedItemIndex]) ? (
<div className="flex items-center gap-2 text-xs text-orange-400" aria-live="polite">
<RefreshCw size={14} className="animate-spin" />
<span>{t($ => $.addDownloads.fetching)}</span>
</div>
) : isAddDownloadMetadataError(parsedItems[selectedItemIndex]) ? (
<div className="flex items-center gap-2 text-xs text-red-500" aria-live="polite">
<span>{t($ => $.addDownloads.metadataFailed)}</span>
</div>
) : (
<p className="text-xs text-text-muted">
{t($ => $.addDownloads.torrentMetadataPending)}
+31
View File
@@ -13,6 +13,8 @@ import {
metadataSummaryMessage,
isYouTubePlaylistUrl,
isMagnetUrl,
isAddDownloadMetadataLoading,
isAddDownloadMetadataError,
isMetadataRefreshableRow,
isRemoteTorrentUrl,
playlistFilePrefix,
@@ -545,6 +547,7 @@ describe('add download metadata workflow', () => {
expect(admitted.status).toBe('ready');
expect(canSubmitMetadataRows([admitted])).toBe(true);
expect(isMetadataRefreshableRow(admitted)).toBe(false);
expect(isMetadataRefreshableRow({ ...admitted, torrentMetadataStatus: 'ready' })).toBe(true);
const failed = { ...admitted, torrentMetadataStatus: 'error' as const };
const refreshed = refreshFailedMetadataRows([failed])[0];
@@ -558,6 +561,34 @@ describe('add download metadata workflow', () => {
expect(isMetadataRefreshableRow(row())).toBe(false);
});
it('exposes optional magnet metadata as loading while keeping transfer readiness', () => {
const magnet = row({
sourceUrl: 'magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567',
isTorrent: true,
torrentMetadataStatus: 'loading'
});
expect(magnet.status).toBe('ready');
expect(isAddDownloadMetadataLoading(magnet)).toBe(true);
expect(isAddDownloadMetadataLoading({
...magnet,
torrentMetadataStatus: 'ready'
})).toBe(false);
expect(isAddDownloadMetadataLoading({
...magnet,
status: 'loading',
torrentMetadataStatus: undefined
})).toBe(true);
expect(isAddDownloadMetadataError({
...magnet,
torrentMetadataStatus: 'error'
})).toBe(true);
expect(isAddDownloadMetadataError({
...magnet,
torrentMetadataStatus: 'ready'
})).toBe(false);
});
it('refreshes only selected metadata rows when requested by the preview action', () => {
const selected = row({
id: 'selected-magnet',
+10
View File
@@ -120,6 +120,16 @@ export const isMagnetTorrentRow = (
row: Pick<AddDownloadDraftRow, 'isTorrent' | 'sourceUrl'>
): boolean => row.isTorrent === true && isMagnetUrl(row.sourceUrl);
export const isAddDownloadMetadataLoading = (
row: Pick<AddDownloadDraftRow, 'status' | 'isTorrent' | 'sourceUrl' | 'torrentMetadataStatus'>
): boolean => row.status === 'loading'
|| (isMagnetTorrentRow(row) && row.torrentMetadataStatus === 'loading');
export const isAddDownloadMetadataError = (
row: Pick<AddDownloadDraftRow, 'status' | 'isTorrent' | 'sourceUrl' | 'torrentMetadataStatus'>
): boolean => row.status === 'metadata-error'
|| (isMagnetTorrentRow(row) && row.torrentMetadataStatus === 'error');
export const isMetadataRefreshableRow = (row: AddDownloadDraftRow): boolean =>
row.status !== 'loading'
&& (row.status === 'metadata-error'