mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Desktop: Ask to start in safe mode when the application has crashed
This commit is contained in:
parent
bd917ae09c
commit
d9a4a9cb30
@ -808,6 +808,9 @@ packages/app-desktop/services/plugins/hooks/useViewIsReady.js.map
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.d.ts
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js.map
|
||||
packages/app-desktop/services/restart.d.ts
|
||||
packages/app-desktop/services/restart.js
|
||||
packages/app-desktop/services/restart.js.map
|
||||
packages/app-desktop/services/share/invitationRespond.d.ts
|
||||
packages/app-desktop/services/share/invitationRespond.js
|
||||
packages/app-desktop/services/share/invitationRespond.js.map
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -798,6 +798,9 @@ packages/app-desktop/services/plugins/hooks/useViewIsReady.js.map
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.d.ts
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js.map
|
||||
packages/app-desktop/services/restart.d.ts
|
||||
packages/app-desktop/services/restart.js
|
||||
packages/app-desktop/services/restart.js.map
|
||||
packages/app-desktop/services/share/invitationRespond.d.ts
|
||||
packages/app-desktop/services/share/invitationRespond.js
|
||||
packages/app-desktop/services/share/invitationRespond.js.map
|
||||
|
@ -192,7 +192,7 @@ export default class ElectronAppWrapper {
|
||||
// We got the response from the renderer process:
|
||||
// save the response and try quit again.
|
||||
this.rendererProcessQuitReply_ = args;
|
||||
this.electronApp_.quit();
|
||||
this.quit();
|
||||
}
|
||||
});
|
||||
|
||||
@ -253,7 +253,7 @@ export default class ElectronAppWrapper {
|
||||
});
|
||||
}
|
||||
|
||||
async quit() {
|
||||
quit() {
|
||||
this.electronApp_.quit();
|
||||
}
|
||||
|
||||
@ -325,7 +325,7 @@ export default class ElectronAppWrapper {
|
||||
|
||||
if (!gotTheLock) {
|
||||
// Another instance is already running - exit
|
||||
this.electronApp_.quit();
|
||||
this.quit();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ export default class ElectronAppWrapper {
|
||||
});
|
||||
|
||||
this.electronApp_.on('window-all-closed', () => {
|
||||
this.electronApp_.quit();
|
||||
this.quit();
|
||||
});
|
||||
|
||||
this.electronApp_.on('activate', () => {
|
||||
|
@ -324,6 +324,15 @@ class Application extends BaseApplication {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private crashDetectionHandler() {
|
||||
if (!Setting.value('wasClosedSuccessfully')) {
|
||||
const answer = confirm(_('The application did not close properly. Would you like to start in safe mode?'));
|
||||
Setting.setValue('isSafeMode', !!answer);
|
||||
}
|
||||
|
||||
Setting.setValue('wasClosedSuccessfully', false);
|
||||
}
|
||||
|
||||
public async start(argv: string[]): Promise<any> {
|
||||
// If running inside a package, the command line, instead of being "node.exe <path> <flags>" is "joplin.exe <flags>" so
|
||||
// insert an extra argument so that they can be processed in a consistent way everywhere.
|
||||
@ -331,6 +340,8 @@ class Application extends BaseApplication {
|
||||
|
||||
argv = await super.start(argv);
|
||||
|
||||
this.crashDetectionHandler();
|
||||
|
||||
await this.applySettingsSideEffects();
|
||||
|
||||
if (Setting.value('sync.upgradeState') === Setting.SYNC_UPGRADE_STATE_MUST_DO) {
|
||||
|
@ -2,7 +2,7 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import { saveProfileConfig } from '@joplin/lib/services/profileConfig';
|
||||
import { ProfileConfig } from '@joplin/lib/services/profileConfig/types';
|
||||
import bridge from '../services/bridge';
|
||||
import restart from '../services/restart';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'switchProfile',
|
||||
@ -20,7 +20,7 @@ export const runtime = (): CommandRuntime => {
|
||||
};
|
||||
|
||||
await saveProfileConfig(`${Setting.value('rootProfileDir')}/profiles.json`, newConfig);
|
||||
bridge().restart(false);
|
||||
await restart(false);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import bridge from '../services/bridge';
|
||||
import restart from '../services/restart';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleSafeMode',
|
||||
@ -14,7 +14,7 @@ export const runtime = (): CommandRuntime => {
|
||||
enabled = enabled !== null ? enabled : !Setting.value('isSafeMode');
|
||||
Setting.setValue('isSafeMode', enabled);
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -14,6 +14,7 @@ const pathUtils = require('@joplin/lib/path-utils');
|
||||
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
|
||||
const shared = require('@joplin/lib/components/shared/config-shared.js');
|
||||
import ClipperConfigScreen from '../ClipperConfigScreen';
|
||||
import restart from '../../services/restart';
|
||||
const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');
|
||||
|
||||
const settingKeyToControl: any = {
|
||||
@ -72,12 +73,12 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
if (!confirm('This cannot be undone. Do you want to continue?')) return;
|
||||
Setting.setValue('sync.startupOperation', SyncStartupOperation.ClearLocalSyncState);
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
} else if (key === 'sync.clearLocalDataButton') {
|
||||
if (!confirm('This cannot be undone. Do you want to continue?')) return;
|
||||
Setting.setValue('sync.startupOperation', SyncStartupOperation.ClearLocalData);
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
} else if (key === 'sync.openSyncWizard') {
|
||||
this.props.dispatch({
|
||||
type: 'DIALOG_OPEN',
|
||||
@ -632,7 +633,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
private async restartApp() {
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
}
|
||||
|
||||
private async checkNeedRestart() {
|
||||
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import versionInfo from '@joplin/lib/versionInfo';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import bridge from '../services/bridge';
|
||||
import restart from '../services/restart';
|
||||
const packageInfo = require('../packageInfo.js');
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
|
||||
@ -75,7 +75,7 @@ export default class ErrorBoundary extends React.Component<Props, State> {
|
||||
const safeMode_click = async () => {
|
||||
Setting.setValue('isSafeMode', true);
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -40,6 +40,7 @@ import { showMissingMasterKeyMessage } from '@joplin/lib/services/e2ee/utils';
|
||||
import { MasterKeyEntity } from '@joplin/lib/services/e2ee/types';
|
||||
import commands from './commands/index';
|
||||
import invitationRespond from '../../services/share/invitationRespond';
|
||||
import restart from '../../services/restart';
|
||||
const { connect } = require('react-redux');
|
||||
const { PromptDialog } = require('../PromptDialog.min.js');
|
||||
const NotePropertiesDialog = require('../NotePropertiesDialog.min.js');
|
||||
@ -267,18 +268,22 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
if (this.waitForNotesSavedIID_) shim.clearInterval(this.waitForNotesSavedIID_);
|
||||
this.waitForNotesSavedIID_ = null;
|
||||
|
||||
ipcRenderer.send('asynchronous-message', 'appCloseReply', {
|
||||
canClose: !this.props.hasNotesBeingSaved,
|
||||
});
|
||||
const sendCanClose = async (canClose: boolean) => {
|
||||
if (canClose) {
|
||||
Setting.setValue('wasClosedSuccessfully', true);
|
||||
await Setting.saveAll();
|
||||
}
|
||||
ipcRenderer.send('asynchronous-message', 'appCloseReply', { canClose });
|
||||
};
|
||||
|
||||
await sendCanClose(!this.props.hasNotesBeingSaved);
|
||||
|
||||
if (this.props.hasNotesBeingSaved) {
|
||||
this.waitForNotesSavedIID_ = shim.setInterval(() => {
|
||||
if (!this.props.hasNotesBeingSaved) {
|
||||
shim.clearInterval(this.waitForNotesSavedIID_);
|
||||
this.waitForNotesSavedIID_ = null;
|
||||
ipcRenderer.send('asynchronous-message', 'appCloseReply', {
|
||||
canClose: true,
|
||||
});
|
||||
void sendCanClose(true);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
@ -557,13 +562,13 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
const onRestartAndUpgrade = async () => {
|
||||
Setting.setValue('sync.upgradeState', Setting.SYNC_UPGRADE_STATE_MUST_DO);
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
};
|
||||
|
||||
const onDisableSafeModeAndRestart = async () => {
|
||||
Setting.setValue('isSafeMode', false);
|
||||
await Setting.saveAll();
|
||||
bridge().restart();
|
||||
await restart();
|
||||
};
|
||||
|
||||
const onInvitationRespond = async (shareUserId: string, folderId: string, masterKey: MasterKeyEntity, accept: boolean) => {
|
||||
|
@ -2,7 +2,7 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { createNewProfile, saveProfileConfig } from '@joplin/lib/services/profileConfig';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import bridge from '../../../services/bridge';
|
||||
import restart from '../../../services/restart';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'addProfile',
|
||||
@ -22,7 +22,7 @@ export const runtime = (comp: any): CommandRuntime => {
|
||||
const { newConfig, newProfile } = createNewProfile(context.state.profileConfig, answer);
|
||||
newConfig.currentProfileId = newProfile.id;
|
||||
await saveProfileConfig(`${Setting.value('rootProfileDir')}/profiles.json`, newConfig);
|
||||
bridge().restart(false);
|
||||
await restart(false);
|
||||
}
|
||||
|
||||
comp.setState({ promptOptions: null });
|
||||
|
@ -5,7 +5,7 @@ import useSyncTargetUpgrade, { SyncTargetUpgradeResult } from '@joplin/lib/servi
|
||||
const { render } = require('react-dom');
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
const bridge = require('@electron/remote').require('./bridge').default;
|
||||
import restart from '../services/restart';
|
||||
|
||||
function useAppCloseHandler(upgradeResult: SyncTargetUpgradeResult) {
|
||||
useEffect(function() {
|
||||
@ -64,7 +64,7 @@ function useStyle() {
|
||||
function useRestartOnDone(upgradeResult: SyncTargetUpgradeResult) {
|
||||
useEffect(function() {
|
||||
if (upgradeResult.done && !upgradeResult.error) {
|
||||
bridge().restart();
|
||||
void restart();
|
||||
}
|
||||
}, [upgradeResult.done]);
|
||||
}
|
||||
|
10
packages/app-desktop/services/restart.ts
Normal file
10
packages/app-desktop/services/restart.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import bridge from './bridge';
|
||||
|
||||
|
||||
export default async (linuxSafeRestart: boolean = true) => {
|
||||
Setting.setValue('wasClosedSuccessfully', true);
|
||||
await Setting.saveAll();
|
||||
|
||||
bridge().restart(linuxSafeRestart);
|
||||
};
|
@ -1500,6 +1500,12 @@ class Setting extends BaseModel {
|
||||
public: false,
|
||||
},
|
||||
|
||||
wasClosedSuccessfully: {
|
||||
value: true,
|
||||
type: SettingItemType.Bool,
|
||||
public: false,
|
||||
},
|
||||
|
||||
// 'featureFlag.syncAccurateTimestamps': {
|
||||
// value: false,
|
||||
// type: SettingItemType.Bool,
|
||||
|
Loading…
Reference in New Issue
Block a user