mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 02:46:16 -08:00
fix(updater): tighten manual release fallback
This commit is contained in:
1 parent
93498182d5
commit
3db409cb5b
4 files changed
+100
-8
No files matched your search
@@ -176,6 +176,37 @@ describe('AppUpdateService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('loads additional GitHub release pages when the first page has no stable releases', async () => {
|
||||
const prereleasePage = Array.from({ length: 10 }, (_, index) => ({
|
||||
...githubReleases[2],
|
||||
name: `v0.25.${index}-beta`,
|
||||
tag_name: `v0.25.${index}-beta`,
|
||||
}));
|
||||
const fetcher = createReleaseFetcher([
|
||||
prereleasePage,
|
||||
[githubReleases[0]],
|
||||
]);
|
||||
const { service } = createService({
|
||||
env: {},
|
||||
fetcher,
|
||||
platform: 'linux',
|
||||
});
|
||||
|
||||
await service.checkForUpdates();
|
||||
|
||||
expect(fetcher).toHaveBeenCalledTimes(2);
|
||||
expect(
|
||||
fetcher.mock.calls.map(([url]) =>
|
||||
new URL(url).searchParams.get('page')
|
||||
)
|
||||
).toEqual(['1', '2']);
|
||||
expect(service.getStatus()).toMatchObject({
|
||||
latestVersion: '0.24.0',
|
||||
status: ELECTRON_BRIDGE_APP_UPDATE_STATUSES.Available,
|
||||
supportedSelfUpdate: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('starts a packaged startup check without downloading automatically', async () => {
|
||||
const { service, updater } = createService();
|
||||
|
||||
|
||||
@@ -439,7 +439,7 @@ export class AppUpdateService {
|
||||
}
|
||||
|
||||
private async checkGitHubReleaseForManualUpdate(): Promise<void> {
|
||||
await this.ensureReleasePageLoaded(1);
|
||||
await this.ensureFirstStableReleaseLoaded();
|
||||
const latestRelease = this.releases[0];
|
||||
|
||||
if (!latestRelease) {
|
||||
@@ -467,6 +467,12 @@ export class AppUpdateService {
|
||||
});
|
||||
}
|
||||
|
||||
private async ensureFirstStableReleaseLoaded(): Promise<void> {
|
||||
while (!this.loadedAllReleases && this.releases.length === 0) {
|
||||
await this.ensureReleasePageLoaded(this.loadedReleasePages + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private async findReleaseIndex(
|
||||
version: string | undefined
|
||||
): Promise<number> {
|
||||
|
||||
@@ -65,7 +65,9 @@ describe('AppUpdateNotificationPanelComponent', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(
|
||||
fixture.nativeElement.querySelector('[data-test-id="app-update-notification"]')
|
||||
fixture.nativeElement.querySelector(
|
||||
'[data-test-id="app-update-notification"]'
|
||||
)
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
@@ -86,7 +88,9 @@ describe('AppUpdateNotificationPanelComponent', () => {
|
||||
})
|
||||
);
|
||||
expect(
|
||||
fixture.nativeElement.querySelector('[data-test-id="app-update-notification"]')
|
||||
fixture.nativeElement.querySelector(
|
||||
'[data-test-id="app-update-notification"]'
|
||||
)
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
@@ -103,4 +107,34 @@ describe('AppUpdateNotificationPanelComponent', () => {
|
||||
|
||||
expect(window.electron.downloadAppUpdate).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('labels unsupported platform action as a GitHub release link', () => {
|
||||
const open = jest.spyOn(window, 'open').mockImplementation(() => null);
|
||||
statusHandler?.({
|
||||
...availableStatus,
|
||||
supportedSelfUpdate: false,
|
||||
});
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.nativeElement.querySelector(
|
||||
'[data-test-id="app-update-notification-download"]'
|
||||
) as HTMLButtonElement;
|
||||
|
||||
expect(button.textContent).toContain(
|
||||
'SETTINGS.APP_UPDATE_OPEN_RELEASE'
|
||||
);
|
||||
expect(button.querySelector('mat-icon')?.textContent?.trim()).toBe(
|
||||
'open_in_new'
|
||||
);
|
||||
|
||||
button.click();
|
||||
|
||||
expect(window.electron.downloadAppUpdate).not.toHaveBeenCalled();
|
||||
expect(open).toHaveBeenCalledWith(
|
||||
availableStatus.manualDownloadUrl,
|
||||
'_blank',
|
||||
'noreferrer'
|
||||
);
|
||||
open.mockRestore();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,11 @@
|
||||
import { Component, computed, OnDestroy, OnInit, signal, inject } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
computed,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
signal,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
@@ -46,7 +53,10 @@ import { AppUpdateReleaseNotesDialogComponent } from './settings/app-update-rele
|
||||
}}
|
||||
</strong>
|
||||
@if (status()?.progress; as progress) {
|
||||
<progress [value]="progress.percent" max="100"></progress>
|
||||
<progress
|
||||
[value]="progress.percent"
|
||||
max="100"
|
||||
></progress>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -76,13 +86,14 @@ import { AppUpdateReleaseNotesDialogComponent } from './settings/app-update-rele
|
||||
mat-flat-button
|
||||
type="button"
|
||||
[disabled]="
|
||||
status()?.status === appUpdateStatuses.Downloading
|
||||
status()?.status ===
|
||||
appUpdateStatuses.Downloading
|
||||
"
|
||||
(click)="downloadUpdate()"
|
||||
data-test-id="app-update-notification-download"
|
||||
>
|
||||
<mat-icon>download</mat-icon>
|
||||
{{ 'SETTINGS.APP_UPDATE_DOWNLOAD' | translate }}
|
||||
<mat-icon>{{ primaryActionIcon() }}</mat-icon>
|
||||
{{ primaryActionLabelKey() | translate }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -175,6 +186,16 @@ export class AppUpdateNotificationPanelComponent implements OnInit, OnDestroy {
|
||||
? 'SETTINGS.APP_UPDATE_DOWNLOADED'
|
||||
: 'SETTINGS.APP_UPDATE_AVAILABLE'
|
||||
);
|
||||
readonly primaryActionLabelKey = computed(() =>
|
||||
this.status()?.supportedSelfUpdate === false
|
||||
? 'SETTINGS.APP_UPDATE_OPEN_RELEASE'
|
||||
: 'SETTINGS.APP_UPDATE_DOWNLOAD'
|
||||
);
|
||||
readonly primaryActionIcon = computed(() =>
|
||||
this.status()?.supportedSelfUpdate === false
|
||||
? 'open_in_new'
|
||||
: 'download'
|
||||
);
|
||||
readonly isVisible = computed(() => {
|
||||
const status = this.status();
|
||||
|
||||
|
||||
Reference in new issue
Block a user