mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-12 03:13:39 -07:00
refactor(main): extract update service runtime from main.ts
This commit is contained in:
+14
-173
@@ -144,7 +144,6 @@ import type {
|
|||||||
OverlayNotificationPayload,
|
OverlayNotificationPayload,
|
||||||
OverlayNotificationEventPayload,
|
OverlayNotificationEventPayload,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
UpdateChannel,
|
|
||||||
WindowGeometry,
|
WindowGeometry,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { OPEN_ANKI_CARD_ACTION_ID } from './types';
|
import { OPEN_ANKI_CARD_ACTION_ID } from './types';
|
||||||
@@ -589,26 +588,8 @@ import {
|
|||||||
import { restoreLinuxOverlayWindowShape } from './main/runtime/linux-overlay-window-shape';
|
import { restoreLinuxOverlayWindowShape } from './main/runtime/linux-overlay-window-shape';
|
||||||
import { createJellyfinSubtitleCacheIo } from './main/runtime/jellyfin-subtitle-cache-io';
|
import { createJellyfinSubtitleCacheIo } from './main/runtime/jellyfin-subtitle-cache-io';
|
||||||
import { createStartupOsdSequencer } from './main/runtime/startup-osd-sequencer';
|
import { createStartupOsdSequencer } from './main/runtime/startup-osd-sequencer';
|
||||||
import {
|
|
||||||
createElectronAppUpdater,
|
|
||||||
isNativeUpdaterSupported,
|
|
||||||
} from './main/runtime/update/app-updater';
|
|
||||||
import { createCurlFetch, createGlobalFetch } from './main/runtime/update/fetch-adapter';
|
|
||||||
import { createCurlHttpExecutor } from './main/runtime/update/curl-http-executor';
|
|
||||||
import { createFetchHttpExecutor } from './main/runtime/update/fetch-http-executor';
|
|
||||||
import {
|
|
||||||
fetchLatestStableRelease,
|
|
||||||
fetchReleaseAssetBuffer,
|
|
||||||
fetchReleaseAssetText,
|
|
||||||
findReleaseAsset,
|
|
||||||
parseSha256Sums,
|
|
||||||
type GitHubRelease,
|
|
||||||
} from './main/runtime/update/release-assets';
|
|
||||||
import { shouldFetchReleaseMetadataForPlatform } from './main/runtime/update/release-metadata-policy';
|
|
||||||
import { updateLauncherFromRelease } from './main/runtime/update/launcher-updater';
|
|
||||||
import {
|
import {
|
||||||
INSTALL_UPDATE_ACTION_ID,
|
INSTALL_UPDATE_ACTION_ID,
|
||||||
notifyUpdateAvailable,
|
|
||||||
UPDATE_AVAILABLE_NOTIFICATION_ID,
|
UPDATE_AVAILABLE_NOTIFICATION_ID,
|
||||||
} from './main/runtime/update/update-notifications';
|
} from './main/runtime/update/update-notifications';
|
||||||
import { createOverlayLoadingOsdController } from './main/runtime/overlay-loading-osd';
|
import { createOverlayLoadingOsdController } from './main/runtime/overlay-loading-osd';
|
||||||
@@ -621,16 +602,11 @@ import {
|
|||||||
type ConfiguredStatusNotificationOptions,
|
type ConfiguredStatusNotificationOptions,
|
||||||
} from './main/runtime/configured-status-notification';
|
} from './main/runtime/configured-status-notification';
|
||||||
import { resolveOverlayReadinessNotificationType } from './main/runtime/notification-routing';
|
import { resolveOverlayReadinessNotificationType } from './main/runtime/notification-routing';
|
||||||
import { createUpdateDialogPresenter } from './main/runtime/update/update-dialogs';
|
|
||||||
import {
|
import {
|
||||||
runUpdateCliCommand,
|
runUpdateCliCommand,
|
||||||
writeUpdateCliCommandResponse,
|
writeUpdateCliCommandResponse,
|
||||||
} from './main/runtime/update/update-cli-command';
|
} from './main/runtime/update/update-cli-command';
|
||||||
import {
|
import { createUpdateServiceRuntime } from './main/runtime/update/update-service-runtime';
|
||||||
createFileUpdateStateStore,
|
|
||||||
createUpdateService,
|
|
||||||
} from './main/runtime/update/update-service';
|
|
||||||
import { updateSupportAssetsFromRelease } from './main/runtime/update/support-assets';
|
|
||||||
import {
|
import {
|
||||||
createRefreshSubtitlePrefetchFromActiveTrackHandler,
|
createRefreshSubtitlePrefetchFromActiveTrackHandler,
|
||||||
createResolveActiveSubtitleSidebarSourceHandler,
|
createResolveActiveSubtitleSidebarSourceHandler,
|
||||||
@@ -743,7 +719,6 @@ const ANILIST_UPDATE_MIN_WATCH_SECONDS = 10 * 60;
|
|||||||
const ANILIST_DURATION_RETRY_INTERVAL_MS = 15_000;
|
const ANILIST_DURATION_RETRY_INTERVAL_MS = 15_000;
|
||||||
const ANILIST_MAX_ATTEMPTED_UPDATE_KEYS = 1000;
|
const ANILIST_MAX_ATTEMPTED_UPDATE_KEYS = 1000;
|
||||||
const TRAY_TOOLTIP = 'SubMiner';
|
const TRAY_TOOLTIP = 'SubMiner';
|
||||||
const SUBMINER_BUNDLE_ID = 'com.sudacode.SubMiner';
|
|
||||||
const JELLYFIN_SETUP_PRELOAD_PATH = path.join(__dirname, 'preload-jellyfin-setup.js');
|
const JELLYFIN_SETUP_PRELOAD_PATH = path.join(__dirname, 'preload-jellyfin-setup.js');
|
||||||
|
|
||||||
let anilistMediaGuessRuntimeState: AnilistMediaGuessRuntimeState =
|
let anilistMediaGuessRuntimeState: AnilistMediaGuessRuntimeState =
|
||||||
@@ -6401,153 +6376,19 @@ flushPendingMpvLogWrites = () => {
|
|||||||
void flushMpvLog();
|
void flushMpvLog();
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateStateStore = createFileUpdateStateStore(path.join(USER_DATA_PATH, 'update-state.json'));
|
const { getUpdateService } = createUpdateServiceRuntime({
|
||||||
let updateService: ReturnType<typeof createUpdateService> | null = null;
|
userDataPath: USER_DATA_PATH,
|
||||||
const globalFetchForUpdater = createGlobalFetch();
|
getUpdatesConfig: () => getResolvedConfig().updates,
|
||||||
const curlFetch = createCurlFetch();
|
logInfo: (message) => logger.info(message),
|
||||||
|
logWarn: (message, details) => logger.warn(message, details),
|
||||||
function createNativeUpdaterHttpExecutor() {
|
showOverlayNotification,
|
||||||
if (process.platform === 'win32') {
|
showDesktopNotification: (title, options) => showDesktopNotification(title, options),
|
||||||
return createFetchHttpExecutor();
|
showMpvOsd: (message) => {
|
||||||
}
|
showMpvOsd(message);
|
||||||
return createCurlHttpExecutor();
|
},
|
||||||
}
|
withStatsWindowLayerSuspendedForNativeDialog: (showDialog) =>
|
||||||
|
withStatsWindowLayerSuspendedForNativeDialog(showDialog),
|
||||||
function getFetchForUpdater() {
|
});
|
||||||
if (process.platform === 'win32') return globalFetchForUpdater;
|
|
||||||
return curlFetch;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateLauncherFromSelectedRelease(
|
|
||||||
launcherPath?: string,
|
|
||||||
channel: UpdateChannel = getResolvedConfig().updates.channel,
|
|
||||||
release: GitHubRelease | null = null,
|
|
||||||
) {
|
|
||||||
const fetchForUpdater = getFetchForUpdater();
|
|
||||||
if (!release) {
|
|
||||||
return { status: 'missing-asset', message: `No ${channel} GitHub release found.` };
|
|
||||||
}
|
|
||||||
const sumsAsset = findReleaseAsset(release, 'SHA256SUMS.txt');
|
|
||||||
if (!sumsAsset) {
|
|
||||||
return { status: 'missing-asset', message: 'Release has no SHA256SUMS.txt asset.' };
|
|
||||||
}
|
|
||||||
const sums = parseSha256Sums(
|
|
||||||
await fetchReleaseAssetText(fetchForUpdater, sumsAsset.browser_download_url),
|
|
||||||
);
|
|
||||||
const launcherResult = await updateLauncherFromRelease({
|
|
||||||
release,
|
|
||||||
sha256Sums: sums,
|
|
||||||
launcherPath,
|
|
||||||
downloadAsset: (url) => fetchReleaseAssetBuffer(fetchForUpdater, url),
|
|
||||||
});
|
|
||||||
const supportResults = await updateSupportAssetsFromRelease({
|
|
||||||
release,
|
|
||||||
sha256Sums: sums,
|
|
||||||
downloadAsset: (url) => fetchReleaseAssetBuffer(fetchForUpdater, url),
|
|
||||||
});
|
|
||||||
for (const result of supportResults) {
|
|
||||||
if (result.status === 'protected' && result.command) {
|
|
||||||
logger.warn(`Rofi theme update requires manual command: ${result.command}`);
|
|
||||||
} else if (result.status === 'hash-mismatch' || result.status === 'missing-asset') {
|
|
||||||
logger.warn(`Rofi theme update skipped: ${result.message ?? result.status}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return launcherResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUpdateService() {
|
|
||||||
if (updateService) return updateService;
|
|
||||||
const appUpdater = createElectronAppUpdater({
|
|
||||||
currentVersion: app.getVersion(),
|
|
||||||
isPackaged: app.isPackaged,
|
|
||||||
log: (message) => logger.info(message),
|
|
||||||
getChannel: () => getResolvedConfig().updates.channel,
|
|
||||||
configureHttpExecutor: createNativeUpdaterHttpExecutor,
|
|
||||||
disableDifferentialDownload: true,
|
|
||||||
isNativeUpdaterSupported: () =>
|
|
||||||
isNativeUpdaterSupported({
|
|
||||||
platform: process.platform,
|
|
||||||
isPackaged: app.isPackaged,
|
|
||||||
execPath: process.execPath,
|
|
||||||
env: process.env,
|
|
||||||
log: (message) => logger.warn(message),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const updateDialogPresenter = createUpdateDialogPresenter({
|
|
||||||
platform: process.platform,
|
|
||||||
focusApp: async () => {
|
|
||||||
if (process.platform !== 'darwin') {
|
|
||||||
app.focus({ steal: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await app.dock?.show();
|
|
||||||
} catch (error) {
|
|
||||||
logger.warn('Failed to show macOS dock before update dialog', error);
|
|
||||||
}
|
|
||||||
// app.focus({ steal: true }) alone does not reliably activate the process
|
|
||||||
// when SubMiner was reached via `subminer -u` (single-instance forwarding
|
|
||||||
// from a CLI-spawned child). osascript's `activate` uses LaunchServices,
|
|
||||||
// which is the only path that reliably brings the running app forward.
|
|
||||||
await new Promise<void>((resolve) => {
|
|
||||||
execFile(
|
|
||||||
'/usr/bin/osascript',
|
|
||||||
['-e', `tell application id "${SUBMINER_BUNDLE_ID}" to activate`],
|
|
||||||
{ timeout: 2000 },
|
|
||||||
(error) => {
|
|
||||||
if (error) {
|
|
||||||
logger.warn(
|
|
||||||
`Failed to activate SubMiner via osascript: ${error instanceof Error ? error.message : String(error)}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
app.focus({ steal: true });
|
|
||||||
},
|
|
||||||
withStatsWindowLayerSuspended: (showDialog) =>
|
|
||||||
withStatsWindowLayerSuspendedForNativeDialog(showDialog),
|
|
||||||
showMessageBox: (options) => dialog.showMessageBox(options),
|
|
||||||
});
|
|
||||||
updateService = createUpdateService({
|
|
||||||
getConfig: () => getResolvedConfig().updates,
|
|
||||||
getCurrentVersion: () => app.getVersion(),
|
|
||||||
now: () => Date.now(),
|
|
||||||
readState: () => updateStateStore.readState(),
|
|
||||||
writeState: (state) => updateStateStore.writeState(state),
|
|
||||||
checkAppUpdate: (channel) => appUpdater.checkForUpdates(channel),
|
|
||||||
shouldFetchReleaseMetadata: ({ request, appUpdate }) =>
|
|
||||||
shouldFetchReleaseMetadataForPlatform(process.platform, appUpdate, request),
|
|
||||||
fetchLatestStableRelease: (channel) =>
|
|
||||||
fetchLatestStableRelease({ fetch: getFetchForUpdater(), channel }),
|
|
||||||
updateLauncher: (launcherPath, channel, release) =>
|
|
||||||
updateLauncherFromSelectedRelease(launcherPath, channel, release),
|
|
||||||
showNoUpdateDialog: (version) => updateDialogPresenter.showNoUpdateDialog(version),
|
|
||||||
showUpdateAvailableDialog: (version) =>
|
|
||||||
updateDialogPresenter.showUpdateAvailableDialog(version),
|
|
||||||
showUpdateFailedDialog: (message) => updateDialogPresenter.showUpdateFailedDialog(message),
|
|
||||||
showManualUpdateRequiredDialog: (version) =>
|
|
||||||
updateDialogPresenter.showManualUpdateRequiredDialog(version),
|
|
||||||
downloadAppUpdate: () => appUpdater.downloadUpdate(),
|
|
||||||
showRestartDialog: () => updateDialogPresenter.showRestartDialog(),
|
|
||||||
quitAndInstall: () => appUpdater.quitAndInstall(),
|
|
||||||
notifyUpdateAvailable: (version) =>
|
|
||||||
notifyUpdateAvailable(
|
|
||||||
{ notificationType: getResolvedConfig().updates.notificationType, version },
|
|
||||||
{
|
|
||||||
showSystemNotification: (title, body) => showDesktopNotification(title, { body }),
|
|
||||||
showOverlayNotification,
|
|
||||||
showOsdNotification: (message) => {
|
|
||||||
showMpvOsd(message);
|
|
||||||
},
|
|
||||||
log: (message) => logger.warn(message),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
log: (message) => logger.warn(message),
|
|
||||||
});
|
|
||||||
return updateService;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cycleSecondarySubMode = createCycleSecondarySubModeRuntimeHandler({
|
const cycleSecondarySubMode = createCycleSecondarySubModeRuntimeHandler({
|
||||||
cycleSecondarySubModeMainDeps: {
|
cycleSecondarySubModeMainDeps: {
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
import { app, dialog } from 'electron';
|
||||||
|
import { execFile } from 'node:child_process';
|
||||||
|
import path from 'node:path';
|
||||||
|
import type { UpdateChannel, UpdatesConfig } from '../../../types/config';
|
||||||
|
import type { OverlayNotificationPayload } from '../../../types/notification';
|
||||||
|
import { createElectronAppUpdater, isNativeUpdaterSupported } from './app-updater';
|
||||||
|
import { createCurlFetch, createGlobalFetch } from './fetch-adapter';
|
||||||
|
import { createCurlHttpExecutor } from './curl-http-executor';
|
||||||
|
import { createFetchHttpExecutor } from './fetch-http-executor';
|
||||||
|
import {
|
||||||
|
fetchLatestStableRelease,
|
||||||
|
fetchReleaseAssetBuffer,
|
||||||
|
fetchReleaseAssetText,
|
||||||
|
findReleaseAsset,
|
||||||
|
parseSha256Sums,
|
||||||
|
type GitHubRelease,
|
||||||
|
} from './release-assets';
|
||||||
|
import { shouldFetchReleaseMetadataForPlatform } from './release-metadata-policy';
|
||||||
|
import { updateLauncherFromRelease } from './launcher-updater';
|
||||||
|
import { notifyUpdateAvailable } from './update-notifications';
|
||||||
|
import { createUpdateDialogPresenter } from './update-dialogs';
|
||||||
|
import { createFileUpdateStateStore, createUpdateService } from './update-service';
|
||||||
|
import { updateSupportAssetsFromRelease } from './support-assets';
|
||||||
|
|
||||||
|
const SUBMINER_BUNDLE_ID = 'com.sudacode.SubMiner';
|
||||||
|
|
||||||
|
export interface UpdateServiceRuntimeDeps {
|
||||||
|
userDataPath: string;
|
||||||
|
getUpdatesConfig: () => Required<UpdatesConfig>;
|
||||||
|
logInfo: (message: string) => void;
|
||||||
|
logWarn: (message: string, details?: unknown) => void;
|
||||||
|
showOverlayNotification: (payload: OverlayNotificationPayload) => void;
|
||||||
|
showDesktopNotification: (title: string, options: { body: string }) => void;
|
||||||
|
showMpvOsd: (message: string) => void;
|
||||||
|
withStatsWindowLayerSuspendedForNativeDialog: <T>(showDialog: () => Promise<T>) => Promise<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createUpdateServiceRuntime(deps: UpdateServiceRuntimeDeps): {
|
||||||
|
getUpdateService: () => ReturnType<typeof createUpdateService>;
|
||||||
|
} {
|
||||||
|
const updateStateStore = createFileUpdateStateStore(
|
||||||
|
path.join(deps.userDataPath, 'update-state.json'),
|
||||||
|
);
|
||||||
|
let updateService: ReturnType<typeof createUpdateService> | null = null;
|
||||||
|
const globalFetchForUpdater = createGlobalFetch();
|
||||||
|
const curlFetch = createCurlFetch();
|
||||||
|
|
||||||
|
function createNativeUpdaterHttpExecutor() {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
return createFetchHttpExecutor();
|
||||||
|
}
|
||||||
|
return createCurlHttpExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFetchForUpdater() {
|
||||||
|
if (process.platform === 'win32') return globalFetchForUpdater;
|
||||||
|
return curlFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateLauncherFromSelectedRelease(
|
||||||
|
launcherPath?: string,
|
||||||
|
channel: UpdateChannel = deps.getUpdatesConfig().channel,
|
||||||
|
release: GitHubRelease | null = null,
|
||||||
|
) {
|
||||||
|
const fetchForUpdater = getFetchForUpdater();
|
||||||
|
if (!release) {
|
||||||
|
return { status: 'missing-asset', message: `No ${channel} GitHub release found.` };
|
||||||
|
}
|
||||||
|
const sumsAsset = findReleaseAsset(release, 'SHA256SUMS.txt');
|
||||||
|
if (!sumsAsset) {
|
||||||
|
return { status: 'missing-asset', message: 'Release has no SHA256SUMS.txt asset.' };
|
||||||
|
}
|
||||||
|
const sums = parseSha256Sums(
|
||||||
|
await fetchReleaseAssetText(fetchForUpdater, sumsAsset.browser_download_url),
|
||||||
|
);
|
||||||
|
const launcherResult = await updateLauncherFromRelease({
|
||||||
|
release,
|
||||||
|
sha256Sums: sums,
|
||||||
|
launcherPath,
|
||||||
|
downloadAsset: (url) => fetchReleaseAssetBuffer(fetchForUpdater, url),
|
||||||
|
});
|
||||||
|
const supportResults = await updateSupportAssetsFromRelease({
|
||||||
|
release,
|
||||||
|
sha256Sums: sums,
|
||||||
|
downloadAsset: (url) => fetchReleaseAssetBuffer(fetchForUpdater, url),
|
||||||
|
});
|
||||||
|
for (const result of supportResults) {
|
||||||
|
if (result.status === 'protected' && result.command) {
|
||||||
|
deps.logWarn(`Rofi theme update requires manual command: ${result.command}`);
|
||||||
|
} else if (result.status === 'hash-mismatch' || result.status === 'missing-asset') {
|
||||||
|
deps.logWarn(`Rofi theme update skipped: ${result.message ?? result.status}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return launcherResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUpdateService() {
|
||||||
|
if (updateService) return updateService;
|
||||||
|
const appUpdater = createElectronAppUpdater({
|
||||||
|
currentVersion: app.getVersion(),
|
||||||
|
isPackaged: app.isPackaged,
|
||||||
|
log: (message) => deps.logInfo(message),
|
||||||
|
getChannel: () => deps.getUpdatesConfig().channel,
|
||||||
|
configureHttpExecutor: createNativeUpdaterHttpExecutor,
|
||||||
|
disableDifferentialDownload: true,
|
||||||
|
isNativeUpdaterSupported: () =>
|
||||||
|
isNativeUpdaterSupported({
|
||||||
|
platform: process.platform,
|
||||||
|
isPackaged: app.isPackaged,
|
||||||
|
execPath: process.execPath,
|
||||||
|
env: process.env,
|
||||||
|
log: (message) => deps.logWarn(message),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const updateDialogPresenter = createUpdateDialogPresenter({
|
||||||
|
platform: process.platform,
|
||||||
|
focusApp: async () => {
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.focus({ steal: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await app.dock?.show();
|
||||||
|
} catch (error) {
|
||||||
|
deps.logWarn('Failed to show macOS dock before update dialog', error);
|
||||||
|
}
|
||||||
|
// app.focus({ steal: true }) alone does not reliably activate the process
|
||||||
|
// when SubMiner was reached via `subminer -u` (single-instance forwarding
|
||||||
|
// from a CLI-spawned child). osascript's `activate` uses LaunchServices,
|
||||||
|
// which is the only path that reliably brings the running app forward.
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
execFile(
|
||||||
|
'/usr/bin/osascript',
|
||||||
|
['-e', `tell application id "${SUBMINER_BUNDLE_ID}" to activate`],
|
||||||
|
{ timeout: 2000 },
|
||||||
|
(error) => {
|
||||||
|
if (error) {
|
||||||
|
deps.logWarn(
|
||||||
|
`Failed to activate SubMiner via osascript: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
app.focus({ steal: true });
|
||||||
|
},
|
||||||
|
withStatsWindowLayerSuspended: (showDialog) =>
|
||||||
|
deps.withStatsWindowLayerSuspendedForNativeDialog(showDialog),
|
||||||
|
showMessageBox: (options) => dialog.showMessageBox(options),
|
||||||
|
});
|
||||||
|
updateService = createUpdateService({
|
||||||
|
getConfig: () => deps.getUpdatesConfig(),
|
||||||
|
getCurrentVersion: () => app.getVersion(),
|
||||||
|
now: () => Date.now(),
|
||||||
|
readState: () => updateStateStore.readState(),
|
||||||
|
writeState: (state) => updateStateStore.writeState(state),
|
||||||
|
checkAppUpdate: (channel) => appUpdater.checkForUpdates(channel),
|
||||||
|
shouldFetchReleaseMetadata: ({ request, appUpdate }) =>
|
||||||
|
shouldFetchReleaseMetadataForPlatform(process.platform, appUpdate, request),
|
||||||
|
fetchLatestStableRelease: (channel) =>
|
||||||
|
fetchLatestStableRelease({ fetch: getFetchForUpdater(), channel }),
|
||||||
|
updateLauncher: (launcherPath, channel, release) =>
|
||||||
|
updateLauncherFromSelectedRelease(launcherPath, channel, release),
|
||||||
|
showNoUpdateDialog: (version) => updateDialogPresenter.showNoUpdateDialog(version),
|
||||||
|
showUpdateAvailableDialog: (version) =>
|
||||||
|
updateDialogPresenter.showUpdateAvailableDialog(version),
|
||||||
|
showUpdateFailedDialog: (message) => updateDialogPresenter.showUpdateFailedDialog(message),
|
||||||
|
showManualUpdateRequiredDialog: (version) =>
|
||||||
|
updateDialogPresenter.showManualUpdateRequiredDialog(version),
|
||||||
|
downloadAppUpdate: () => appUpdater.downloadUpdate(),
|
||||||
|
showRestartDialog: () => updateDialogPresenter.showRestartDialog(),
|
||||||
|
quitAndInstall: () => appUpdater.quitAndInstall(),
|
||||||
|
notifyUpdateAvailable: (version) =>
|
||||||
|
notifyUpdateAvailable(
|
||||||
|
{ notificationType: deps.getUpdatesConfig().notificationType, version },
|
||||||
|
{
|
||||||
|
showSystemNotification: (title, body) => deps.showDesktopNotification(title, { body }),
|
||||||
|
showOverlayNotification: (payload) => deps.showOverlayNotification(payload),
|
||||||
|
showOsdNotification: (message) => {
|
||||||
|
deps.showMpvOsd(message);
|
||||||
|
},
|
||||||
|
log: (message) => deps.logWarn(message),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
log: (message) => deps.logWarn(message),
|
||||||
|
});
|
||||||
|
return updateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getUpdateService };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user