mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 21:56:18 -08:00
feat(downloads): download completed Xtream catch-up programmes as TS (#1572)
* feat(epg): copy catch-up programme URLs without changing playback * feat(downloads): save completed Xtream archive programmes as TS * fix(epg): let newer archive copy requests supersede pending work * fix(downloads): protect archive partials and independent submissions * fix(downloads): verify archive identity through finalization * fix(downloads): bound archive storage and capture cleanup entries * fix(downloads): preserve archive ownership across failure paths * fix(downloads): recover explicitly verified archive completions * fix(downloads): journal archive promotion before publishing files * fix(downloads): reset archive proof before an explicit restart * fix(downloads): preserve archive recovery ownership and interruption * fix(downloads): verify durable archive identity at resume open * fix(downloads): fence archive commands during completion commit * fix(downloads): persist archive ownership throughout its lifecycle * fix(downloads): protect archive removal and missing-file recovery * fix(downloads): journal private cleanup captures for recovery * fix(downloads): journal active archive cleanup before removal * fix(downloads): clean settled archives before deleting stale rows * fix(downloads): preserve archive ownership on removal and resubmission * fix(downloads): recover proven archive completions before retry * fix(downloads): recover local archives before remote transfer checks * test(downloads): resolve archive fixture from workspace root * fix(downloads): distinguish reused archive inodes by creation time * fix(downloads): bind fresh archive reservations to owned files * fix(downloads): clean reservations when ownership writes fail * fix(downloads): commit archive reservation and ownership atomically * fix(downloads): retain captures until replacement restoration succeeds * fix(downloads): require durable ownership before cleanup relocation * fix(downloads): preserve 64-bit archive file identities on Windows * refactor(release): keep capture fixture constants in their shared module * fix(downloads): preserve the last link of captured foreign files * fix(downloads): expose retained archive recovery files * fix(downloads): keep recovery instructions open while copying
This commit is contained in:
1 parent
a7f3860102
commit
bad8a0991e
117 files changed
+7510
-880
No files matched your search
@@ -0,0 +1,54 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ConfirmDialogComponent } from './confirm-dialog.component';
|
||||
|
||||
describe('ConfirmDialogComponent actions', () => {
|
||||
it.each([false, true])(
|
||||
'keeps the action in place only when requested: %s',
|
||||
async (keepOpenOnConfirm) => {
|
||||
const onConfirm = jest.fn();
|
||||
const close = jest.fn();
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
ConfirmDialogComponent,
|
||||
NoopAnimationsModule,
|
||||
TranslateModule.forRoot(),
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: MAT_DIALOG_DATA,
|
||||
useValue: {
|
||||
title: 'Recovery',
|
||||
message: '/saved/entry',
|
||||
confirmLabel: 'Copy',
|
||||
cancelLabel: 'Close',
|
||||
keepOpenOnConfirm,
|
||||
onConfirm,
|
||||
},
|
||||
},
|
||||
{ provide: MatDialogRef, useValue: { close } },
|
||||
],
|
||||
}).compileComponents();
|
||||
const fixture = TestBed.createComponent(ConfirmDialogComponent);
|
||||
fixture.detectChanges();
|
||||
const buttons = fixture.nativeElement.querySelectorAll(
|
||||
'button'
|
||||
) as NodeListOf<HTMLButtonElement>;
|
||||
buttons[1].click();
|
||||
if (keepOpenOnConfirm) {
|
||||
expect(onConfirm).toHaveBeenCalledTimes(1);
|
||||
expect(close).not.toHaveBeenCalled();
|
||||
expect(fixture.nativeElement.textContent).toContain(
|
||||
'/saved/entry'
|
||||
);
|
||||
} else {
|
||||
expect(onConfirm).not.toHaveBeenCalled();
|
||||
expect(close).toHaveBeenCalledWith(true);
|
||||
}
|
||||
buttons[0].click();
|
||||
expect(close).toHaveBeenCalled();
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -9,6 +9,8 @@ export interface ConfirmDialogData {
|
||||
width?: string;
|
||||
confirmLabel?: string;
|
||||
cancelLabel?: string;
|
||||
/** Run the action in the dialog; only Close/backdrop/Escape dismiss it. */
|
||||
keepOpenOnConfirm?: boolean;
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
@@ -25,9 +27,23 @@ export interface ConfirmDialogData {
|
||||
<button mat-button mat-dialog-close cdkFocusInitial>
|
||||
{{ dialogData.cancelLabel || 'NO' | translate }}
|
||||
</button>
|
||||
<button mat-flat-button [mat-dialog-close]="true" color="primary">
|
||||
{{ dialogData.confirmLabel || 'YES' | translate }}
|
||||
</button>
|
||||
@if (dialogData.keepOpenOnConfirm) {
|
||||
<button
|
||||
mat-flat-button
|
||||
(click)="dialogData.onConfirm()"
|
||||
color="primary"
|
||||
>
|
||||
{{ dialogData.confirmLabel || 'YES' | translate }}
|
||||
</button>
|
||||
} @else {
|
||||
<button
|
||||
mat-flat-button
|
||||
[mat-dialog-close]="true"
|
||||
color="primary"
|
||||
>
|
||||
{{ dialogData.confirmLabel || 'YES' | translate }}
|
||||
</button>
|
||||
}
|
||||
</mat-dialog-actions>
|
||||
`,
|
||||
})
|
||||
|
||||
@@ -83,4 +83,15 @@ describe('DialogService', () => {
|
||||
|
||||
expect(onConfirm).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it('does not repeat a persistent dialog action on programmatic close', () => {
|
||||
const onConfirm = jest.fn();
|
||||
dialog.open.mockReturnValue({ afterClosed: () => of(true) });
|
||||
service.openConfirmDialog({
|
||||
title: 'Recovery',
|
||||
message: 'Path',
|
||||
keepOpenOnConfirm: true,
|
||||
onConfirm,
|
||||
});
|
||||
expect(onConfirm).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -28,6 +28,8 @@ export class DialogService {
|
||||
});
|
||||
dialogRef
|
||||
.afterClosed()
|
||||
.subscribe((result) => (result ? data.onConfirm() : null));
|
||||
.subscribe((result) =>
|
||||
result && !data.keepOpenOnConfirm ? data.onConfirm() : null
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user