mirror of
https://github.com/RPCSX/rpcsx-ui.git
synced 2026-01-31 01:05:23 +01:00
Fix crash on shutdown
This commit is contained in:
@@ -91,7 +91,7 @@ tryFetchGame(const std::filesystem::directory_entry &entry) {
|
||||
|
||||
auto data = sfo::load(paramSfoPath.string());
|
||||
if (data.errc != sfo::error::ok) {
|
||||
elog("%s: error %d", entry.path().c_str(), data.errc);
|
||||
elog("%s: error %d", entry.path().c_str(), static_cast<int>(data.errc));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const mainWindow: Window = {
|
||||
};
|
||||
|
||||
export function initialize() {
|
||||
explorer.pushExplorerView(mainWindow, {
|
||||
return explorer.pushExplorerView(mainWindow, {
|
||||
filter: {
|
||||
type: 'game'
|
||||
}
|
||||
|
||||
@@ -117,8 +117,7 @@ async function activateMainWindow() {
|
||||
|
||||
setupElectron();
|
||||
|
||||
export function initialize() {
|
||||
console.log('web initialization');
|
||||
export async function initialize() {
|
||||
ipcMain.on('window/create', (_event, options) => {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -130,11 +129,6 @@ export function initialize() {
|
||||
win.loadURL(`app://-/${options.url}`);
|
||||
});
|
||||
|
||||
// console.log(await github.githubReleases({
|
||||
// owner: "RPCSX",
|
||||
// repository: "rpcsx"
|
||||
// }));
|
||||
|
||||
const createWindow = async () => {
|
||||
await activateMainWindow();
|
||||
|
||||
@@ -152,28 +146,31 @@ export function initialize() {
|
||||
uiInitializedFuture.dispose();
|
||||
|
||||
console.log('initialization complete');
|
||||
explorer.pushExplorerView(toWindow(MainWindow), {
|
||||
return explorer.pushExplorerView(toWindow(MainWindow), {
|
||||
filter: {
|
||||
type: 'game'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('window-all-closed', async () => {
|
||||
await core.shutdown(undefined);
|
||||
try {
|
||||
await core.shutdown(undefined);
|
||||
} catch (e) {
|
||||
console.error("shutdown throws exception", e);
|
||||
}
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
await app.whenReady();
|
||||
return createWindow();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ export type ComponentId = string;
|
||||
|
||||
export type Component = {
|
||||
getId(): ComponentId;
|
||||
onClose(listener: () => void): IDisposable;
|
||||
onClose(listener: () => void | Promise<void>): IDisposable;
|
||||
sendEvent(event: string, params?: any): void;
|
||||
};
|
||||
|
||||
@@ -12,8 +12,16 @@ export function onComponentActivation(component: ComponentInstance) {
|
||||
const rendererComponent: Component = {
|
||||
getId: () => ":renderer",
|
||||
onClose: (listener) => {
|
||||
webContents.on("destroyed", listener);
|
||||
return Disposable.Create(() => { webContents.off("destroyed", listener); });
|
||||
const wrapped = async () => {
|
||||
try {
|
||||
await listener();
|
||||
} catch (e) {
|
||||
console.error("onClose listener throws exception", e);
|
||||
}
|
||||
};
|
||||
|
||||
webContents.on("destroyed", wrapped);
|
||||
return Disposable.Create(() => { webContents.off("destroyed", wrapped); });
|
||||
},
|
||||
sendEvent: (event, params) => {
|
||||
webContents.send(`${component.getName()}/${event}`, params);
|
||||
|
||||
@@ -207,10 +207,7 @@ export class ComponentInstance implements ComponentContext {
|
||||
const externalDisposable = externalEmitter.event(listener);
|
||||
const emitterDisposable = emitter.event(listener);
|
||||
|
||||
const disposable = Disposable.Create(() => {
|
||||
externalDisposable.dispose();
|
||||
emitterDisposable.dispose();
|
||||
|
||||
const disposable = Disposable.Create(async () => {
|
||||
if (!externalEmitter.hasListeners()) {
|
||||
delete caller.externalEventEmitter[externalEvent];
|
||||
}
|
||||
@@ -219,6 +216,17 @@ export class ComponentInstance implements ComponentContext {
|
||||
delete this.eventEmitter[event];
|
||||
}
|
||||
|
||||
try {
|
||||
await externalDisposable.dispose();
|
||||
} catch (e) {
|
||||
console.error('externalDisposable throws error', e);
|
||||
}
|
||||
|
||||
try {
|
||||
await emitterDisposable.dispose();
|
||||
} catch (e) {
|
||||
console.error('emitterDisposable throws error', e);
|
||||
}
|
||||
});
|
||||
|
||||
caller.manage(disposable);
|
||||
|
||||
@@ -20,6 +20,10 @@ export async function activate() {
|
||||
await Promise.all(Object.values(components).map(component => initializeComponent(component.getManifest())));
|
||||
|
||||
for (const component of Object.values(components)) {
|
||||
if (component.getName() == "core") {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await instance.activateComponent(component.getManifest());
|
||||
} catch (e) {
|
||||
@@ -34,6 +38,9 @@ export async function deactivate() {
|
||||
const components = getComponentList();
|
||||
|
||||
for (const component of Object.values(components)) {
|
||||
if (component.getName() == "core") {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await instance.unregisterComponent(component.getId());
|
||||
} catch (e) {
|
||||
@@ -189,5 +196,5 @@ export async function handleSettingsGet(caller: Component, request: SettingsGetR
|
||||
|
||||
export async function shutdown(caller: Component, _request: ShutdownRequest): Promise<ShutdownResponse> {
|
||||
console.warn(`shutdown invoked by ${caller.getId()}`);
|
||||
instance.uninitializeComponent(self.thisComponent().getManifest());
|
||||
await instance.uninitializeComponent(self.thisComponent().getManifest());
|
||||
}
|
||||
|
||||
@@ -139,22 +139,24 @@ export class ExplorerComponent implements IDisposable {
|
||||
title: "Explorer progress"
|
||||
})).channel;
|
||||
|
||||
const closeDisposable = caller.onClose(async () => {
|
||||
delete this.subscriptions[progressChannel];
|
||||
|
||||
await progress.progressUpdate({
|
||||
channel: progressChannel,
|
||||
status: ProgressStatus.Canceled
|
||||
});
|
||||
});
|
||||
|
||||
progress.onProgressUpdate(({ value }) => {
|
||||
if (value.status == ProgressStatus.Canceled) {
|
||||
closeDisposable.dispose();
|
||||
delete this.subscriptions[progressChannel];
|
||||
}
|
||||
});
|
||||
|
||||
this.subscriptions[progressChannel] = caller;
|
||||
|
||||
caller.onClose(() => {
|
||||
progress.progressUpdate({
|
||||
channel: progressChannel,
|
||||
status: ProgressStatus.Canceled
|
||||
});
|
||||
|
||||
delete this.subscriptions[progressChannel];
|
||||
});
|
||||
|
||||
self.sendExplorerItemsEvent(caller, {
|
||||
channel: progressChannel,
|
||||
|
||||
@@ -60,14 +60,14 @@ export function progressCreate(source: Component, params: ProgressCreateRequest)
|
||||
return { channel };
|
||||
}
|
||||
|
||||
export function progressUpdate(caller: Component, params: ProgressUpdateRequest) {
|
||||
export async function progressUpdate(caller: Component, params: ProgressUpdateRequest) {
|
||||
const info = channels[params.channel];
|
||||
|
||||
if (!info) {
|
||||
throw { code: ErrorCode.InvalidParams };
|
||||
}
|
||||
|
||||
if (info.creator != caller) {
|
||||
if (info.creator.getId() != caller.getId()) {
|
||||
throw { code: ErrorCode.InvalidRequest };
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export function progressUpdate(caller: Component, params: ProgressUpdateRequest)
|
||||
params.status == ProgressStatus.Complete ||
|
||||
params.status == ProgressStatus.Error) {
|
||||
if (info.disposable) {
|
||||
info.disposable.dispose();
|
||||
await info.disposable.dispose();
|
||||
}
|
||||
|
||||
delete channels[params.channel];
|
||||
|
||||
Reference in New Issue
Block a user