mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 05:06:16 -08:00
refactor(downloads): simplify ready cards
This commit is contained in:
1 parent
8a5b29ea4d
commit
63b87da5f3
4 files changed
+119
-47
No files matched your search
@@ -72,12 +72,6 @@
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
<span class="download-library__offline">
|
||||
<mat-icon aria-hidden="true"
|
||||
>download_done</mat-icon
|
||||
>
|
||||
{{ 'DOWNLOADS.OFFLINE' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="download-library__body">
|
||||
@@ -169,14 +163,59 @@
|
||||
}
|
||||
</div>
|
||||
<div class="download-library__metadata">
|
||||
@if (entity.sourceName.trim()) {
|
||||
<span>{{ entity.sourceName }}</span>
|
||||
<span aria-hidden="true">·</span>
|
||||
}
|
||||
<span>{{
|
||||
formatBytes(entity.trackedBytes)
|
||||
}}</span>
|
||||
</div>
|
||||
<div
|
||||
class="download-library__actions"
|
||||
[attr.aria-label]="entity.title"
|
||||
>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
[matMenuTriggerFor]="seriesMenu"
|
||||
[attr.aria-label]="
|
||||
('DOWNLOADS.MORE_ACTIONS'
|
||||
| translate) +
|
||||
': ' +
|
||||
entity.title
|
||||
"
|
||||
[matTooltip]="
|
||||
'DOWNLOADS.MORE_ACTIONS' | translate
|
||||
"
|
||||
>
|
||||
<mat-icon aria-hidden="true">
|
||||
more_vert
|
||||
</mat-icon>
|
||||
</button>
|
||||
<mat-menu #seriesMenu="matMenu">
|
||||
<app-download-source-menu-header
|
||||
[sourceName]="entity.sourceName"
|
||||
/>
|
||||
<button
|
||||
mat-menu-item
|
||||
type="button"
|
||||
[attr.aria-label]="
|
||||
('DOWNLOADS.OPEN_EPISODES'
|
||||
| translate) +
|
||||
': ' +
|
||||
entity.title
|
||||
"
|
||||
(click)="openEpisodes(entity)"
|
||||
>
|
||||
<mat-icon aria-hidden="true">
|
||||
video_library
|
||||
</mat-icon>
|
||||
<span>
|
||||
{{
|
||||
'DOWNLOADS.OPEN_EPISODES'
|
||||
| translate
|
||||
}}
|
||||
</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
} @else {
|
||||
@@ -253,12 +292,6 @@
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
<span class="download-library__offline">
|
||||
<mat-icon aria-hidden="true"
|
||||
>download_done</mat-icon
|
||||
>
|
||||
{{ 'DOWNLOADS.OFFLINE' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="download-library__body">
|
||||
@@ -316,10 +349,6 @@
|
||||
</span>
|
||||
}
|
||||
<div class="download-library__metadata">
|
||||
@if (entity.sourceName.trim()) {
|
||||
<span>{{ entity.sourceName }}</span>
|
||||
<span aria-hidden="true">·</span>
|
||||
}
|
||||
<span>{{
|
||||
formatBytes(entity.trackedBytes)
|
||||
}}</span>
|
||||
@@ -382,6 +411,9 @@
|
||||
>
|
||||
</button>
|
||||
<mat-menu #itemMenu="matMenu">
|
||||
<app-download-source-menu-header
|
||||
[sourceName]="entity.sourceName"
|
||||
/>
|
||||
<button
|
||||
mat-menu-item
|
||||
type="button"
|
||||
|
||||
@@ -127,33 +127,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.download-library__offline {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 5px 8px;
|
||||
border: 1px solid
|
||||
color-mix(in srgb, var(--mat-sys-on-primary) 18%, transparent);
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--mat-sys-primary) 88%, transparent);
|
||||
color: var(--mat-sys-on-primary);
|
||||
font-size: 0.66rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.045em;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
pointer-events: none;
|
||||
|
||||
mat-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.download-library__body {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
|
||||
@@ -36,6 +36,11 @@ const TRANSLATIONS = {
|
||||
SOURCE_PLAYLIST_MISSING:
|
||||
'This download can no longer open because its source was removed.',
|
||||
},
|
||||
PORTALS: {
|
||||
MULTI_SOURCE: {
|
||||
SOURCE: 'Source',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function item(overrides: Partial<DownloadItem>): DownloadItem {
|
||||
@@ -218,6 +223,66 @@ describe('DownloadLibraryComponent', () => {
|
||||
expect(fallbackEpisodeCard.textContent).toContain('Episode');
|
||||
});
|
||||
|
||||
it('keeps ready cards clean while preserving tracked size', () => {
|
||||
const section = byTestId('downloads-library-section');
|
||||
const movieCard = byTestId('download-library-movie-9');
|
||||
const seriesCard = byTestId('download-library-series-playlist-a-77');
|
||||
const episodeCard = byTestId('download-library-episode-21');
|
||||
|
||||
expect(section.textContent).not.toContain('Offline');
|
||||
expect(movieCard.textContent).not.toContain('Cinema');
|
||||
expect(seriesCard.textContent).not.toContain('Living room');
|
||||
expect(episodeCard.textContent).not.toContain('Archive');
|
||||
expect(movieCard.textContent).toContain('2.4 MB');
|
||||
});
|
||||
|
||||
it('puts the movie source ahead of its overflow commands', async () => {
|
||||
const card = byTestId('download-library-movie-9');
|
||||
|
||||
await click(button(card, 'More actions: Moonrise'));
|
||||
|
||||
const header = document.querySelector<HTMLElement>(
|
||||
'.download-source-menu-header'
|
||||
);
|
||||
const copy = button(document, 'Copy download URL: Moonrise');
|
||||
const remove = button(document, 'Remove from manager: Moonrise');
|
||||
expect(header?.textContent?.replace(/\s+/g, ' ').trim()).toBe(
|
||||
'Source Cinema'
|
||||
);
|
||||
expect(
|
||||
header &&
|
||||
header.compareDocumentPosition(copy) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
copy.compareDocumentPosition(remove) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('opens downloaded episodes from the series overflow without a file action', async () => {
|
||||
const card = byTestId('download-library-series-playlist-a-77');
|
||||
const episodeGroups: DownloadSeriesCardViewModel[] = [];
|
||||
const actions: unknown[] = [];
|
||||
component.episodesOpened.subscribe((group) =>
|
||||
episodeGroups.push(group)
|
||||
);
|
||||
component.itemAction.subscribe((action) => actions.push(action));
|
||||
|
||||
await click(button(card, 'More actions: Northwind'));
|
||||
|
||||
const header = document.querySelector<HTMLElement>(
|
||||
'.download-source-menu-header'
|
||||
);
|
||||
expect(header?.textContent?.replace(/\s+/g, ' ').trim()).toBe(
|
||||
'Source Living room'
|
||||
);
|
||||
await click(button(document, 'Open downloaded episodes: Northwind'));
|
||||
|
||||
expect(episodeGroups).toEqual([SERIES]);
|
||||
expect(actions).toEqual([]);
|
||||
});
|
||||
|
||||
it('omits the named library section when no completed entity is visible', async () => {
|
||||
fixture.componentRef.setInput('entities', []);
|
||||
await fixture.whenStable();
|
||||
|
||||
@@ -19,6 +19,7 @@ import type {
|
||||
DownloadLibraryEntity,
|
||||
DownloadSeriesCardViewModel,
|
||||
} from './download-library.viewmodel';
|
||||
import { DownloadSourceMenuHeaderComponent } from './download-source-menu-header.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-download-library',
|
||||
@@ -29,6 +30,7 @@ import type {
|
||||
MatMenuModule,
|
||||
MatTooltipModule,
|
||||
TranslatePipe,
|
||||
DownloadSourceMenuHeaderComponent,
|
||||
],
|
||||
templateUrl: './download-library.component.html',
|
||||
styleUrl: './download-library.component.scss',
|
||||
|
||||
Reference in new issue
Block a user