Skip to content

Commit b706d45

Browse files
authored
Queue workspace switching on emain (#1440)
1 parent 7c799d7 commit b706d45

File tree

1 file changed

+85
-82
lines changed

1 file changed

+85
-82
lines changed

emain/emain-window.ts

Lines changed: 85 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,23 @@ async function getClientId() {
3636
return cachedClientId;
3737
}
3838

39-
type TabSwitchQueueEntry =
39+
type WindowActionQueueEntry =
4040
| {
41-
op: "switch";
41+
op: "switchtab";
4242
tabId: string;
4343
setInBackend: boolean;
4444
}
4545
| {
46-
op: "create";
46+
op: "createtab";
4747
pinned: boolean;
4848
}
4949
| {
50-
op: "close";
50+
op: "closetab";
5151
tabId: string;
52+
}
53+
| {
54+
op: "switchworkspace";
55+
workspaceId: string;
5256
};
5357

5458
export class WaveBrowserWindow extends BaseWindow {
@@ -59,7 +63,7 @@ export class WaveBrowserWindow extends BaseWindow {
5963
activeTabView: WaveTabView;
6064
private canClose: boolean;
6165
private deleteAllowed: boolean;
62-
private tabSwitchQueue: TabSwitchQueueEntry[];
66+
private actionQueue: WindowActionQueueEntry[];
6367

6468
constructor(waveWindow: WaveWindow, fullConfig: FullConfigType, opts: WindowOpts) {
6569
console.log("create win", waveWindow.oid);
@@ -138,7 +142,7 @@ export class WaveBrowserWindow extends BaseWindow {
138142
}
139143

140144
super(winOpts);
141-
this.tabSwitchQueue = [];
145+
this.actionQueue = [];
142146
this.waveWindowId = waveWindow.oid;
143147
this.workspaceId = waveWindow.workspaceid;
144148
this.allLoadedTabViews = new Map<string, WaveTabView>();
@@ -147,7 +151,7 @@ export class WaveBrowserWindow extends BaseWindow {
147151
clearInterval(winBoundsPoller);
148152
return;
149153
}
150-
if (this.tabSwitchQueue.length > 0) {
154+
if (this.actionQueue.length > 0) {
151155
return;
152156
}
153157
this.finalizePositioning();
@@ -279,7 +283,7 @@ export class WaveBrowserWindow extends BaseWindow {
279283
waveWindowMap.set(waveWindow.oid, this);
280284
}
281285

282-
removeAllChildViews() {
286+
private removeAllChildViews() {
283287
for (const tabView of this.allLoadedTabViews.values()) {
284288
if (!this.isDestroyed()) {
285289
this.contentView.removeChildView(tabView);
@@ -327,28 +331,15 @@ export class WaveBrowserWindow extends BaseWindow {
327331
}
328332
}
329333
}
330-
const newWs = await WindowService.SwitchWorkspace(this.waveWindowId, workspaceId);
331-
if (!newWs) {
332-
return;
333-
}
334-
console.log("switchWorkspace newWs", newWs);
335-
this.removeAllChildViews();
336-
console.log("destroyed all tabs", this.waveWindowId);
337-
this.workspaceId = workspaceId;
338-
this.allLoadedTabViews = new Map();
339-
await this.setActiveTab(newWs.activetabid, false);
334+
await this._queueActionInternal({ op: "switchworkspace", workspaceId });
340335
}
341336

342337
async setActiveTab(tabId: string, setInBackend: boolean) {
343338
console.log("setActiveTab", tabId, this.waveWindowId, this.workspaceId, setInBackend);
344-
await this.queueTabSwitch(tabId, setInBackend);
345-
}
346-
347-
async closeTab(tabId: string) {
348-
await this.queueCloseTab(tabId);
339+
await this._queueActionInternal({ op: "switchtab", tabId, setInBackend });
349340
}
350341

351-
async initializeTab(tabView: WaveTabView) {
342+
private async initializeTab(tabView: WaveTabView) {
352343
const clientId = await getClientId();
353344
await tabView.initPromise;
354345
this.contentView.addChildView(tabView);
@@ -367,7 +358,7 @@ export class WaveBrowserWindow extends BaseWindow {
367358
console.log("wave-ready init time", Date.now() - startTime + "ms");
368359
}
369360

370-
async setTabViewIntoWindow(tabView: WaveTabView, tabInitialized: boolean) {
361+
private async setTabViewIntoWindow(tabView: WaveTabView, tabInitialized: boolean) {
371362
if (this.activeTabView == tabView) {
372363
return;
373364
}
@@ -393,18 +384,18 @@ export class WaveBrowserWindow extends BaseWindow {
393384
// something is causing the new tab to lose focus so it requires manual refocusing
394385
tabView.webContents.focus();
395386
setTimeout(() => {
396-
if (this.activeTabView == tabView && !tabView.webContents.isFocused()) {
387+
if (tabView.webContents && this.activeTabView == tabView && !tabView.webContents.isFocused()) {
397388
tabView.webContents.focus();
398389
}
399390
}, 10);
400391
setTimeout(() => {
401-
if (this.activeTabView == tabView && !tabView.webContents.isFocused()) {
392+
if (tabView.webContents && this.activeTabView == tabView && !tabView.webContents.isFocused()) {
402393
tabView.webContents.focus();
403394
}
404395
}, 30);
405396
}
406397

407-
async repositionTabsSlowly(delayMs: number) {
398+
private async repositionTabsSlowly(delayMs: number) {
408399
const activeTabView = this.activeTabView;
409400
const winBounds = this.getContentBounds();
410401
if (activeTabView == null) {
@@ -433,7 +424,7 @@ export class WaveBrowserWindow extends BaseWindow {
433424
this.finalizePositioning();
434425
}
435426

436-
finalizePositioning() {
427+
private finalizePositioning() {
437428
if (this.isDestroyed()) {
438429
return;
439430
}
@@ -447,92 +438,104 @@ export class WaveBrowserWindow extends BaseWindow {
447438
}
448439
}
449440

450-
async queueTabSwitch(tabId: string, setInBackend: boolean) {
451-
await this._queueTabSwitchInternal({ op: "switch", tabId, setInBackend });
452-
}
453-
454441
async queueCreateTab(pinned = false) {
455-
await this._queueTabSwitchInternal({ op: "create", pinned });
442+
await this._queueActionInternal({ op: "createtab", pinned });
456443
}
457444

458445
async queueCloseTab(tabId: string) {
459-
await this._queueTabSwitchInternal({ op: "close", tabId });
446+
await this._queueActionInternal({ op: "closetab", tabId });
460447
}
461448

462-
async _queueTabSwitchInternal(entry: TabSwitchQueueEntry) {
463-
if (this.tabSwitchQueue.length >= 2) {
464-
this.tabSwitchQueue[1] = entry;
449+
private async _queueActionInternal(entry: WindowActionQueueEntry) {
450+
if (this.actionQueue.length >= 2) {
451+
this.actionQueue[1] = entry;
465452
return;
466453
}
467-
const wasEmpty = this.tabSwitchQueue.length === 0;
468-
this.tabSwitchQueue.push(entry);
454+
const wasEmpty = this.actionQueue.length === 0;
455+
this.actionQueue.push(entry);
469456
if (wasEmpty) {
470-
await this.processTabSwitchQueue();
457+
await this.processActionQueue();
471458
}
472459
}
473460

474-
removeTabViewLater(tabId: string, delayMs: number) {
461+
private removeTabViewLater(tabId: string, delayMs: number) {
475462
setTimeout(() => {
476463
this.removeTabView(tabId, false);
477464
}, 1000);
478465
}
479466

480-
// the queue and this function are used to serialize tab switches
481-
// [0] => the tab that is currently being switched to
482-
// [1] => the tab that will be switched to next
483-
// queueTabSwitch will replace [1] if it is already set
467+
// the queue and this function are used to serialize operations that update the window contents view
468+
// processActionQueue will replace [1] if it is already set
484469
// we don't mess with [0] because it is "in process"
485-
// we replace [1] because there is no point to switching to a tab that will be switched out of immediately
486-
async processTabSwitchQueue() {
487-
while (this.tabSwitchQueue.length > 0) {
470+
// we replace [1] because there is no point to run an action that is going to be overwritten
471+
private async processActionQueue() {
472+
while (this.actionQueue.length > 0) {
488473
try {
489-
const entry = this.tabSwitchQueue[0];
474+
const entry = this.actionQueue[0];
490475
let tabId: string = null;
491476
// have to use "===" here to get the typechecker to work :/
492-
if (entry.op === "create") {
493-
const { pinned } = entry;
494-
tabId = await WorkspaceService.CreateTab(this.workspaceId, null, true, pinned);
495-
} else if (entry.op === "switch") {
496-
let setInBackend: boolean = false;
497-
({ tabId, setInBackend } = entry);
498-
if (this.activeTabView?.waveTabId == tabId) {
499-
continue;
500-
}
501-
if (setInBackend) {
502-
await WorkspaceService.SetActiveTab(this.workspaceId, tabId);
503-
}
504-
} else if (entry.op === "close") {
505-
console.log("processTabSwitchQueue closeTab", entry.tabId);
506-
tabId = entry.tabId;
507-
const rtn = await WorkspaceService.CloseTab(this.workspaceId, tabId, true);
508-
if (rtn == null) {
509-
console.log("[error] closeTab: no return value", tabId, this.workspaceId, this.waveWindowId);
510-
return;
511-
}
512-
this.removeTabViewLater(tabId, 1000);
513-
if (rtn.closewindow) {
514-
this.close();
515-
return;
516-
}
517-
if (!rtn.newactivetabid) {
518-
return;
519-
}
520-
tabId = rtn.newactivetabid;
477+
switch (entry.op) {
478+
case "createtab":
479+
tabId = await WorkspaceService.CreateTab(this.workspaceId, null, true, entry.pinned);
480+
break;
481+
case "switchtab":
482+
tabId = entry.tabId;
483+
if (this.activeTabView?.waveTabId == tabId) {
484+
continue;
485+
}
486+
if (entry.setInBackend) {
487+
await WorkspaceService.SetActiveTab(this.workspaceId, tabId);
488+
}
489+
break;
490+
case "closetab":
491+
tabId = entry.tabId;
492+
const rtn = await WorkspaceService.CloseTab(this.workspaceId, tabId, true);
493+
if (rtn == null) {
494+
console.log(
495+
"[error] closeTab: no return value",
496+
tabId,
497+
this.workspaceId,
498+
this.waveWindowId
499+
);
500+
return;
501+
}
502+
this.removeTabViewLater(tabId, 1000);
503+
if (rtn.closewindow) {
504+
this.close();
505+
return;
506+
}
507+
if (!rtn.newactivetabid) {
508+
return;
509+
}
510+
tabId = rtn.newactivetabid;
511+
break;
512+
case "switchworkspace":
513+
const newWs = await WindowService.SwitchWorkspace(this.waveWindowId, entry.workspaceId);
514+
if (!newWs) {
515+
return;
516+
}
517+
console.log("processActionQueue switchworkspace newWs", newWs);
518+
this.removeAllChildViews();
519+
console.log("destroyed all tabs", this.waveWindowId);
520+
this.workspaceId = entry.workspaceId;
521+
this.allLoadedTabViews = new Map();
522+
tabId = newWs.activetabid;
523+
break;
521524
}
522525
if (tabId == null) {
523526
return;
524527
}
525528
const [tabView, tabInitialized] = await getOrCreateWebViewForTab(this.waveWindowId, tabId);
526529
await this.setTabViewIntoWindow(tabView, tabInitialized);
527530
} catch (e) {
528-
console.log("error caught in processTabSwitchQueue", e);
531+
console.log("error caught in processActionQueue", e);
529532
} finally {
530-
this.tabSwitchQueue.shift();
533+
this.actionQueue.shift();
531534
}
532535
}
533536
}
534537

535-
async mainResizeHandler(_: any) {
538+
private async mainResizeHandler(_: any) {
536539
if (this == null || this.isDestroyed() || this.fullScreen) {
537540
return;
538541
}

0 commit comments

Comments
 (0)