Skip to content

Commit

Permalink
feat: add checkmarks to "Show Me" menu to indicate which example is o…
Browse files Browse the repository at this point in the history
…pen (#705)


Co-authored-by: VerteDinde <[email protected]>
  • Loading branch information
georgexu99 and VerteDinde authored Jun 17, 2021
1 parent 9fee8ac commit 1af0e91
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 15 deletions.
5 changes: 5 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export interface SetFiddleOptions {
gistId?: string;
}

export interface SetUpMenuOptions {
acceleratorsToBlock?: BlockableAccelerator[] | null;
activeTemplate?: string | null;
}

export interface SetupRequest {
fiddle?: SetFiddleOptions;
version?: string;
Expand Down
3 changes: 3 additions & 0 deletions src/ipc-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export enum IpcEvents {
GET_APP_PATHS = 'GET_APP_PATHS',
SELECT_ALL_IN_EDITOR = 'SELECT_ALL_IN_EDITOR',
BLOCK_ACCELERATORS = 'BLOCK_ACCELERATORS',
SET_SHOW_ME_TEMPLATE = 'SET_SHOW_ME_TEMPLATE',
CLICK_TITLEBAR_MAC = 'CLICK_TITLEBAR_MAC',
TASK_BISECT = 'TASK_BISECT',
TASK_TEST = 'TASK_TEST',
Expand All @@ -45,6 +46,7 @@ export const ipcMainEvents = [
IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG,
IpcEvents.SHOW_INACTIVE,
IpcEvents.CONFIRM_QUIT,
IpcEvents.SET_SHOW_ME_TEMPLATE,
IpcEvents.BLOCK_ACCELERATORS,
IpcEvents.CLICK_TITLEBAR_MAC,
IpcEvents.OUTPUT_ENTRY,
Expand Down Expand Up @@ -75,6 +77,7 @@ export const ipcRendererEvents = [
IpcEvents.BEFORE_QUIT,
IpcEvents.GET_APP_PATHS,
IpcEvents.SELECT_ALL_IN_EDITOR,
IpcEvents.SET_SHOW_ME_TEMPLATE,
IpcEvents.TASK_BISECT,
IpcEvents.TASK_TEST,
];
Expand Down
15 changes: 14 additions & 1 deletion src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,20 @@ export function setupMenuHandler() {
ipcMainManager.on(
IpcEvents.BLOCK_ACCELERATORS,
async (_, acceleratorsToBlock) => {
(await import('./menu')).setupMenu(acceleratorsToBlock);
(await import('./menu')).setupMenu({
acceleratorsToBlock,
activeTemplate: null,
});
},
);

ipcMainManager.on(
IpcEvents.SET_SHOW_ME_TEMPLATE,
async (_, activeTemplate) => {
(await import('./menu')).setupMenu({
acceleratorsToBlock: [],
activeTemplate,
});
},
);
}
Expand Down
31 changes: 25 additions & 6 deletions src/main/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import {
shell,
} from 'electron';

import { BlockableAccelerator, Templates } from '../interfaces';
import {
BlockableAccelerator,
SetUpMenuOptions,
Templates,
} from '../interfaces';
import { IpcEvents } from '../ipc-events';
import { SHOW_ME_TEMPLATES } from '../templates';
import { showOpenDialog, showSaveDialog } from './files';
Expand Down Expand Up @@ -169,27 +173,34 @@ function getTasksMenu(): MenuItemConstructorOptions {

function getShowMeMenuItem(
key: string,
activeKey: string | null,
item: string | Templates,
): MenuItemConstructorOptions {
if (typeof item === 'string') {
return {
label: key,
type: 'radio',
checked: key === activeKey,
click: () => ipcMainManager.send(IpcEvents.FS_OPEN_TEMPLATE, [key]),
};
}

return {
label: key,
submenu: Object.keys(item).map((subkey) => {
return getShowMeMenuItem(subkey, item[subkey]);
return getShowMeMenuItem(subkey, activeKey, item[subkey]);
}),
};
}

function getShowMeMenu(): MenuItemConstructorOptions {
function getShowMeMenu(
activeTemplate: string | null,
): MenuItemConstructorOptions {
const showMeMenu: Array<MenuItemConstructorOptions> = Object.keys(
SHOW_ME_TEMPLATES,
).map((key) => getShowMeMenuItem(key, SHOW_ME_TEMPLATES[key]));
).map((key) =>
getShowMeMenuItem(key, activeTemplate, SHOW_ME_TEMPLATES[key]),
);

return {
label: 'Show Me',
Expand Down Expand Up @@ -295,7 +306,10 @@ function getFileMenu(
/**
* Creates the app's window menu.
*/
export function setupMenu(acceleratorsToBlock: BlockableAccelerator[] = []) {
export function setupMenu(options?: SetUpMenuOptions) {
const acceleratorsToBlock = options?.acceleratorsToBlock || [];
const activeTemplate = options?.activeTemplate || null;

// Get template for default menu
const defaultMenu = require('electron-default-menu');
const menu = (defaultMenu(
Expand Down Expand Up @@ -383,7 +397,12 @@ export function setupMenu(acceleratorsToBlock: BlockableAccelerator[] = []) {
getFileMenu(acceleratorsToBlock),
);

menu.splice(menu.length - 1, 0, getTasksMenu(), getShowMeMenu());
menu.splice(
menu.length - 1,
0,
getTasksMenu(),
getShowMeMenu(activeTemplate),
);

Menu.setApplicationMenu(Menu.buildFromTemplate(menu));
}
6 changes: 6 additions & 0 deletions src/main/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export function createMainWindow(): Electron.BrowserWindow {
}
});

browserWindow.on('focus', () => {
if (browserWindow) {
ipcMainManager.send(IpcEvents.SET_SHOW_ME_TEMPLATE);
}
});

browserWindow.on('closed', () => {
browserWindows = browserWindows.filter((bw) => browserWindow !== bw);

Expand Down
10 changes: 8 additions & 2 deletions src/renderer/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import { autorun, reaction } from 'mobx';
import * as MonacoType from 'monaco-editor';

import { ipcRenderer } from 'electron';
import { IpcEvents } from '../ipc-events';
import { ipcRendererManager } from './ipc';
import {
EditorValues,
GenericDialogType,
PACKAGE_NAME,
SetFiddleOptions,
} from '../interfaces';
import { WEBCONTENTS_READY_FOR_IPC_SIGNAL } from '../ipc-events';
import { WEBCONTENTS_READY_FOR_IPC_SIGNAL, IpcEvents } from '../ipc-events';
import { getPackageJson, PackageJsonOptions } from '../utils/get-package';
import { FileManager } from './file-manager';
import { RemoteLoader } from './remote-loader';
Expand Down Expand Up @@ -78,6 +77,9 @@ export class App {
this.state.localPath = filePath;
this.state.templateName = templateName;

// update menu when a new Fiddle is loaded
ipcRenderer.send(IpcEvents.SET_SHOW_ME_TEMPLATE, templateName);

return true;
}

Expand Down Expand Up @@ -131,6 +133,10 @@ export class App {

ipcRenderer.send(WEBCONTENTS_READY_FOR_IPC_SIGNAL);

ipcRenderer.on(IpcEvents.SET_SHOW_ME_TEMPLATE, () => {
ipcRenderer.send(IpcEvents.SET_SHOW_ME_TEMPLATE, this.state.templateName);
});

return rendered;
}

Expand Down
3 changes: 2 additions & 1 deletion src/renderer/file-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export class FileManager {
// content in the file, remove a file that possibly exists.
if (content) {
await this.saveFile(savePath, content);
this.appState.templateName = undefined;
} else {
await this.removeFile(savePath);
}
Expand All @@ -115,7 +116,7 @@ export class FileManager {
this.appState.localPath = pathToSave;
this.appState.gistId = undefined;
}

ipcRendererManager.send(IpcEvents.SET_SHOW_ME_TEMPLATE);
this.appState.editorMosaic.isEdited = false;
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/renderer/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export class AppState {
this.toggleBisectDialog = this.toggleBisectDialog.bind(this);
this.updateElectronVersions = this.updateElectronVersions.bind(this);
this.setIsQuitting = this.setIsQuitting.bind(this);
this.setShowMeMenu = this.setShowMeMenu.bind(this);
this.addAcceleratorToBlock = this.addAcceleratorToBlock.bind(this);
this.removeAcceleratorToBlock = this.removeAcceleratorToBlock.bind(this);
this.hideChannels = this.hideChannels.bind(this);
Expand Down Expand Up @@ -623,6 +624,10 @@ export class AppState {
console.warn(error);
}

@action public async setShowMeMenu() {
ipcRendererManager.send(IpcEvents.SET_SHOW_ME_TEMPLATE, this.templateName);
}

@action public async addAcceleratorToBlock(acc: BlockableAccelerator) {
if (!this.acceleratorsToBlock.includes(acc)) {
this.acceleratorsToBlock = [...this.acceleratorsToBlock, acc];
Expand Down
31 changes: 29 additions & 2 deletions tests/main/menu-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,33 @@ describe('menu', () => {
IpcEvents.SELECT_ALL_IN_EDITOR,
);
});

describe('setup Show Me menu', () => {
it('show me menu correctly contains no check when no template is selected', () => {
overridePlatform('darwin');
setupMenu();

const result = (electron.Menu.buildFromTemplate as any).mock
.calls[0][0];
const showMeMenu = result[result.length - 2];

const showMeItemChecked = showMeMenu?.submenu[0]?.submenu[0]?.checked;
expect(showMeItemChecked).toEqual(false);
});

it('checks correct show me radio button after click', () => {
overridePlatform('darwin');
// simulate the menu rebuild after click that sends correct templateName
setupMenu({ activeTemplate: 'App' });

const result = (electron.Menu.buildFromTemplate as any).mock
.calls[0][0];
const showMeMenu = result[result.length - 2];

const showMeItemChecked = showMeMenu?.submenu[0]?.submenu[0]?.checked;
expect(showMeItemChecked).toEqual(true);
});
});
});

describe('menu groups', () => {
Expand Down Expand Up @@ -340,15 +367,15 @@ describe('menu', () => {
});

it('saves a Fiddle with blocked accelerator', () => {
setupMenu([BlockableAccelerator.save]);
setupMenu({ acceleratorsToBlock: [BlockableAccelerator.save] });
file.submenu[Idx.SAVE].click();
expect(ipcMainManager.send).toHaveBeenCalledWith<any>(
IpcEvents.FS_SAVE_FIDDLE,
);
});

it('saves as a Fiddle with blocked accelerator', () => {
setupMenu([BlockableAccelerator.saveAs]);
setupMenu({ acceleratorsToBlock: [BlockableAccelerator.saveAs] });
file.submenu[Idx.SAVE_AS].click();
expect(electron.dialog.showOpenDialogSync).toHaveBeenCalled();
});
Expand Down
7 changes: 4 additions & 3 deletions tests/renderer/file-manager-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,20 @@ describe('FileManager', () => {
await fm.saveFiddle('/fake/path');

const n = Object.keys(editorValues).length;
// ipc calls for each editor value + one for SET_SHOW_ME_TEMPLATE
const ipcCalls = n + 1;
expect(fs.outputFile).toHaveBeenCalledTimes(n);
expect(ipcRendererManager.send).toHaveBeenCalledTimes(n);
expect(ipcRendererManager.send).toHaveBeenCalledTimes(ipcCalls);
});

it('handles an error (remove)', async () => {
(fs.remove as jest.Mock).mockImplementation(() => {
throw new Error('bwap');
});

await fm.saveFiddle('/fake/path');

expect(fs.remove).toHaveBeenCalledTimes(1);
expect(ipcRendererManager.send).toHaveBeenCalledTimes(1);
expect(ipcRendererManager.send).toHaveBeenCalledTimes(2);
});

it('runs saveFiddle (normal) on IPC event', () => {
Expand Down

0 comments on commit 1af0e91

Please sign in to comment.