Fixed the legacy modal icon and bring it back to the front

master
WolverinDEV 2021-05-16 12:22:11 +02:00
parent b7b4c51904
commit 13feceb289
7 changed files with 159 additions and 33 deletions

View File

@ -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++;

View File

@ -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();
}
});
}
}

View File

@ -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);
}

View File

@ -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",

View File

@ -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,
};

View File

@ -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();

View File

@ -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;
}
}