mirror of https://github.com/laurent22/joplin.git
Desktop: Resolves #12006: Add a new menu item to launch the primary instance from the secondary one
parent
587db433a8
commit
52ffd46a6a
|
@ -158,9 +158,10 @@ packages/app-desktop/commands/exportFolders.js
|
|||
packages/app-desktop/commands/exportNotes.js
|
||||
packages/app-desktop/commands/focusElement.js
|
||||
packages/app-desktop/commands/index.js
|
||||
packages/app-desktop/commands/newAppInstance.js
|
||||
packages/app-desktop/commands/openNoteInNewWindow.js
|
||||
packages/app-desktop/commands/openPrimaryAppInstance.js
|
||||
packages/app-desktop/commands/openProfileDirectory.js
|
||||
packages/app-desktop/commands/openSecondaryAppInstance.js
|
||||
packages/app-desktop/commands/replaceMisspelling.js
|
||||
packages/app-desktop/commands/restoreNoteRevision.js
|
||||
packages/app-desktop/commands/startExternalEditing.js
|
||||
|
|
|
@ -133,9 +133,10 @@ packages/app-desktop/commands/exportFolders.js
|
|||
packages/app-desktop/commands/exportNotes.js
|
||||
packages/app-desktop/commands/focusElement.js
|
||||
packages/app-desktop/commands/index.js
|
||||
packages/app-desktop/commands/newAppInstance.js
|
||||
packages/app-desktop/commands/openNoteInNewWindow.js
|
||||
packages/app-desktop/commands/openPrimaryAppInstance.js
|
||||
packages/app-desktop/commands/openProfileDirectory.js
|
||||
packages/app-desktop/commands/openSecondaryAppInstance.js
|
||||
packages/app-desktop/commands/replaceMisspelling.js
|
||||
packages/app-desktop/commands/restoreNoteRevision.js
|
||||
packages/app-desktop/commands/startExternalEditing.js
|
||||
|
|
|
@ -655,7 +655,7 @@ export default class ElectronAppWrapper {
|
|||
// might still be there for a short while.
|
||||
await msleep(1000);
|
||||
this.ipcLogger_.warn('restartAltInstance: App is gone - restarting it');
|
||||
void bridge().launchNewAppInstance(this.env());
|
||||
void bridge().launchAltAppInstance(this.env());
|
||||
} else {
|
||||
this.ipcLogger_.warn('restartAltInstance: Could not restart calling app because it was still open');
|
||||
}
|
||||
|
|
|
@ -523,12 +523,18 @@ export class Bridge {
|
|||
}
|
||||
}
|
||||
|
||||
public async launchNewAppInstance(env: string) {
|
||||
public async launchAltAppInstance(env: string) {
|
||||
const cmd = this.appLaunchCommand(env, 'alt1');
|
||||
|
||||
await execCommand([cmd.execPath].concat(cmd.args), { detached: true });
|
||||
}
|
||||
|
||||
public async launchMainAppInstance(env: string) {
|
||||
const cmd = this.appLaunchCommand(env, '');
|
||||
|
||||
await execCommand([cmd.execPath].concat(cmd.args), { detached: true });
|
||||
}
|
||||
|
||||
public async restart() {
|
||||
// Note that in this case we are not sending the "appClose" event
|
||||
// to notify services and component that the app is about to close
|
||||
|
|
|
@ -6,7 +6,8 @@ import * as exportDeletionLog from './exportDeletionLog';
|
|||
import * as exportFolders from './exportFolders';
|
||||
import * as exportNotes from './exportNotes';
|
||||
import * as focusElement from './focusElement';
|
||||
import * as newAppInstance from './newAppInstance';
|
||||
import * as openSecondaryAppInstance from './openSecondaryAppInstance';
|
||||
import * as openPrimaryAppInstance from './openPrimaryAppInstance';
|
||||
import * as openNoteInNewWindow from './openNoteInNewWindow';
|
||||
import * as openProfileDirectory from './openProfileDirectory';
|
||||
import * as replaceMisspelling from './replaceMisspelling';
|
||||
|
@ -29,7 +30,8 @@ const index: any[] = [
|
|||
exportFolders,
|
||||
exportNotes,
|
||||
focusElement,
|
||||
newAppInstance,
|
||||
openSecondaryAppInstance,
|
||||
openPrimaryAppInstance,
|
||||
openNoteInNewWindow,
|
||||
openProfileDirectory,
|
||||
replaceMisspelling,
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import bridge from '../services/bridge';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'openPrimaryAppInstance',
|
||||
label: () => _('Open primary app instance...'),
|
||||
};
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context: CommandContext) => {
|
||||
await bridge().launchMainAppInstance(Setting.value('env'));
|
||||
},
|
||||
|
||||
enabledCondition: 'isAltInstance',
|
||||
};
|
||||
};
|
|
@ -4,14 +4,14 @@ import bridge from '../services/bridge';
|
|||
import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'newAppInstance',
|
||||
label: () => _('New application instance...'),
|
||||
name: 'openSecondaryAppInstance',
|
||||
label: () => _('Open secondary app instance...'),
|
||||
};
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context: CommandContext) => {
|
||||
await bridge().launchNewAppInstance(Setting.value('env'));
|
||||
await bridge().launchAltAppInstance(Setting.value('env'));
|
||||
},
|
||||
|
||||
enabledCondition: '!isAltInstance',
|
|
@ -555,7 +555,8 @@ function useMenu(props: Props) {
|
|||
const newFolderItem = menuItemDic.newFolder;
|
||||
const newSubFolderItem = menuItemDic.newSubFolder;
|
||||
const printItem = menuItemDic.print;
|
||||
const newAppInstance = menuItemDic.newAppInstance;
|
||||
const openSecondaryAppInstance = menuItemDic.openSecondaryAppInstance;
|
||||
const openPrimaryAppInstance = menuItemDic.openPrimaryAppInstance;
|
||||
const switchProfileItem = {
|
||||
label: _('Switch profile'),
|
||||
submenu: switchProfileMenuItems,
|
||||
|
@ -723,7 +724,8 @@ function useMenu(props: Props) {
|
|||
type: 'separator',
|
||||
},
|
||||
switchProfileItem,
|
||||
newAppInstance,
|
||||
openSecondaryAppInstance,
|
||||
openPrimaryAppInstance,
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,8 @@ export default function() {
|
|||
'toggleTabMovesFocus',
|
||||
'editor.deleteLine',
|
||||
'editor.duplicateLine',
|
||||
'newAppInstance',
|
||||
'openSecondaryAppInstance',
|
||||
'openPrimaryAppInstance',
|
||||
// We cannot put the undo/redo commands in the menu because they are
|
||||
// editor-specific commands. If we put them there it will break the
|
||||
// undo/redo in regular text fields.
|
||||
|
|
|
@ -14,13 +14,17 @@ interface ExecCommandOptions {
|
|||
}
|
||||
|
||||
export default async (command: string | string[], options: ExecCommandOptions | null = null): Promise<string> => {
|
||||
const detached = options ? options.detached : false;
|
||||
|
||||
// When launching a detached executable it's better not to pipe the stdout and stderr, as this
|
||||
// will most likely cause an EPIPE error.
|
||||
|
||||
options = {
|
||||
showInput: true,
|
||||
showStdout: true,
|
||||
showStderr: true,
|
||||
showInput: !detached,
|
||||
showStdout: !detached,
|
||||
showStderr: !detached,
|
||||
quiet: false,
|
||||
env: {},
|
||||
detached: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ Each instance is completely isolated, operating as a standalone version of Jopli
|
|||
|
||||
Currently, Joplin supports up to **two running instances**:
|
||||
|
||||
1. **Main Instance**: The primary application instance, with full access to all Joplin features.
|
||||
1. **Primary Instance**: The primary application instance, with full access to all Joplin features.
|
||||
|
||||
2. **Alternative Instance**: A secondary application instance that functions independently. However, it does not support the **Web Clipper service**, which can only run in the main instance.
|
||||
2. **Secondary Instance**: A secondary application instance that functions independently. However, it does not support the **Web Clipper service**, which can only run in the main instance.
|
||||
|
||||
## How to Launch a Second Instance
|
||||
|
||||
|
@ -29,8 +29,20 @@ To start a second instance of Joplin:
|
|||
|
||||
2. Navigate to the menu and select:
|
||||
|
||||
**File** => **New application instance...**
|
||||
**File** => **Open secondary app instance...**
|
||||
|
||||
3. A new instance of Joplin will open with its own profile.
|
||||
|
||||
This second instance operates independently, allowing you to customise it as needed.
|
||||
|
||||
## Caveats
|
||||
|
||||
### Launching the primary instance when the secondary instance is active
|
||||
|
||||
Technically, the secondary instance is still initiated from the same executable file, which might confuse the operating system. Most operating systems reasonably assume that if you attempt to launch a GUI application that is already running, your intention is to bring that application into focus.
|
||||
|
||||
In practical terms, this means the following:
|
||||
|
||||
If you close the primary instance while the secondary instance remains open, and then attempt to reopen the primary instance—for instance, by clicking on its icon—the operating system will most likely refocus on the secondary instance instead of launching the primary one. To address this issue, the secondary instance includes a menu item labelled **Open primary app instance...**. Clicking on this option will explicitly launch the primary instance.
|
||||
|
||||
In the same way, the secondary instance should generally be launched only from the first one, using the **Open secondary app instance...** menu item.
|
||||
|
|
Loading…
Reference in New Issue