Added the possibility to connect within an already running TeaWeb instance
This commit is contained in:
parent
9326572342
commit
27e3967ffa
4 changed files with 550 additions and 234 deletions
|
@ -1,4 +1,7 @@
|
||||||
# Changelog:
|
# Changelog:
|
||||||
|
* **06.10.19**
|
||||||
|
- Added the possibility to connect within an already running TeaWeb instance
|
||||||
|
|
||||||
* **30.10.19**
|
* **30.10.19**
|
||||||
- Removed old `files.php` script and replaced it with a more modern `file.ts` script to generate the environment
|
- Removed old `files.php` script and replaced it with a more modern `file.ts` script to generate the environment
|
||||||
- Some small UI fixed
|
- Some small UI fixed
|
||||||
|
|
|
@ -28,8 +28,8 @@ namespace bipc {
|
||||||
|
|
||||||
export interface ChannelMessage {
|
export interface ChannelMessage {
|
||||||
channel_id: string;
|
channel_id: string;
|
||||||
key: string;
|
type: string;
|
||||||
message: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProcessQueryResponse {
|
export interface ProcessQueryResponse {
|
||||||
|
@ -63,7 +63,7 @@ namespace bipc {
|
||||||
abstract send_message(type: string, data: any, target?: string);
|
abstract send_message(type: string, data: any, target?: string);
|
||||||
|
|
||||||
protected handle_message(message: BroadcastMessage) {
|
protected handle_message(message: BroadcastMessage) {
|
||||||
log.trace(LogCategory.IPC, tr("Received message %o"), message);
|
//log.trace(LogCategory.IPC, tr("Received message %o"), message);
|
||||||
|
|
||||||
if(message.receiver === BasicIPCHandler.BROADCAST_UNIQUE_ID) {
|
if(message.receiver === BasicIPCHandler.BROADCAST_UNIQUE_ID) {
|
||||||
if(message.type == "process-query") {
|
if(message.type == "process-query") {
|
||||||
|
@ -86,7 +86,8 @@ namespace bipc {
|
||||||
log.warn(LogCategory.IPC, tr("Received a query response for an unknown request."));
|
log.warn(LogCategory.IPC, tr("Received a query response for an unknown request."));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if(message.type == "certificate-accept-callback") {
|
}
|
||||||
|
else if(message.type == "certificate-accept-callback") {
|
||||||
const data: CertificateAcceptCallback = message.data;
|
const data: CertificateAcceptCallback = message.data;
|
||||||
if(!this._cert_accept_callbacks[data.request_id]) {
|
if(!this._cert_accept_callbacks[data.request_id]) {
|
||||||
log.warn(LogCategory.IPC, tr("Received certificate accept callback for an unknown request ID."));
|
log.warn(LogCategory.IPC, tr("Received certificate accept callback for an unknown request ID."));
|
||||||
|
@ -99,21 +100,24 @@ namespace bipc {
|
||||||
|
|
||||||
} as CertificateAcceptSucceeded, message.sender);
|
} as CertificateAcceptSucceeded, message.sender);
|
||||||
return;
|
return;
|
||||||
} else if(message.type == "certificate-accept-succeeded") {
|
}
|
||||||
|
else if(message.type == "certificate-accept-succeeded") {
|
||||||
if(!this._cert_accept_succeeded[message.sender]) {
|
if(!this._cert_accept_succeeded[message.sender]) {
|
||||||
log.warn(LogCategory.IPC, tr("Received certificate accept succeeded, but haven't a callback."));
|
log.warn(LogCategory.IPC, tr("Received certificate accept succeeded, but haven't a callback."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._cert_accept_succeeded[message.sender]();
|
this._cert_accept_succeeded[message.sender]();
|
||||||
return;
|
return;
|
||||||
} else if(message.type === "channel") {
|
}
|
||||||
|
}
|
||||||
|
if(message.type === "channel") {
|
||||||
const data: ChannelMessage = message.data;
|
const data: ChannelMessage = message.data;
|
||||||
|
|
||||||
let channel_invoked = false;
|
let channel_invoked = false;
|
||||||
for(const channel of this._channels)
|
for(const channel of this._channels)
|
||||||
if(channel.channel_id === data.channel_id && (typeof(channel.target_id) === "undefined" || channel.target_id === message.sender)) {
|
if(channel.channel_id === data.channel_id && (typeof(channel.target_id) === "undefined" || channel.target_id === message.sender)) {
|
||||||
if(channel.message_handler)
|
if(channel.message_handler)
|
||||||
channel.message_handler(message.sender, data);
|
channel.message_handler(message.sender, message.receiver === BasicIPCHandler.BROADCAST_UNIQUE_ID, data);
|
||||||
channel_invoked = true;
|
channel_invoked = true;
|
||||||
}
|
}
|
||||||
if(!channel_invoked) {
|
if(!channel_invoked) {
|
||||||
|
@ -121,22 +125,23 @@ namespace bipc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
create_channel(target_id?: string, channel_id?: string) {
|
create_channel(target_id?: string, channel_id?: string) {
|
||||||
let channel: Channel = {
|
let channel: Channel = {
|
||||||
target_id: target_id,
|
target_id: target_id,
|
||||||
channel_id: channel_id || uuidv4(),
|
channel_id: channel_id || uuidv4(),
|
||||||
message_handler: undefined,
|
message_handler: undefined,
|
||||||
send_message: (key: string, message: any) => {
|
send_message: (type: string, data: any, target?: string) => {
|
||||||
if(!channel.target_id)
|
if(typeof target !== "undefined") {
|
||||||
throw "channel has no target!";
|
if(typeof channel.target_id === "string" && target != channel.target_id)
|
||||||
|
throw "target id does not match channel target";
|
||||||
|
}
|
||||||
|
|
||||||
this.send_message("channel", {
|
this.send_message("channel", {
|
||||||
key: key,
|
type: type,
|
||||||
message: message,
|
data: data,
|
||||||
channel_id: channel.channel_id
|
channel_id: channel.channel_id
|
||||||
} as ChannelMessage, channel.target_id)
|
} as ChannelMessage, target || channel.target_id || BasicIPCHandler.BROADCAST_UNIQUE_ID);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,8 +203,8 @@ namespace bipc {
|
||||||
readonly channel_id: string;
|
readonly channel_id: string;
|
||||||
target_id?: string;
|
target_id?: string;
|
||||||
|
|
||||||
message_handler: (remote_id: string, message: ChannelMessage) => any;
|
message_handler: (remote_id: string, broadcast: boolean, message: ChannelMessage) => any;
|
||||||
send_message(key: string, message: any);
|
send_message(type: string, message: any, target?: string);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BroadcastChannelIPC extends BasicIPCHandler {
|
class BroadcastChannelIPC extends BasicIPCHandler {
|
||||||
|
@ -252,6 +257,224 @@ namespace bipc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace connect {
|
||||||
|
export interface ConnectOffer {
|
||||||
|
request_id: string;
|
||||||
|
data: ConnectRequestData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConnectOfferAnswer {
|
||||||
|
request_id: string;
|
||||||
|
accepted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConnectExecute {
|
||||||
|
request_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConnectExecuted {
|
||||||
|
request_id: string;
|
||||||
|
succeeded: boolean;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The connect process:
|
||||||
|
* 1. Broadcast an offer
|
||||||
|
* 2. Wait 50ms for all offer responses or until the first one respond with "ok"
|
||||||
|
* 3. Select (if possible) on accepted offer and execute the connect
|
||||||
|
*/
|
||||||
|
export class ConnectHandler {
|
||||||
|
private static readonly CHANNEL_NAME = "connect";
|
||||||
|
|
||||||
|
readonly ipc_handler: BasicIPCHandler;
|
||||||
|
private ipc_channel: Channel;
|
||||||
|
|
||||||
|
public callback_available: (data: ConnectRequestData) => boolean = () => false;
|
||||||
|
public callback_execute: (data: ConnectRequestData) => boolean | string = () => false;
|
||||||
|
|
||||||
|
|
||||||
|
private _pending_connect_offers: {
|
||||||
|
id: string;
|
||||||
|
data: ConnectRequestData;
|
||||||
|
timeout: number;
|
||||||
|
|
||||||
|
remote_handler: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
private _pending_connects_requests: {
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
data: ConnectRequestData;
|
||||||
|
timeout: number;
|
||||||
|
|
||||||
|
callback_success: () => any;
|
||||||
|
callback_failed: (message: string) => any;
|
||||||
|
callback_avail: () => Promise<boolean>;
|
||||||
|
|
||||||
|
remote_handler?: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
constructor(ipc_handler: BasicIPCHandler) {
|
||||||
|
this.ipc_handler = ipc_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setup() {
|
||||||
|
this.ipc_channel = this.ipc_handler.create_channel(undefined, ConnectHandler.CHANNEL_NAME);
|
||||||
|
this.ipc_channel.message_handler = this.on_message.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private on_message(sender: string, broadcast: boolean, message: ChannelMessage) {
|
||||||
|
if(broadcast) {
|
||||||
|
if(message.type == "offer") {
|
||||||
|
const data = message.data as ConnectOffer;
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
accepted: this.callback_available(data.data),
|
||||||
|
request_id: data.request_id
|
||||||
|
} as ConnectOfferAnswer;
|
||||||
|
|
||||||
|
if(response.accepted) {
|
||||||
|
log.debug(LogCategory.IPC, tr("Received new connect offer from %s: %s"), sender, data.request_id);
|
||||||
|
|
||||||
|
const ld = {
|
||||||
|
remote_handler: sender,
|
||||||
|
data: data.data,
|
||||||
|
id: data.request_id,
|
||||||
|
timeout: 0
|
||||||
|
};
|
||||||
|
this._pending_connect_offers.push(ld);
|
||||||
|
ld.timeout = setTimeout(() => {
|
||||||
|
log.debug(LogCategory.IPC, tr("Dropping connect request %s, because we never received an execute."), ld.id);
|
||||||
|
this._pending_connect_offers.remove(ld);
|
||||||
|
}, 120 * 1000) as any;
|
||||||
|
}
|
||||||
|
this.ipc_channel.send_message("offer-answer", response, sender);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(message.type == "offer-answer") {
|
||||||
|
const data = message.data as ConnectOfferAnswer;
|
||||||
|
const request = this._pending_connects_requests.find(e => e.id === data.request_id);
|
||||||
|
if(!request) {
|
||||||
|
log.warn(LogCategory.IPC, tr("Received connect offer answer with unknown request id (%s)."), data.request_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!data.accepted) {
|
||||||
|
log.debug(LogCategory.IPC, tr("Client %s rejected the connect offer (%s)."), sender, request.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(request.remote_handler) {
|
||||||
|
log.debug(LogCategory.IPC, tr("Client %s accepted the connect offer (%s), but offer has already been accepted."), sender, request.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(LogCategory.IPC, tr("Client %s accepted the connect offer (%s). Request local acceptance."), sender, request.id);
|
||||||
|
request.remote_handler = sender;
|
||||||
|
clearTimeout(request.timeout);
|
||||||
|
|
||||||
|
request.callback_avail().then(flag => {
|
||||||
|
if(!flag) {
|
||||||
|
request.callback_failed("local avail rejected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(LogCategory.IPC, tr("Executing connect with client %s"), request.remote_handler);
|
||||||
|
this.ipc_channel.send_message("execute", {
|
||||||
|
request_id: request.id
|
||||||
|
} as ConnectExecute, request.remote_handler);
|
||||||
|
request.timeout = setTimeout(() => {
|
||||||
|
request.callback_failed("connect execute timeout");
|
||||||
|
}, 1000) as any;
|
||||||
|
}).catch(error => {
|
||||||
|
log.error(LogCategory.IPC, tr("Local avail callback caused an error: %o"), error);
|
||||||
|
request.callback_failed(tr("local avail callback caused an error"));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(message.type == "executed") {
|
||||||
|
const data = message.data as ConnectExecuted;
|
||||||
|
const request = this._pending_connects_requests.find(e => e.id === data.request_id);
|
||||||
|
if(!request) {
|
||||||
|
log.warn(LogCategory.IPC, tr("Received connect executed with unknown request id (%s)."), data.request_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request.remote_handler != sender) {
|
||||||
|
log.warn(LogCategory.IPC, tr("Received connect executed for request %s, but from wrong client: %s (expected %s)"), data.request_id, sender, request.remote_handler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(LogCategory.IPC, tr("Received connect executed response from client %s for request %s. Succeeded: %o (%s)"), sender, data.request_id, data.succeeded, data.message);
|
||||||
|
clearTimeout(request.timeout);
|
||||||
|
if(data.succeeded)
|
||||||
|
request.callback_success();
|
||||||
|
else
|
||||||
|
request.callback_failed(data.message);
|
||||||
|
}
|
||||||
|
else if(message.type == "execute") {
|
||||||
|
const data = message.data as ConnectExecute;
|
||||||
|
const request = this._pending_connect_offers.find(e => e.id === data.request_id);
|
||||||
|
if(!request) {
|
||||||
|
log.warn(LogCategory.IPC, tr("Received connect execute with unknown request id (%s)."), data.request_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request.remote_handler != sender) {
|
||||||
|
log.warn(LogCategory.IPC, tr("Received connect execute for request %s, but from wrong client: %s (expected %s)"), data.request_id, sender, request.remote_handler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(request.timeout);
|
||||||
|
this._pending_connect_offers.remove(request);
|
||||||
|
|
||||||
|
log.debug(LogCategory.IPC, tr("Executing connect for %s"), data.request_id);
|
||||||
|
const cr = this.callback_execute(request.data);
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
request_id: data.request_id,
|
||||||
|
|
||||||
|
succeeded: typeof(cr) !== "string" && cr,
|
||||||
|
message: typeof(cr) === "string" ? cr : "",
|
||||||
|
} as ConnectExecuted;
|
||||||
|
this.ipc_channel.send_message("executed", response, request.remote_handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post_connect_request(data: ConnectRequestData, callback_avail: () => Promise<boolean>) : Promise<void> {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
const pd = {
|
||||||
|
data: data,
|
||||||
|
id: uuidv4(),
|
||||||
|
timeout: 0,
|
||||||
|
|
||||||
|
callback_success: () => {
|
||||||
|
this._pending_connects_requests.remove(pd);
|
||||||
|
clearTimeout(pd.timeout);
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
|
||||||
|
callback_failed: error => {
|
||||||
|
this._pending_connects_requests.remove(pd);
|
||||||
|
clearTimeout(pd.timeout);
|
||||||
|
reject(error);
|
||||||
|
},
|
||||||
|
|
||||||
|
callback_avail: callback_avail,
|
||||||
|
};
|
||||||
|
this._pending_connects_requests.push(pd);
|
||||||
|
|
||||||
|
this.ipc_channel.send_message("offer", {
|
||||||
|
request_id: pd.id,
|
||||||
|
data: pd.data
|
||||||
|
} as ConnectOffer);
|
||||||
|
pd.timeout = setTimeout(() => {
|
||||||
|
pd.callback_failed("received no response to offer");
|
||||||
|
}, 50) as any;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace mproxy {
|
||||||
export interface MethodProxyInvokeData {
|
export interface MethodProxyInvokeData {
|
||||||
method_name: string;
|
method_name: string;
|
||||||
arguments: any[];
|
arguments: any[];
|
||||||
|
@ -364,15 +587,15 @@ namespace bipc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handle_message(remote_id: string, message: ChannelMessage) {
|
private _handle_message(remote_id: string, boradcast: boolean, message: ChannelMessage) {
|
||||||
if(message.key === "finalize") {
|
if(message.type === "finalize") {
|
||||||
this._handle_finalize();
|
this._handle_finalize();
|
||||||
} else if(message.key === "initialize") {
|
} else if(message.type === "initialize") {
|
||||||
this._handle_remote_callback(remote_id);
|
this._handle_remote_callback(remote_id);
|
||||||
} else if(message.key === "invoke") {
|
} else if(message.type === "invoke") {
|
||||||
this._handle_invoke(message.message);
|
this._handle_invoke(message.data);
|
||||||
} else if(message.key === "result") {
|
} else if(message.type === "result") {
|
||||||
this._handle_result(message.message);
|
this._handle_result(message.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,20 +687,30 @@ namespace bipc {
|
||||||
protected abstract on_connected();
|
protected abstract on_connected();
|
||||||
protected abstract on_disconnected();
|
protected abstract on_disconnected();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let handler: BasicIPCHandler;
|
let handler: BasicIPCHandler;
|
||||||
|
let connect_handler: connect.ConnectHandler;
|
||||||
|
|
||||||
export function setup() {
|
export function setup() {
|
||||||
if(!supported())
|
if(!supported())
|
||||||
return;
|
return;
|
||||||
/* TODO: test for support */
|
|
||||||
handler = new BroadcastChannelIPC();
|
handler = new BroadcastChannelIPC();
|
||||||
handler.setup();
|
handler.setup();
|
||||||
|
|
||||||
|
connect_handler = new connect.ConnectHandler(handler);
|
||||||
|
connect_handler.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_handler() {
|
export function get_handler() {
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function get_connect_handler() {
|
||||||
|
return connect_handler;
|
||||||
|
}
|
||||||
|
|
||||||
export function supported() {
|
export function supported() {
|
||||||
/* ios does not support this */
|
/* ios does not support this */
|
||||||
return typeof(window.BroadcastChannel) !== "undefined";
|
return typeof(window.BroadcastChannel) !== "undefined";
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
/// <reference path="log.ts" />
|
/// <reference path="log.ts" />
|
||||||
/// <reference path="PPTListener.ts" />
|
/// <reference path="PPTListener.ts" />
|
||||||
|
|
||||||
|
import spawnYesNo = Modals.spawnYesNo;
|
||||||
|
|
||||||
const js_render = window.jsrender || $;
|
const js_render = window.jsrender || $;
|
||||||
const native_client = window.require !== undefined;
|
const native_client = window.require !== undefined;
|
||||||
|
|
||||||
|
@ -288,35 +290,42 @@ interface Window {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function execute_default_connect() {
|
type ConnectRequestData = {
|
||||||
if(settings.static(Settings.KEY_FLAG_CONNECT_DEFAULT, false) && settings.static(Settings.KEY_CONNECT_ADDRESS, "")) {
|
address: string;
|
||||||
const profile_uuid = settings.static(Settings.KEY_CONNECT_PROFILE, (profiles.default_profile() || {id: 'default'}).id);
|
|
||||||
const profile = profiles.find_profile(profile_uuid) || profiles.default_profile();
|
|
||||||
const address = settings.static(Settings.KEY_CONNECT_ADDRESS, "");
|
|
||||||
const username = settings.static(Settings.KEY_CONNECT_USERNAME, "Another TeaSpeak user");
|
|
||||||
|
|
||||||
const password = settings.static(Settings.KEY_CONNECT_PASSWORD, "");
|
profile?: string;
|
||||||
const password_hashed = settings.static(Settings.KEY_FLAG_CONNECT_PASSWORD, false);
|
username?: string;
|
||||||
|
password?: {
|
||||||
|
value: string;
|
||||||
|
hashed: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function handle_connect_request(properties: ConnectRequestData, connection: ConnectionHandler) {
|
||||||
|
const profile_uuid = properties.profile || (profiles.default_profile() || {id: 'default'}).id;
|
||||||
|
const profile = profiles.find_profile(profile_uuid) || profiles.default_profile();
|
||||||
|
const username = properties.username || profile.connect_username();
|
||||||
|
|
||||||
|
const password = properties.password ? properties.password.value : "";
|
||||||
|
const password_hashed = properties.password ? properties.password.hashed : false;
|
||||||
|
|
||||||
if(profile && profile.valid()) {
|
if(profile && profile.valid()) {
|
||||||
const connection = server_connections.active_connection_handler() || server_connections.spawn_server_connection_handler();
|
connection.startConnection(properties.address, profile, true, {
|
||||||
connection.startConnection(address, profile, true, {
|
|
||||||
nickname: username,
|
nickname: username,
|
||||||
password: password.length > 0 ? {
|
password: password.length > 0 ? {
|
||||||
password: password,
|
password: password,
|
||||||
hashed: password_hashed
|
hashed: password_hashed
|
||||||
} : undefined
|
} : undefined
|
||||||
});
|
});
|
||||||
|
server_connections.set_active_connection_handler(connection);
|
||||||
} else {
|
} else {
|
||||||
Modals.spawnConnectModal({},{
|
Modals.spawnConnectModal({},{
|
||||||
url: address,
|
url: properties.address,
|
||||||
enforce: true
|
enforce: true
|
||||||
}, {
|
}, {
|
||||||
profile: profile,
|
profile: profile,
|
||||||
enforce: true
|
enforce: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
@ -416,7 +425,6 @@ function main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* schedule it a bit later then the main because the main function is still within the loader */
|
/* schedule it a bit later then the main because the main function is still within the loader */
|
||||||
setTimeout(execute_default_connect, 5);
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const connection = server_connections.active_connection_handler();
|
const connection = server_connections.active_connection_handler();
|
||||||
/*
|
/*
|
||||||
|
@ -499,6 +507,74 @@ const task_teaweb_starter: loader.Task = {
|
||||||
priority: 10
|
priority: 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const task_connect_handler: loader.Task = {
|
||||||
|
name: "Connect handler",
|
||||||
|
function: async () => {
|
||||||
|
const address = settings.static(Settings.KEY_CONNECT_ADDRESS, "");
|
||||||
|
const chandler = bipc.get_connect_handler();
|
||||||
|
if(settings.static(Settings.KEY_FLAG_CONNECT_DEFAULT, false) && address) {
|
||||||
|
const connect_data = {
|
||||||
|
address: address,
|
||||||
|
|
||||||
|
profile: settings.static(Settings.KEY_CONNECT_PROFILE, ""),
|
||||||
|
username: settings.static(Settings.KEY_CONNECT_USERNAME, ""),
|
||||||
|
|
||||||
|
password: {
|
||||||
|
value: settings.static(Settings.KEY_CONNECT_PASSWORD, ""),
|
||||||
|
hashed: settings.static(Settings.KEY_FLAG_CONNECT_PASSWORD, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(chandler) {
|
||||||
|
try {
|
||||||
|
await chandler.post_connect_request(connect_data, () => new Promise<boolean>((resolve, reject) => {
|
||||||
|
spawnYesNo(tr("Another TeaWeb instance is already running"), tra("Another TeaWeb instance is already running.{:br:}Would you like to connect there?"), response => {
|
||||||
|
resolve(response);
|
||||||
|
}, {
|
||||||
|
closeable: false
|
||||||
|
}).open();
|
||||||
|
}));
|
||||||
|
log.info(LogCategory.CLIENT, tr("Executed connect successfully in another browser window. Closing this window"));
|
||||||
|
|
||||||
|
const message =
|
||||||
|
"You're connecting to {0} within the other TeaWeb instance.{:br:}" +
|
||||||
|
"You could now close this page.";
|
||||||
|
createInfoModal(
|
||||||
|
tr("Connecting successfully within other instance"),
|
||||||
|
MessageHelper.formatMessage(tr(message), connect_data.address),
|
||||||
|
{
|
||||||
|
closeable: false,
|
||||||
|
footer: undefined
|
||||||
|
}
|
||||||
|
).open();
|
||||||
|
return;
|
||||||
|
} catch(error) {
|
||||||
|
log.info(LogCategory.CLIENT, tr("Failed to execute connect within other TeaWeb instance. Using this one. Error: %o"), error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.register_task(loader.Stage.LOADED, {
|
||||||
|
priority: 0,
|
||||||
|
function: async () => handle_connect_request(connect_data, server_connections.active_connection_handler() || server_connections.spawn_server_connection_handler()),
|
||||||
|
name: tr("default url connect")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(chandler) {
|
||||||
|
/* no instance avail, so lets make us avail */
|
||||||
|
chandler.callback_available = data => {
|
||||||
|
return !settings.static_global(Settings.KEY_DISABLE_MULTI_SESSION);
|
||||||
|
};
|
||||||
|
|
||||||
|
chandler.callback_execute = data => {
|
||||||
|
handle_connect_request(data, server_connections.spawn_server_connection_handler());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loader.register_task(loader.Stage.LOADED, task_teaweb_starter);
|
||||||
|
},
|
||||||
|
priority: 10
|
||||||
|
};
|
||||||
|
|
||||||
const task_certificate_callback: loader.Task = {
|
const task_certificate_callback: loader.Task = {
|
||||||
name: "certificate accept tester",
|
name: "certificate accept tester",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
|
@ -546,7 +622,7 @@ const task_certificate_callback: loader.Task = {
|
||||||
log.info(LogCategory.IPC, tr("We're not used to accept certificated. Booting app."));
|
log.info(LogCategory.IPC, tr("We're not used to accept certificated. Booting app."));
|
||||||
}
|
}
|
||||||
|
|
||||||
loader.register_task(loader.Stage.LOADED, task_teaweb_starter);
|
loader.register_task(loader.Stage.LOADED, task_connect_handler);
|
||||||
},
|
},
|
||||||
priority: 10
|
priority: 10
|
||||||
};
|
};
|
||||||
|
@ -574,8 +650,9 @@ loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
|
||||||
if(app.is_web()) {
|
if(app.is_web()) {
|
||||||
loader.register_task(loader.Stage.LOADED, task_certificate_callback);
|
loader.register_task(loader.Stage.LOADED, task_certificate_callback);
|
||||||
} else
|
} else {
|
||||||
loader.register_task(loader.Stage.LOADED, task_teaweb_starter);
|
loader.register_task(loader.Stage.LOADED, task_teaweb_starter);
|
||||||
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if(ex instanceof Error || typeof(ex.stack) !== "undefined")
|
if(ex instanceof Error || typeof(ex.stack) !== "undefined")
|
||||||
console.error((tr || (msg => msg))("Critical error stack trace: %o"), ex.stack);
|
console.error((tr || (msg => msg))("Critical error stack trace: %o"), ex.stack);
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
namespace Modals {
|
namespace Modals {
|
||||||
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: {
|
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: {
|
||||||
text_yes?: string,
|
text_yes?: string,
|
||||||
text_no?: string
|
text_no?: string,
|
||||||
|
|
||||||
|
closeable?: boolean;
|
||||||
}) {
|
}) {
|
||||||
properties = properties || {};
|
properties = properties || {};
|
||||||
|
|
||||||
|
@ -16,6 +18,7 @@ namespace Modals {
|
||||||
props.header = header;
|
props.header = header;
|
||||||
props.template_properties.question = ModalFunctions.jqueriefy(body);
|
props.template_properties.question = ModalFunctions.jqueriefy(body);
|
||||||
|
|
||||||
|
props.closeable = typeof(properties.closeable) !== "boolean" || properties.closeable;
|
||||||
const modal = createModal(props);
|
const modal = createModal(props);
|
||||||
let submited = false;
|
let submited = false;
|
||||||
const button_yes = modal.htmlTag.find(".button-yes");
|
const button_yes = modal.htmlTag.find(".button-yes");
|
||||||
|
|
Loading…
Add table
Reference in a new issue