mirror of
https://github.com/nimbold/Firelink.git
synced 2026-09-02 05:57:59 +00:00
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:
+1
-1
Submodule Extensions/Browser updated: d39d3c79cf...f288273338
@@ -48,6 +48,8 @@ import {
|
|||||||
reconcileDownloadRows,
|
reconcileDownloadRows,
|
||||||
refreshFailedMetadataRows,
|
refreshFailedMetadataRows,
|
||||||
isMagnetUrl,
|
isMagnetUrl,
|
||||||
|
isAddDownloadMetadataLoading,
|
||||||
|
isAddDownloadMetadataError,
|
||||||
isMetadataRefreshableRow,
|
isMetadataRefreshableRow,
|
||||||
selectExactMediaSelection,
|
selectExactMediaSelection,
|
||||||
updateRowIfCurrent,
|
updateRowIfCurrent,
|
||||||
@@ -2273,17 +2275,19 @@ export const AddDownloadsModal = () => {
|
|||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</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 font-mono ${isAddDownloadMetadataLoading(item) ? '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'}`}>
|
<div className={`flex-[1.5] font-medium ${isAddDownloadMetadataError(item) || item.status === 'invalid' ? 'text-red-500' : isAddDownloadMetadataLoading(item) ? 'text-orange-400' : 'text-blue-500'}`}>
|
||||||
{item.status === 'loading' ? (
|
{isAddDownloadMetadataLoading(item) ? (
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<RefreshCw size={12} className="animate-spin" /> {item.isPlaylist ? t($ => $.addDownloads.fetchingPlaylist) : t($ => $.addDownloads.fetching)}
|
<RefreshCw size={12} className="animate-spin" /> {item.isPlaylist ? t($ => $.addDownloads.fetchingPlaylist) : t($ => $.addDownloads.fetching)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
item.status === 'fallback'
|
item.status === 'fallback'
|
||||||
? t($ => $.addDownloads.fallback)
|
? t($ => $.addDownloads.fallback)
|
||||||
: item.status === 'metadata-error'
|
: 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)
|
? 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'
|
: item.status === 'invalid'
|
||||||
? t($ => $.addDownloads.invalid)
|
? t($ => $.addDownloads.invalid)
|
||||||
: t($ => $.addDownloads.ready)
|
: t($ => $.addDownloads.ready)
|
||||||
@@ -2351,6 +2355,15 @@ export const AddDownloadsModal = () => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</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">
|
<p className="text-xs text-text-muted">
|
||||||
{t($ => $.addDownloads.torrentMetadataPending)}
|
{t($ => $.addDownloads.torrentMetadataPending)}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
metadataSummaryMessage,
|
metadataSummaryMessage,
|
||||||
isYouTubePlaylistUrl,
|
isYouTubePlaylistUrl,
|
||||||
isMagnetUrl,
|
isMagnetUrl,
|
||||||
|
isAddDownloadMetadataLoading,
|
||||||
|
isAddDownloadMetadataError,
|
||||||
isMetadataRefreshableRow,
|
isMetadataRefreshableRow,
|
||||||
isRemoteTorrentUrl,
|
isRemoteTorrentUrl,
|
||||||
playlistFilePrefix,
|
playlistFilePrefix,
|
||||||
@@ -545,6 +547,7 @@ describe('add download metadata workflow', () => {
|
|||||||
expect(admitted.status).toBe('ready');
|
expect(admitted.status).toBe('ready');
|
||||||
expect(canSubmitMetadataRows([admitted])).toBe(true);
|
expect(canSubmitMetadataRows([admitted])).toBe(true);
|
||||||
expect(isMetadataRefreshableRow(admitted)).toBe(false);
|
expect(isMetadataRefreshableRow(admitted)).toBe(false);
|
||||||
|
expect(isMetadataRefreshableRow({ ...admitted, torrentMetadataStatus: 'ready' })).toBe(true);
|
||||||
|
|
||||||
const failed = { ...admitted, torrentMetadataStatus: 'error' as const };
|
const failed = { ...admitted, torrentMetadataStatus: 'error' as const };
|
||||||
const refreshed = refreshFailedMetadataRows([failed])[0];
|
const refreshed = refreshFailedMetadataRows([failed])[0];
|
||||||
@@ -558,6 +561,34 @@ describe('add download metadata workflow', () => {
|
|||||||
expect(isMetadataRefreshableRow(row())).toBe(false);
|
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', () => {
|
it('refreshes only selected metadata rows when requested by the preview action', () => {
|
||||||
const selected = row({
|
const selected = row({
|
||||||
id: 'selected-magnet',
|
id: 'selected-magnet',
|
||||||
|
|||||||
@@ -120,6 +120,16 @@ export const isMagnetTorrentRow = (
|
|||||||
row: Pick<AddDownloadDraftRow, 'isTorrent' | 'sourceUrl'>
|
row: Pick<AddDownloadDraftRow, 'isTorrent' | 'sourceUrl'>
|
||||||
): boolean => row.isTorrent === true && isMagnetUrl(row.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 =>
|
export const isMetadataRefreshableRow = (row: AddDownloadDraftRow): boolean =>
|
||||||
row.status !== 'loading'
|
row.status !== 'loading'
|
||||||
&& (row.status === 'metadata-error'
|
&& (row.status === 'metadata-error'
|
||||||
|
|||||||
Reference in New Issue
Block a user