#1960 fix unexpected top menu focus (#1963)

* #1960 fix unexpected top menu focus

* #1960 test update

* #1960 improved test

* #1960 optimized algrithm to handle only Alt key to improve performance and avoid side effects

* #1960 tests update

* #1960 fixed 3 dit menu focus on workspace change with Alt+1, Alt+2

* #313 fix linter issue

* #1960 fix linter issue

* tests update
This commit is contained in:
Profesor08
2022-02-08 06:23:51 -08:00
committed by GitHub
parent 301ba8deb2
commit 1c71579bbe
3 changed files with 47 additions and 29 deletions

View File

@@ -35,6 +35,9 @@ describe('menu/menu', function desc() {
const mainWindow = this.app.windows().find((window) => window.url().includes('index')); const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
mainWindow.should.not.be.null; mainWindow.should.not.be.null;
await mainWindow.bringToFront();
await mainWindow.click('#app');
// Settings window should open if Alt works // Settings window should open if Alt works
robot.keyTap('alt'); robot.keyTap('alt');
robot.keyTap('enter'); robot.keyTap('enter');

View File

@@ -56,7 +56,8 @@ const tabView = new MessagingTabView(server);
describe('main/views/MattermostView', () => { describe('main/views/MattermostView', () => {
describe('load', () => { describe('load', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
mattermostView.loadSuccess = jest.fn(); mattermostView.loadSuccess = jest.fn();
@@ -102,7 +103,8 @@ describe('main/views/MattermostView', () => {
}); });
describe('retry', () => { describe('retry', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
mattermostView.view.webContents.loadURL.mockImplementation(() => Promise.resolve()); mattermostView.view.webContents.loadURL.mockImplementation(() => Promise.resolve());
@@ -153,7 +155,8 @@ describe('main/views/MattermostView', () => {
}); });
describe('loadSuccess', () => { describe('loadSuccess', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
jest.useFakeTimers(); jest.useFakeTimers();
@@ -173,7 +176,7 @@ describe('main/views/MattermostView', () => {
}); });
describe('show', () => { describe('show', () => {
const window = {addBrowserView: jest.fn(), removeBrowserView: jest.fn()}; const window = {addBrowserView: jest.fn(), removeBrowserView: jest.fn(), on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {}); const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
@@ -218,7 +221,7 @@ describe('main/views/MattermostView', () => {
}); });
describe('destroy', () => { describe('destroy', () => {
const window = {removeBrowserView: jest.fn()}; const window = {removeBrowserView: jest.fn(), on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {}); const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
@@ -245,10 +248,11 @@ describe('main/views/MattermostView', () => {
}); });
describe('handleInputEvents', () => { describe('handleInputEvents', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
it('should open three dot menu on pressing Alt', () => { it('should open three dot menu on pressing Alt', () => {
mattermostView.handleInputEvents(null, {key: 'Alt', type: 'keyDown'}); mattermostView.handleInputEvents(null, {key: 'Alt', type: 'keyDown', alt: true, shift: false, control: false, meta: false});
mattermostView.handleInputEvents(null, {key: 'Alt', type: 'keyUp'}); mattermostView.handleInputEvents(null, {key: 'Alt', type: 'keyUp'});
expect(WindowManager.focusThreeDotMenu).toHaveBeenCalled(); expect(WindowManager.focusThreeDotMenu).toHaveBeenCalled();
}); });
@@ -268,7 +272,8 @@ describe('main/views/MattermostView', () => {
}); });
describe('handleDidNavigate', () => { describe('handleDidNavigate', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
mattermostView.setBounds = jest.fn(); mattermostView.setBounds = jest.fn();
@@ -286,7 +291,8 @@ describe('main/views/MattermostView', () => {
}); });
describe('handleUpdateTarget', () => { describe('handleUpdateTarget', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
beforeEach(() => { beforeEach(() => {
mattermostView.emit = jest.fn(); mattermostView.emit = jest.fn();
@@ -310,7 +316,8 @@ describe('main/views/MattermostView', () => {
}); });
describe('updateMentionsFromTitle', () => { describe('updateMentionsFromTitle', () => {
const mattermostView = new MattermostView(tabView, {}, {}, {}); const window = {on: jest.fn()};
const mattermostView = new MattermostView(tabView, {}, window, {});
it('should parse mentions from title', () => { it('should parse mentions from title', () => {
mattermostView.updateMentionsFromTitle('(7) Mattermost'); mattermostView.updateMentionsFromTitle('(7) Mattermost');

View File

@@ -62,14 +62,14 @@ export class MattermostView extends EventEmitter {
currentFavicon?: string; currentFavicon?: string;
hasBeenShown: boolean; hasBeenShown: boolean;
altTimeout?: number;
altLastPressed?: boolean;
contextMenu: ContextMenu; contextMenu: ContextMenu;
status?: Status; status?: Status;
retryLoad?: NodeJS.Timeout; retryLoad?: NodeJS.Timeout;
maxRetries: number; maxRetries: number;
private altPressStatus: boolean;
constructor(tab: TabView, serverInfo: ServerInfo, win: BrowserWindow, options: BrowserViewConstructorOptions) { constructor(tab: TabView, serverInfo: ServerInfo, win: BrowserWindow, options: BrowserViewConstructorOptions) {
super(); super();
this.tab = tab; this.tab = tab;
@@ -98,7 +98,6 @@ export class MattermostView extends EventEmitter {
this.hasBeenShown = false; this.hasBeenShown = false;
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
this.altLastPressed = false;
this.view.webContents.on('before-input-event', this.handleInputEvents); this.view.webContents.on('before-input-event', this.handleInputEvents);
} }
@@ -118,6 +117,12 @@ export class MattermostView extends EventEmitter {
this.contextMenu = new ContextMenu({}, this.view); this.contextMenu = new ContextMenu({}, this.view);
this.maxRetries = MAX_SERVER_RETRIES; this.maxRetries = MAX_SERVER_RETRIES;
this.altPressStatus = false;
this.window.on('blur', () => {
this.altPressStatus = false;
});
} }
// use the same name as the server // use the same name as the server
@@ -288,24 +293,27 @@ export class MattermostView extends EventEmitter {
return this.view.webContents; return this.view.webContents;
} }
handleInputEvents = (_: Event, input: Input) => { private registerAltKeyPressed = (input: Input) => {
// Handler for pressing the Alt key to focus the 3-dot menu const isAltPressed = input.key === 'Alt' && input.alt === true && input.control === false && input.shift === false && input.meta === false;
if (input.key === 'Alt' && input.type === 'keyUp' && this.altLastPressed) {
this.altLastPressed = false; if (input.type === 'keyDown') {
clearTimeout(this.altTimeout); this.altPressStatus = isAltPressed;
WindowManager.focusThreeDotMenu();
return;
} }
// Hack to detect keyPress so that alt+<key> combinations don't default back to the 3-dot menu if (input.key !== 'Alt') {
if (input.key === 'Alt' && input.type === 'keyDown') { this.altPressStatus = false;
this.altLastPressed = true; }
this.altTimeout = setTimeout(() => { };
this.altLastPressed = false;
}, 500) as unknown as number; private isAltKeyReleased = (input: Input) => {
} else { return input.type === 'keyUp' && this.altPressStatus === true;
this.altLastPressed = false; };
clearTimeout(this.altTimeout);
handleInputEvents = (_: Event, input: Input) => {
this.registerAltKeyPressed(input);
if (this.isAltKeyReleased(input)) {
WindowManager.focusThreeDotMenu();
} }
} }