Fixed the legacy modal icon and bring it back to the front
parent
b7b4c51904
commit
13feceb289
|
@ -39,6 +39,7 @@ import ipRegex from "ip-regex";
|
|||
import * as htmltags from "./ui/htmltags";
|
||||
import {ServerSettings} from "tc-shared/ServerSettings";
|
||||
import {ignorePromise} from "tc-shared/proto";
|
||||
import {InvokerInfo} from "tc-shared/tree/ChannelDefinitions";
|
||||
|
||||
assertMainApplication();
|
||||
|
||||
|
@ -68,6 +69,43 @@ export enum DisconnectReason {
|
|||
UNKNOWN
|
||||
}
|
||||
|
||||
export type ClientDisconnectInfo = {
|
||||
reason: "handler-destroy" | "requested"
|
||||
} | {
|
||||
reason: "connection-closed" | "connection-ping-timeout"
|
||||
} | {
|
||||
reason: "connect-failure" | "connect-dns-fail" | "connect-identity-too-low"
|
||||
} | {
|
||||
reason: "connect-identity-unsupported",
|
||||
unsupportedReason: "ts3-server"
|
||||
} | {
|
||||
/* Connect fail since client has been banned */
|
||||
reason: "connect-banned",
|
||||
message: string
|
||||
} | {
|
||||
/* Connection got closed because the client got kicked */
|
||||
reason: "client-kicked",
|
||||
message: string,
|
||||
invoker: InvokerInfo
|
||||
} | {
|
||||
/* Connection got closed because the client got banned */
|
||||
reason: "client-banned",
|
||||
message: string,
|
||||
length: number | 0,
|
||||
invoker?: InvokerInfo,
|
||||
} | {
|
||||
reason: "server-shutdown",
|
||||
message: string,
|
||||
/* TODO: Do we have an invoker here? */
|
||||
} | {
|
||||
reason: "connect-host-message-disconnect",
|
||||
message: string
|
||||
} | {
|
||||
reason: "generic-connection-error",
|
||||
message: string,
|
||||
allowReconnect: boolean
|
||||
}
|
||||
|
||||
export enum ConnectionState {
|
||||
UNCONNECTED, /* no connection is currenting running */
|
||||
CONNECTING, /* we try to establish a connection to the target server */
|
||||
|
@ -120,17 +158,6 @@ export interface LocalClientStatus {
|
|||
queries_visible: boolean;
|
||||
}
|
||||
|
||||
export interface ConnectParametersOld {
|
||||
nickname?: string;
|
||||
channel?: {
|
||||
target: string | number;
|
||||
password?: string;
|
||||
};
|
||||
token?: string;
|
||||
password?: {password: string, hashed: boolean};
|
||||
auto_reconnect_attempt?: boolean;
|
||||
}
|
||||
|
||||
export class ConnectionHandler {
|
||||
readonly handlerId: string;
|
||||
|
||||
|
@ -530,6 +557,15 @@ export class ConnectionHandler {
|
|||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method dispatches a connection disconnect.
|
||||
* The method can be called out of every context and will properly terminate
|
||||
* all resources related to the current connection.
|
||||
*/
|
||||
handleDisconnectNew(reason: ClientDisconnectInfo) {
|
||||
/* TODO: */
|
||||
}
|
||||
|
||||
private _certificate_modal: Modal;
|
||||
handleDisconnect(type: DisconnectReason, data: any = {}) {
|
||||
this.connectAttemptId++;
|
||||
|
|
|
@ -4,6 +4,7 @@ import {AbstractServerConnection} from "../connection/ConnectionBase";
|
|||
import {DisconnectReason} from "../ConnectionHandler";
|
||||
import {ConnectParameters} from "tc-shared/ui/modal/connect/Controller";
|
||||
import {getBackend} from "tc-shared/backend";
|
||||
import {ErrorCode} from "tc-shared/connection/ErrorCode";
|
||||
|
||||
export interface HandshakeIdentityHandler {
|
||||
connection: AbstractServerConnection;
|
||||
|
@ -14,6 +15,18 @@ export interface HandshakeIdentityHandler {
|
|||
fillClientInitData(data: any);
|
||||
}
|
||||
|
||||
export type ServerHandshakeError = {
|
||||
reason: "identity-unsupported",
|
||||
}
|
||||
|
||||
export type ServerHandshakeResult = {
|
||||
status: "success",
|
||||
/* TODO: May some other variables as well? */
|
||||
} | {
|
||||
status: "failed",
|
||||
error: ServerHandshakeError
|
||||
};
|
||||
|
||||
export class HandshakeHandler {
|
||||
private connection: AbstractServerConnection;
|
||||
private handshakeImpl: HandshakeIdentityHandler;
|
||||
|
@ -114,7 +127,7 @@ export class HandshakeHandler {
|
|||
this.handshakeImpl.fillClientInitData(data);
|
||||
this.connection.send_command("clientinit", data).catch(error => {
|
||||
if(error instanceof CommandResult) {
|
||||
if(error.id == 1028) {
|
||||
if(error.id == ErrorCode.SERVER_INVALID_PASSWORD) {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.SERVER_REQUIRES_PASSWORD);
|
||||
} else if(error.id == 783 || error.id == 519) {
|
||||
error.extra_message = isNaN(parseInt(error.extra_message)) ? "8" : error.extra_message;
|
||||
|
@ -124,8 +137,9 @@ export class HandshakeHandler {
|
|||
} else {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_KICKED, error);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
this.connection.disconnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -71,8 +71,9 @@ export class ConnectionProfile {
|
|||
|
||||
spawnIdentityHandshakeHandler(connection: AbstractServerConnection): HandshakeIdentityHandler | undefined {
|
||||
const identity = this.selectedIdentity();
|
||||
if (!identity)
|
||||
if (!identity) {
|
||||
return undefined;
|
||||
}
|
||||
return identity.spawn_identity_handshake_handler(connection);
|
||||
}
|
||||
|
||||
|
|
|
@ -808,6 +808,13 @@ export class Settings {
|
|||
description: "Last used TeaSpeak Client version (TeaClient only)",
|
||||
}
|
||||
|
||||
/* When using a higher number clients crash due to a bug in NodeJS */
|
||||
static readonly KEY_IPC_EVENT_BUNDLE_MAX_SIZE: ValuedRegistryKey<number> = {
|
||||
key: "ipc_event_bundle_max_size",
|
||||
valueType: "number",
|
||||
defaultValue: 0
|
||||
}
|
||||
|
||||
static readonly FN_LOG_ENABLED: (category: string) => RegistryKey<boolean> = category => {
|
||||
return {
|
||||
key: "log." + category.toLowerCase() + ".enabled",
|
||||
|
|
|
@ -12,4 +12,13 @@ export type ChannelDescriptionResult = {
|
|||
} | {
|
||||
status: "error",
|
||||
message: string
|
||||
};
|
||||
|
||||
/**
|
||||
* The invoker info the server sends with all notifies if required
|
||||
*/
|
||||
export type InvokerInfo = {
|
||||
invokerName: string,
|
||||
invokerUniqueId: string,
|
||||
invokerId: number,
|
||||
};
|
|
@ -2,6 +2,7 @@ import * as loader from "tc-loader";
|
|||
import {Stage} from "tc-loader";
|
||||
import $ from "jquery";
|
||||
import {LogCategory, logError} from "tc-shared/log";
|
||||
import ModalIcon from "../react-elements/modal/TeaCup.png";
|
||||
|
||||
export enum ElementType {
|
||||
HEADER,
|
||||
|
@ -88,8 +89,6 @@ export class ModalProperties {
|
|||
}
|
||||
|
||||
template_properties?: any = {};
|
||||
trigger_tab: boolean = true;
|
||||
full_size?: boolean = false;
|
||||
}
|
||||
|
||||
namespace modal {
|
||||
|
@ -218,13 +217,14 @@ export class Modal {
|
|||
modal_footer: footer,
|
||||
|
||||
closeable: this.properties.closeable,
|
||||
full_size: this.properties.full_size
|
||||
full_size: false
|
||||
};
|
||||
|
||||
if(this.properties.template_properties)
|
||||
Object.assign(properties, this.properties.template_properties);
|
||||
|
||||
const tag = template.renderTag(properties);
|
||||
tag.find(".modal-header .container-icon img").attr("src", ModalIcon);
|
||||
if(typeof(this.properties.width) !== "undefined" && typeof(this.properties.min_width) !== "undefined")
|
||||
tag.find(".modal-content")
|
||||
.css("min-width", this.properties.min_width)
|
||||
|
@ -258,7 +258,7 @@ export class Modal {
|
|||
_global_modal_last = this.htmlTag[0];
|
||||
|
||||
this.shown = true;
|
||||
this.htmlTag.prependTo($("body"));
|
||||
this.htmlTag.appendTo($("body"));
|
||||
|
||||
_global_modal_count++;
|
||||
this.htmlTag.show();
|
||||
|
|
|
@ -2,16 +2,43 @@ import {UiVariableConsumer, UiVariableMap, UiVariableProvider} from "tc-shared/u
|
|||
import {guid} from "tc-shared/crypto/uid";
|
||||
import {LogCategory, logWarn} from "tc-shared/log";
|
||||
import ReactDOM from "react-dom";
|
||||
import {Settings, settings} from "tc-shared/settings";
|
||||
|
||||
/*
|
||||
* We need to globally bundle all IPC invoke events since
|
||||
* calling setImmediate too often will cause a electron crash with
|
||||
* "async hook stack has become corrupted (actual: 88, expected: 0)".
|
||||
*
|
||||
* WolverinDEV has never experience it by himself but @REDOSS had.
|
||||
*/
|
||||
let ipcInvokeCallbacks: (() => void)[];
|
||||
|
||||
function registerInvokeCallback(callback: () => void) {
|
||||
if(Array.isArray(ipcInvokeCallbacks)) {
|
||||
ipcInvokeCallbacks.push(callback);
|
||||
} else {
|
||||
ipcInvokeCallbacks = [ callback ];
|
||||
setImmediate(() => {
|
||||
const callbacks = ipcInvokeCallbacks;
|
||||
ipcInvokeCallbacks = undefined;
|
||||
for(const callback of callbacks) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class IpcUiVariableProvider<Variables extends UiVariableMap> extends UiVariableProvider<Variables> {
|
||||
readonly ipcChannelId: string;
|
||||
private broadcastChannel: BroadcastChannel;
|
||||
private readonly bundleMaxSize: number;
|
||||
|
||||
private broadcastChannel: BroadcastChannel;
|
||||
private enqueuedMessages: any[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.bundleMaxSize = settings.getValue(Settings.KEY_IPC_EVENT_BUNDLE_MAX_SIZE);
|
||||
this.ipcChannelId = "teaspeak-ipc-vars-" + guid();
|
||||
this.broadcastChannel = new BroadcastChannel(this.ipcChannelId);
|
||||
this.broadcastChannel.onmessage = event => this.handleIpcMessage(event.data, event.source, event.origin);
|
||||
|
@ -96,19 +123,33 @@ export class IpcUiVariableProvider<Variables extends UiVariableMap> extends UiVa
|
|||
* @private
|
||||
*/
|
||||
private broadcastIpcMessage(message: any) {
|
||||
if(this.bundleMaxSize <= 0) {
|
||||
this.broadcastChannel.postMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Array.isArray(this.enqueuedMessages)) {
|
||||
this.enqueuedMessages.push(message);
|
||||
if(this.enqueuedMessages.length >= this.bundleMaxSize) {
|
||||
this.sendEnqueuedMessages();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.enqueuedMessages = [ message ];
|
||||
setImmediate(() => {
|
||||
this.broadcastChannel.postMessage({
|
||||
type: "bundled",
|
||||
messages: this.enqueuedMessages
|
||||
});
|
||||
this.enqueuedMessages = undefined;
|
||||
})
|
||||
registerInvokeCallback(() => this.sendEnqueuedMessages());
|
||||
}
|
||||
|
||||
private sendEnqueuedMessages() {
|
||||
if(!this.enqueuedMessages) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.broadcastChannel.postMessage({
|
||||
type: "bundled",
|
||||
messages: this.enqueuedMessages
|
||||
});
|
||||
this.enqueuedMessages = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,8 +158,11 @@ export type IpcVariableDescriptor<Variables extends UiVariableMap> = {
|
|||
}
|
||||
|
||||
let editTokenIndex = 0;
|
||||
|
||||
class IpcUiVariableConsumer<Variables extends UiVariableMap> extends UiVariableConsumer<Variables> {
|
||||
readonly description: IpcVariableDescriptor<Variables>;
|
||||
private readonly bundleMaxSize: number;
|
||||
|
||||
private broadcastChannel: BroadcastChannel;
|
||||
private editListener: {[key: string]: { resolve: () => void, reject: (error) => void }};
|
||||
|
||||
|
@ -129,6 +173,7 @@ class IpcUiVariableConsumer<Variables extends UiVariableMap> extends UiVariableC
|
|||
this.description = description;
|
||||
this.editListener = {};
|
||||
|
||||
this.bundleMaxSize = settings.getValue(Settings.KEY_IPC_EVENT_BUNDLE_MAX_SIZE);
|
||||
this.broadcastChannel = new BroadcastChannel(this.description.ipcChannelId);
|
||||
this.broadcastChannel.onmessage = event => this.handleIpcMessage(event.data, event.source);
|
||||
}
|
||||
|
@ -207,19 +252,33 @@ class IpcUiVariableConsumer<Variables extends UiVariableMap> extends UiVariableC
|
|||
* @private
|
||||
*/
|
||||
private sendIpcMessage(message: any) {
|
||||
if(this.bundleMaxSize <= 0) {
|
||||
this.broadcastChannel.postMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Array.isArray(this.enqueuedMessages)) {
|
||||
this.enqueuedMessages.push(message);
|
||||
if(this.enqueuedMessages.length >= this.bundleMaxSize) {
|
||||
this.sendEnqueuedMessages();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.enqueuedMessages = [ message ];
|
||||
setImmediate(() => {
|
||||
this.broadcastChannel.postMessage({
|
||||
type: "bundled",
|
||||
messages: this.enqueuedMessages
|
||||
});
|
||||
this.enqueuedMessages = undefined;
|
||||
})
|
||||
registerInvokeCallback(() => this.sendEnqueuedMessages());
|
||||
}
|
||||
|
||||
private sendEnqueuedMessages() {
|
||||
if(!this.enqueuedMessages) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.broadcastChannel.postMessage({
|
||||
type: "bundled",
|
||||
messages: this.enqueuedMessages
|
||||
});
|
||||
this.enqueuedMessages = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue