2020-08-07 23:03:19 +00:00
|
|
|
import {AbstractExternalModalController} from "tc-shared/ui/react-elements/external-modal/Controller";
|
|
|
|
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
|
|
|
import * as ipc from "tc-shared/ipc/BrowserIPC";
|
|
|
|
import {ChannelMessage} from "tc-shared/ipc/BrowserIPC";
|
|
|
|
import {LogCategory, logDebug, logWarn} from "tc-shared/log";
|
2020-08-09 16:58:19 +00:00
|
|
|
import {Popout2ControllerMessages, PopoutIPCMessage} from "tc-shared/ui/react-elements/external-modal/IPCMessage";
|
2020-09-28 07:37:48 +00:00
|
|
|
import {RegistryMap} from "tc-shared/events";
|
2020-08-07 23:03:19 +00:00
|
|
|
|
2020-08-10 12:41:34 +00:00
|
|
|
export class ExternalModalController extends AbstractExternalModalController {
|
2020-09-28 07:37:48 +00:00
|
|
|
private readonly uniqueModalId: string;
|
2020-08-07 23:03:19 +00:00
|
|
|
private currentWindow: Window;
|
|
|
|
private windowClosedTestInterval: number = 0;
|
|
|
|
private windowClosedTimeout: number;
|
|
|
|
|
2020-09-28 07:37:48 +00:00
|
|
|
constructor(modal: string, registries: RegistryMap, userData: any, uniqueModalId: string) {
|
|
|
|
super(modal, registries, userData);
|
|
|
|
this.uniqueModalId = uniqueModalId || modal;
|
2020-08-07 23:03:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected async spawnWindow() : Promise<boolean> {
|
|
|
|
if(this.currentWindow)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
this.currentWindow = this.trySpawnWindow0();
|
|
|
|
if(!this.currentWindow) {
|
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
spawnYesNo(tr("Would you like to open the popup?"), tra("Would you like to open popup {}?", this.modalType), callback => {
|
|
|
|
if(!callback) {
|
|
|
|
reject("user aborted");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.currentWindow = this.trySpawnWindow0();
|
|
|
|
if(window) {
|
|
|
|
reject(tr("Failed to spawn window"));
|
|
|
|
} else {
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
}).close_listener.push(() => reject(tr("user aborted")));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-09-28 07:37:48 +00:00
|
|
|
if(!this.currentWindow) {
|
2020-08-07 23:03:19 +00:00
|
|
|
return false;
|
2020-09-28 07:37:48 +00:00
|
|
|
}
|
2020-08-07 23:03:19 +00:00
|
|
|
|
|
|
|
this.currentWindow.onbeforeunload = () => {
|
|
|
|
clearInterval(this.windowClosedTestInterval);
|
|
|
|
|
|
|
|
this.windowClosedTimeout = Date.now() + 5000;
|
|
|
|
this.windowClosedTestInterval = setInterval(() => {
|
|
|
|
if(!this.currentWindow) {
|
|
|
|
clearInterval(this.windowClosedTestInterval);
|
|
|
|
this.windowClosedTestInterval = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(this.currentWindow.closed || Date.now() > this.windowClosedTimeout) {
|
|
|
|
clearInterval(this.windowClosedTestInterval);
|
|
|
|
this.windowClosedTestInterval = 0;
|
|
|
|
this.handleWindowClosed();
|
|
|
|
}
|
|
|
|
}, 100);
|
|
|
|
};
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected destroyWindow() {
|
|
|
|
clearInterval(this.windowClosedTestInterval);
|
|
|
|
this.windowClosedTestInterval = 0;
|
|
|
|
|
|
|
|
if(this.currentWindow) {
|
|
|
|
this.currentWindow.close();
|
|
|
|
this.currentWindow = undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected focusWindow() {
|
|
|
|
this.currentWindow?.focus();
|
|
|
|
}
|
|
|
|
|
|
|
|
private trySpawnWindow0() : Window | null {
|
|
|
|
const parameters = {
|
|
|
|
"loader-target": "manifest",
|
|
|
|
"chunk": "modal-external",
|
|
|
|
"modal-target": this.modalType,
|
|
|
|
"ipc-channel": this.ipcChannel.channelId,
|
|
|
|
"ipc-address": ipc.getInstance().getLocalAddress(),
|
|
|
|
"disableGlobalContextMenu": __build.mode === "debug" ? 1 : 0,
|
|
|
|
"loader-abort": __build.mode === "debug" ? 1 : 0,
|
|
|
|
};
|
|
|
|
|
2020-08-08 13:20:32 +00:00
|
|
|
const options = this.getOptions();
|
2020-08-07 23:03:19 +00:00
|
|
|
const features = {
|
|
|
|
status: "no",
|
|
|
|
location: "no",
|
|
|
|
toolbar: "no",
|
|
|
|
menubar: "no",
|
2020-08-08 13:20:32 +00:00
|
|
|
resizable: "yes",
|
|
|
|
width: options.defaultSize?.width,
|
|
|
|
height: options.defaultSize?.height
|
2020-08-07 23:03:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let baseUrl = location.origin + location.pathname + "?";
|
|
|
|
return window.open(
|
|
|
|
baseUrl + Object.keys(parameters).map(e => e + "=" + encodeURIComponent(parameters[e])).join("&"),
|
2020-09-28 07:37:48 +00:00
|
|
|
this.uniqueModalId,
|
2020-08-07 23:03:19 +00:00
|
|
|
Object.keys(features).map(e => e + "=" + features[e]).join(",")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected handleIPCMessage(remoteId: string, broadcast: boolean, message: ChannelMessage) {
|
|
|
|
if(!broadcast && this.ipcRemoteId !== remoteId) {
|
|
|
|
if(this.windowClosedTestInterval > 0) {
|
|
|
|
clearInterval(this.windowClosedTestInterval);
|
|
|
|
this.windowClosedTestInterval = 0;
|
|
|
|
|
|
|
|
logDebug(LogCategory.IPC, tr("Remote window got reconnected. Client reloaded it."));
|
|
|
|
} else {
|
|
|
|
logWarn(LogCategory.IPC, tr("Remote window got a new id. Maybe a reload?"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
super.handleIPCMessage(remoteId, broadcast, message);
|
|
|
|
}
|
2020-08-09 16:58:19 +00:00
|
|
|
|
|
|
|
protected handleTypedIPCMessage<T extends Popout2ControllerMessages>(type: T, payload: PopoutIPCMessage[T]) {
|
|
|
|
super.handleTypedIPCMessage(type, payload);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case "invoke-modal-action":
|
|
|
|
const data = payload as PopoutIPCMessage["invoke-modal-action"];
|
|
|
|
switch (data.action) {
|
|
|
|
case "close":
|
|
|
|
this.destroy();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "minimize":
|
|
|
|
window.focus();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-08-10 12:41:34 +00:00
|
|
|
}
|