Resolved all tc-shared imports into relative imports

canary
WolverinDEV 2020-09-12 15:49:20 +02:00
parent 391205cb34
commit 4a4cbdf38e
153 changed files with 3851 additions and 3090 deletions

View File

@ -1,18 +1,78 @@
import * as ts from "tsd/libraries/typescript";
import {SourceFile, SyntaxKind, TransformerFactory} from "tsd/libraries/typescript";
import * as path from "path";
import * as fs from "fs-extra";
type ImportReplacement = { index: number, length: number, replacement: string };
let importReplacements: ImportReplacement[] = [];
async function processFile(file: string) {
const ImportTransformerFactory: (depth: number) => TransformerFactory<SourceFile> = fileDepth => context => source => {
const visit = (node: ts.Node, depth: number) => {
if(node.kind === SyntaxKind.ImportDeclaration) {
const decl = node as ts.ImportDeclaration;
if(decl.moduleSpecifier?.kind === SyntaxKind.StringLiteral) {
const module = decl.moduleSpecifier as ts.StringLiteral;
if(module.text.startsWith("tc-shared")) {
const rootPath = [...new Array(fileDepth)].map(() => "..").join("/");
const newPath = (rootPath || ".") + module.text.substr(9);
console.error("Import: %o -> %o", module.text, newPath);
importReplacements.push({
index: module.getStart(source, false) + 1,
length: module.getWidth(source) - 2,
replacement: newPath
});
}
}
}
if(depth > 5) {
/* no import decl possible */
return node;
}
return ts.visitEachChild(node, n => visit(n, depth + 1), context);
};
return ts.visitNode(source, n => visit(n, fileDepth));
}
async function processDirectory(directory: string) {
async function processFile(file: string, fileDepth: number) {
if(path.extname(file) !== ".ts") {
return;
}
let sourceData = (await fs.readFile(file)).toString();
let source = ts.createSourceFile(
file,
sourceData,
ts.ScriptTarget.ES2015,
true
);
console.log("Transforming %s", file);
importReplacements = [];
ts.transform(source, [ImportTransformerFactory(fileDepth)]);
importReplacements.sort((a, b) => b.index - a.index);
importReplacements.forEach(replacement => {
sourceData = sourceData.substring(0, replacement.index) + replacement.replacement + sourceData.substring(replacement.index + replacement.length);
});
await fs.writeFile(file, sourceData);
}
async function processDirectory(directory: string, depth: number) {
const files = await fs.readdir(directory);
for(const file of files) {
console.log(file);
let filePath = path.join(directory, file);
if((await fs.stat(filePath)).isDirectory()) {
await processDirectory(filePath, depth + 1);
} else {
await processFile(filePath, depth);
}
}
}
processDirectory(path.join(__dirname, "js")).catch(error => {
processDirectory(path.join(__dirname, "js"), 0).catch(error => {
console.error(error);
});

View File

@ -1,43 +1,43 @@
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {PermissionManager} from "tc-shared/permission/PermissionManager";
import {GroupManager} from "tc-shared/permission/GroupManager";
import {ServerSettings, Settings, settings, StaticSettings} from "tc-shared/settings";
import {Sound, SoundManager} from "tc-shared/sound/Sounds";
import {ConnectionProfile} from "tc-shared/profiles/ConnectionProfile";
import * as log from "tc-shared/log";
import {LogCategory, logError, logInfo, logWarn} from "tc-shared/log";
import {createErrorModal, createInfoModal, createInputModal, Modal} from "tc-shared/ui/elements/Modal";
import {hashPassword} from "tc-shared/utils/helpers";
import {HandshakeHandler} from "tc-shared/connection/HandshakeHandler";
import {AbstractServerConnection} from "./connection/ConnectionBase";
import {PermissionManager} from "./permission/PermissionManager";
import {GroupManager} from "./permission/GroupManager";
import {ServerSettings, Settings, settings, StaticSettings} from "./settings";
import {Sound, SoundManager} from "./sound/Sounds";
import {ConnectionProfile} from "./profiles/ConnectionProfile";
import * as log from "./log";
import {LogCategory, logError, logInfo, logWarn} from "./log";
import {createErrorModal, createInfoModal, createInputModal, Modal} from "./ui/elements/Modal";
import {hashPassword} from "./utils/helpers";
import {HandshakeHandler} from "./connection/HandshakeHandler";
import * as htmltags from "./ui/htmltags";
import {FilterMode, InputStartResult, InputState} from "tc-shared/voice/RecorderBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {defaultRecorder, RecorderProfile} from "tc-shared/voice/RecorderProfile";
import {Frame} from "tc-shared/ui/frames/chat_frame";
import {Hostbanner} from "tc-shared/ui/frames/hostbanner";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {connection_log, Regex} from "tc-shared/ui/modal/ModalConnect";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {spawnAvatarUpload} from "tc-shared/ui/modal/ModalAvatar";
import {FilterMode, InputStartResult, InputState} from "./voice/RecorderBase";
import {CommandResult} from "./connection/ServerConnectionDeclaration";
import {defaultRecorder, RecorderProfile} from "./voice/RecorderProfile";
import {Frame} from "./ui/frames/chat_frame";
import {Hostbanner} from "./ui/frames/hostbanner";
import {server_connections} from "./ui/frames/connection_handlers";
import {connection_log, Regex} from "./ui/modal/ModalConnect";
import {formatMessage} from "./ui/frames/chat";
import {spawnAvatarUpload} from "./ui/modal/ModalAvatar";
import * as dns from "tc-backend/dns";
import {EventHandler, Registry} from "tc-shared/events";
import {FileManager} from "tc-shared/file/FileManager";
import {FileTransferState, TransferProvider} from "tc-shared/file/Transfer";
import {traj} from "tc-shared/i18n/localize";
import {md5} from "tc-shared/crypto/md5";
import {guid} from "tc-shared/crypto/uid";
import {ServerEventLog} from "tc-shared/ui/frames/log/ServerEventLog";
import {EventType} from "tc-shared/ui/frames/log/Definitions";
import {PluginCmdRegistry} from "tc-shared/connection/PluginCmdHandler";
import {W2GPluginCmdHandler} from "tc-shared/video-viewer/W2GPlugin";
import {VoiceConnectionStatus, WhisperSessionInitializeData} from "tc-shared/connection/VoiceConnection";
import {getServerConnectionFactory} from "tc-shared/connection/ConnectionFactory";
import {WhisperSession} from "tc-shared/voice/VoiceWhisper";
import {spawnEchoTestModal} from "tc-shared/ui/modal/echo-test/Controller";
import {ServerFeature, ServerFeatures} from "tc-shared/connection/ServerFeatures";
import {ChannelTree} from "tc-shared/tree/ChannelTree";
import {LocalClientEntry} from "tc-shared/tree/Client";
import {ServerAddress} from "tc-shared/tree/Server";
import {EventHandler, Registry} from "./events";
import {FileManager} from "./file/FileManager";
import {FileTransferState, TransferProvider} from "./file/Transfer";
import {traj} from "./i18n/localize";
import {md5} from "./crypto/md5";
import {guid} from "./crypto/uid";
import {ServerEventLog} from "./ui/frames/log/ServerEventLog";
import {EventType} from "./ui/frames/log/Definitions";
import {PluginCmdRegistry} from "./connection/PluginCmdHandler";
import {W2GPluginCmdHandler} from "./video-viewer/W2GPlugin";
import {VoiceConnectionStatus, WhisperSessionInitializeData} from "./connection/VoiceConnection";
import {getServerConnectionFactory} from "./connection/ConnectionFactory";
import {WhisperSession} from "./voice/VoiceWhisper";
import {spawnEchoTestModal} from "./ui/modal/echo-test/Controller";
import {ServerFeature, ServerFeatures} from "./connection/ServerFeatures";
import {ChannelTree} from "./tree/ChannelTree";
import {LocalClientEntry} from "./tree/Client";
import {ServerAddress} from "./tree/Server";
export enum InputHardwareState {
MISSING,

View File

@ -1,9 +1,9 @@
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {EventType, KeyDescriptor, KeyEvent, KeyHook} from "tc-shared/PPTListener";
import {server_connections} from "./ui/frames/connection_handlers";
import {EventType, KeyDescriptor, KeyEvent, KeyHook} from "./PPTListener";
import * as ppt from "tc-backend/ppt";
import {Settings, settings} from "tc-shared/settings";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {Settings, settings} from "./settings";
import * as log from "./log";
import {LogCategory} from "./log";
export interface KeyControl {
category: string;

View File

@ -1,5 +1,5 @@
import {AbstractInput, LevelMeter} from "tc-shared/voice/RecorderBase";
import {Registry} from "tc-shared/events";
import {AbstractInput, LevelMeter} from "../voice/RecorderBase";
import {Registry} from "../events";
export type DeviceQueryResult = {}

View File

@ -1,13 +1,13 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {guid} from "tc-shared/crypto/uid";
import {createErrorModal, createInfoModal, createInputModal} from "tc-shared/ui/elements/Modal";
import {default_profile, find_profile} from "tc-shared/profiles/ConnectionProfile";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {spawnConnectModal} from "tc-shared/ui/modal/ModalConnect";
import * as log from "./log";
import {LogCategory} from "./log";
import {guid} from "./crypto/uid";
import {createErrorModal, createInfoModal, createInputModal} from "./ui/elements/Modal";
import {default_profile, find_profile} from "./profiles/ConnectionProfile";
import {server_connections} from "./ui/frames/connection_handlers";
import {spawnConnectModal} from "./ui/modal/ModalConnect";
import * as top_menu from "./ui/frames/MenuBar";
import {control_bar_instance} from "tc-shared/ui/frames/control-bar";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {control_bar_instance} from "./ui/frames/control-bar";
import {ConnectionHandler} from "./ConnectionHandler";
export const boorkmak_connect = (mark: Bookmark, new_tab?: boolean) => {
const profile = find_profile(mark.connect_profile) || default_profile();

View File

@ -2,8 +2,8 @@ import {
AbstractServerConnection,
ServerCommand,
SingleCommandHandler
} from "tc-shared/connection/ConnectionBase";
import {tr} from "tc-shared/i18n/localize";
} from "../connection/ConnectionBase";
import {tr} from "../i18n/localize";
export abstract class AbstractCommandHandler {
readonly connection: AbstractServerConnection;

View File

@ -1,9 +1,9 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {AbstractServerConnection, CommandOptions, ServerCommand} from "tc-shared/connection/ConnectionBase";
import {Sound} from "tc-shared/sound/Sounds";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {createErrorModal, createInfoModal, createInputModal, createModal} from "tc-shared/ui/elements/Modal";
import * as log from "../log";
import {LogCategory} from "../log";
import {AbstractServerConnection, CommandOptions, ServerCommand} from "../connection/ConnectionBase";
import {Sound} from "../sound/Sounds";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {createErrorModal, createInfoModal, createInputModal, createModal} from "../ui/elements/Modal";
import {
ClientConnectionInfo,
ClientEntry,
@ -11,19 +11,19 @@ import {
LocalClientEntry,
MusicClientEntry,
SongInfo
} from "tc-shared/tree/Client";
import {ChannelEntry} from "tc-shared/tree/Channel";
import {ConnectionHandler, ConnectionState, DisconnectReason, ViewReasonId} from "tc-shared/ConnectionHandler";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {spawnPoke} from "tc-shared/ui/modal/ModalPoke";
import {AbstractCommandHandler, AbstractCommandHandlerBoss} from "tc-shared/connection/AbstractCommandHandler";
import {batch_updates, BatchUpdateType, flush_batched_updates} from "tc-shared/ui/react-elements/ReactComponentBase";
import {OutOfViewClient} from "tc-shared/ui/frames/side/PrivateConversationManager";
import {renderBBCodeAsJQuery} from "tc-shared/text/bbcode";
import {tr} from "tc-shared/i18n/localize";
import {EventClient, EventType} from "tc-shared/ui/frames/log/Definitions";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
} from "../tree/Client";
import {ChannelEntry} from "../tree/Channel";
import {ConnectionHandler, ConnectionState, DisconnectReason, ViewReasonId} from "../ConnectionHandler";
import {formatMessage} from "../ui/frames/chat";
import {server_connections} from "../ui/frames/connection_handlers";
import {spawnPoke} from "../ui/modal/ModalPoke";
import {AbstractCommandHandler, AbstractCommandHandlerBoss} from "../connection/AbstractCommandHandler";
import {batch_updates, BatchUpdateType, flush_batched_updates} from "../ui/react-elements/ReactComponentBase";
import {OutOfViewClient} from "../ui/frames/side/PrivateConversationManager";
import {renderBBCodeAsJQuery} from "../text/bbcode";
import {tr} from "../i18n/localize";
import {EventClient, EventType} from "../ui/frames/log/Definitions";
import {ErrorCode} from "../connection/ErrorCode";
export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss {
constructor(connection: AbstractServerConnection) {

View File

@ -1,16 +1,16 @@
import {ServerCommand, SingleCommandHandler} from "tc-shared/connection/ConnectionBase";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {ServerCommand, SingleCommandHandler} from "../connection/ConnectionBase";
import * as log from "../log";
import {LogCategory} from "../log";
import {
ClientNameInfo,
CommandResult,
Playlist, PlaylistInfo, PlaylistSong,
QueryList,
QueryListEntry, ServerGroupClient
} from "tc-shared/connection/ServerConnectionDeclaration";
import {AbstractCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {tr} from "tc-shared/i18n/localize";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
} from "../connection/ServerConnectionDeclaration";
import {AbstractCommandHandler} from "../connection/AbstractCommandHandler";
import {tr} from "../i18n/localize";
import {ErrorCode} from "../connection/ErrorCode";
export class CommandHelper extends AbstractCommandHandler {
private whoAmIResponse: any;

View File

@ -1,11 +1,11 @@
import {CommandHelper} from "tc-shared/connection/CommandHelper";
import {HandshakeHandler} from "tc-shared/connection/HandshakeHandler";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ServerAddress} from "tc-shared/tree/Server";
import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import {AbstractCommandHandlerBoss} from "tc-shared/connection/AbstractCommandHandler";
import {Registry} from "tc-shared/events";
import {AbstractVoiceConnection} from "tc-shared/connection/VoiceConnection";
import {CommandHelper} from "../connection/CommandHelper";
import {HandshakeHandler} from "../connection/HandshakeHandler";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {ServerAddress} from "../tree/Server";
import {ConnectionHandler, ConnectionState} from "../ConnectionHandler";
import {AbstractCommandHandlerBoss} from "../connection/AbstractCommandHandler";
import {Registry} from "../events";
import {AbstractVoiceConnection} from "../connection/VoiceConnection";
export interface CommandOptions {
flagset?: string[]; /* default: [] */

View File

@ -1,5 +1,5 @@
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {AbstractServerConnection} from "../connection/ConnectionBase";
import {ConnectionHandler} from "../ConnectionHandler";
export interface ServerConnectionFactory {
create(client: ConnectionHandler) : AbstractServerConnection;

View File

@ -1,13 +1,13 @@
import {
AbstractVoiceConnection,
VoiceConnectionStatus, WhisperSessionInitializer
} from "tc-shared/connection/VoiceConnection";
import {RecorderProfile} from "tc-shared/voice/RecorderProfile";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {VoiceClient} from "tc-shared/voice/VoiceClient";
import {VoicePlayerEvents, VoicePlayerLatencySettings, VoicePlayerState} from "tc-shared/voice/VoicePlayer";
import {WhisperSession, WhisperTarget} from "tc-shared/voice/VoiceWhisper";
import {Registry} from "tc-shared/events";
} from "../connection/VoiceConnection";
import {RecorderProfile} from "../voice/RecorderProfile";
import {AbstractServerConnection} from "../connection/ConnectionBase";
import {VoiceClient} from "../voice/VoiceClient";
import {VoicePlayerEvents, VoicePlayerLatencySettings, VoicePlayerState} from "../voice/VoicePlayer";
import {WhisperSession, WhisperTarget} from "../voice/VoiceWhisper";
import {Registry} from "../events";
class DummyVoiceClient implements VoiceClient {
readonly events: Registry<VoicePlayerEvents>;

View File

@ -1,11 +1,11 @@
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {IdentitifyType} from "tc-shared/profiles/Identity";
import {TeaSpeakIdentity} from "tc-shared/profiles/identities/TeamSpeakIdentity";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {ConnectionProfile} from "tc-shared/profiles/ConnectionProfile";
import {settings} from "tc-shared/settings";
import {ConnectParameters, DisconnectReason} from "tc-shared/ConnectionHandler";
import {tr} from "tc-shared/i18n/localize";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {IdentitifyType} from "../profiles/Identity";
import {TeaSpeakIdentity} from "../profiles/identities/TeamSpeakIdentity";
import {AbstractServerConnection} from "../connection/ConnectionBase";
import {ConnectionProfile} from "../profiles/ConnectionProfile";
import {settings} from "../settings";
import {ConnectParameters, DisconnectReason} from "../ConnectionHandler";
import {tr} from "../i18n/localize";
export interface HandshakeIdentityHandler {
connection: AbstractServerConnection;

View File

@ -1,7 +1,7 @@
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {AbstractCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {AbstractServerConnection, ServerCommand} from "tc-shared/connection/ConnectionBase";
import {ConnectionHandler} from "../ConnectionHandler";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {AbstractCommandHandler} from "../connection/AbstractCommandHandler";
import {AbstractServerConnection, ServerCommand} from "../connection/ConnectionBase";
export interface PluginCommandInvoker {
clientId: number;

View File

@ -1,4 +1,4 @@
import {LaterPromise} from "tc-shared/utils/LaterPromise";
import {LaterPromise} from "../utils/LaterPromise";
export class CommandResult {
success: boolean;

View File

@ -1,9 +1,9 @@
import {ConnectionEvents, ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import {Registry} from "tc-shared/events";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {LogCategory, logDebug, logTrace, logWarn} from "tc-shared/log";
import {ExplicitCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {ConnectionEvents, ConnectionHandler, ConnectionState} from "../ConnectionHandler";
import {Registry} from "../events";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {ErrorCode} from "../connection/ErrorCode";
import {LogCategory, logDebug, logTrace, logWarn} from "../log";
import {ExplicitCommandHandler} from "../connection/AbstractCommandHandler";
export type ServerFeatureSupport = "unsupported" | "supported" | "experimental" | "deprecated";

View File

@ -1,8 +1,8 @@
import {RecorderProfile} from "tc-shared/voice/RecorderProfile";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {Registry} from "tc-shared/events";
import {VoiceClient} from "tc-shared/voice/VoiceClient";
import {WhisperSession, WhisperTarget} from "tc-shared/voice/VoiceWhisper";
import {RecorderProfile} from "../voice/RecorderProfile";
import {AbstractServerConnection} from "../connection/ConnectionBase";
import {Registry} from "../events";
import {VoiceClient} from "../voice/VoiceClient";
import {WhisperSession, WhisperTarget} from "../voice/VoiceWhisper";
export enum VoiceConnectionStatus {
ClientUnsupported,

View File

@ -1,6 +1,6 @@
import * as log from "./log";
import {LogCategory} from "./log";
import {guid} from "tc-shared/crypto/uid";
import {guid} from "./crypto/uid";
import * as React from "react";
import {useEffect} from "react";

View File

@ -1,19 +1,19 @@
import {Registry} from "tc-shared/events";
import {ClientGlobalControlEvents} from "tc-shared/events/GlobalEvents";
import {Sound} from "tc-shared/sound/Sounds";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {createErrorModal, createInfoModal, createInputModal} from "tc-shared/ui/elements/Modal";
import {settings} from "tc-shared/settings";
import {spawnConnectModal} from "tc-shared/ui/modal/ModalConnect";
import PermissionType from "tc-shared/permission/PermissionType";
import {spawnQueryCreate} from "tc-shared/ui/modal/ModalQuery";
import {openBanList} from "tc-shared/ui/modal/ModalBanList";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {spawnSettingsModal} from "tc-shared/ui/modal/ModalSettings";
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
import {tr} from "tc-shared/i18n/localize";
import {Registry} from "../events";
import {ClientGlobalControlEvents} from "../events/GlobalEvents";
import {Sound} from "../sound/Sounds";
import {ConnectionHandler} from "../ConnectionHandler";
import {server_connections} from "../ui/frames/connection_handlers";
import {createErrorModal, createInfoModal, createInputModal} from "../ui/elements/Modal";
import {settings} from "../settings";
import {spawnConnectModal} from "../ui/modal/ModalConnect";
import PermissionType from "../permission/PermissionType";
import {spawnQueryCreate} from "../ui/modal/ModalQuery";
import {openBanList} from "../ui/modal/ModalBanList";
import {formatMessage} from "../ui/frames/chat";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {spawnSettingsModal} from "../ui/modal/ModalSettings";
import {spawnPermissionEditorModal} from "../ui/modal/permission/ModalPermissionEditor";
import {tr} from "../i18n/localize";
/*
function initialize_sounds(event_registry: Registry<ClientGlobalControlEvents>) {

View File

@ -1,5 +1,5 @@
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {Registry} from "tc-shared/events";
import {ConnectionHandler} from "../ConnectionHandler";
import {Registry} from "../events";
export interface ClientGlobalControlEvents {
/* open a basic window */

View File

@ -1,5 +1,5 @@
import {Registry} from "tc-shared/events";
import * as hex from "tc-shared/crypto/hex";
import {Registry} from "../events";
import * as hex from "../crypto/hex";
export const kIPCAvatarChannel = "avatars";
export const kLoadingAvatarImage = "img/loading_image.svg";

View File

@ -1,4 +1,4 @@
import {tr} from "tc-shared/i18n/localize";
import {tr} from "../i18n/localize";
export enum ImageType {
UNKNOWN,

View File

@ -1,22 +1,22 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import * as log from "../log";
import {LogCategory} from "../log";
import * as ipc from "../ipc/BrowserIPC";
import {ChannelMessage} from "../ipc/BrowserIPC";
import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import {image_type, ImageCache, media_image_type} from "tc-shared/file/ImageCache";
import {FileManager} from "tc-shared/file/FileManager";
import {image_type, ImageCache, media_image_type} from "../file/ImageCache";
import {FileManager} from "../file/FileManager";
import {
FileDownloadTransfer,
FileTransferState,
ResponseTransferTarget,
TransferProvider,
TransferTargetType
} from "tc-shared/file/Transfer";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {ClientEntry} from "tc-shared/tree/Client";
import {tr} from "tc-shared/i18n/localize";
} from "../file/Transfer";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {server_connections} from "../ui/frames/connection_handlers";
import {ClientEntry} from "../tree/Client";
import {tr} from "../i18n/localize";
import {
AbstractAvatarManager,
AbstractAvatarManagerFactory,
@ -26,10 +26,10 @@ import {
kIPCAvatarChannel,
setGlobalAvatarManagerFactory,
uniqueId2AvatarId
} from "tc-shared/file/Avatars";
import {IPCChannel} from "tc-shared/ipc/BrowserIPC";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
} from "../file/Avatars";
import {IPCChannel} from "../ipc/BrowserIPC";
import {ConnectionHandler} from "../ConnectionHandler";
import {ErrorCode} from "../connection/ErrorCode";
/* FIXME: Retry avatar download after some time! */

View File

@ -7,11 +7,11 @@ import {
AbstractAvatarManagerFactory, AvatarState, AvatarStateData, ClientAvatar,
kIPCAvatarChannel,
setGlobalAvatarManagerFactory, uniqueId2AvatarId
} from "tc-shared/file/Avatars";
import {IPCChannel} from "tc-shared/ipc/BrowserIPC";
import {Settings} from "tc-shared/settings";
} from "../file/Avatars";
import {IPCChannel} from "../ipc/BrowserIPC";
import {Settings} from "../settings";
import {ChannelMessage} from "../ipc/BrowserIPC";
import {guid} from "tc-shared/crypto/uid";
import {guid} from "../crypto/uid";
function isEquivalent(a, b) {
// Create arrays of property names

View File

@ -1,7 +1,7 @@
import {Registry} from "tc-shared/events";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {tr} from "tc-shared/i18n/localize";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {Registry} from "../events";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {tr} from "../i18n/localize";
import {ErrorCode} from "../connection/ErrorCode";
/* Transfer source types */
export enum TransferSourceType {

View File

@ -1,4 +1,4 @@
import {tr} from "tc-shared/i18n/localize";
import {tr} from "../i18n/localize";
interface CountryInfo {
name: string;

View File

@ -1,9 +1,9 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {guid} from "tc-shared/crypto/uid";
import {Settings, StaticSettings} from "tc-shared/settings";
import * as log from "../log";
import {LogCategory} from "../log";
import {guid} from "../crypto/uid";
import {Settings, StaticSettings} from "../settings";
import * as loader from "tc-loader";
import {formatMessage, formatMessageString} from "tc-shared/ui/frames/chat";
import {formatMessage, formatMessageString} from "../ui/frames/chat";
export interface TranslationKey {
message: string;

View File

@ -1,7 +1,7 @@
import "broadcastchannel-polyfill";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {ConnectHandler} from "tc-shared/ipc/ConnectHandler";
import * as log from "../log";
import {LogCategory} from "../log";
import {ConnectHandler} from "../ipc/ConnectHandler";
export interface BroadcastMessage {
timestamp: number;

View File

@ -1,7 +1,7 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {BasicIPCHandler, IPCChannel, ChannelMessage} from "tc-shared/ipc/BrowserIPC";
import {guid} from "tc-shared/crypto/uid";
import * as log from "../log";
import {LogCategory} from "../log";
import {BasicIPCHandler, IPCChannel, ChannelMessage} from "../ipc/BrowserIPC";
import {guid} from "../crypto/uid";
export type ConnectRequestData = {
address: string;

View File

@ -1,7 +1,7 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {BasicIPCHandler, IPCChannel, ChannelMessage} from "tc-shared/ipc/BrowserIPC";
import {guid} from "tc-shared/crypto/uid";
import * as log from "../log";
import {LogCategory} from "../log";
import {BasicIPCHandler, IPCChannel, ChannelMessage} from "../ipc/BrowserIPC";
import {guid} from "../crypto/uid";
export interface MethodProxyInvokeData {
method_name: string;

View File

@ -1,4 +1,4 @@
import {Settings, settings} from "tc-shared/settings";
import {Settings, settings} from "./settings";
import * as loader from "tc-loader";
export enum LogCategory {

View File

@ -1,13 +1,13 @@
import {LaterPromise} from "tc-shared/utils/LaterPromise";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {PermissionManager, PermissionValue} from "tc-shared/permission/PermissionManager";
import {ServerCommand} from "tc-shared/connection/ConnectionBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ConnectionEvents, ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import {AbstractCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {Registry} from "tc-shared/events";
import {tr} from "tc-shared/i18n/localize";
import {LaterPromise} from "../utils/LaterPromise";
import * as log from "../log";
import {LogCategory} from "../log";
import {PermissionManager, PermissionValue} from "../permission/PermissionManager";
import {ServerCommand} from "../connection/ConnectionBase";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {ConnectionEvents, ConnectionHandler, ConnectionState} from "../ConnectionHandler";
import {AbstractCommandHandler} from "../connection/AbstractCommandHandler";
import {Registry} from "../events";
import {tr} from "../i18n/localize";
export enum GroupType {
QUERY,

View File

@ -1,14 +1,14 @@
import * as log from "tc-shared/log";
import {LogCategory, LogType} from "tc-shared/log";
import {PermissionType} from "tc-shared/permission/PermissionType";
import {LaterPromise} from "tc-shared/utils/LaterPromise";
import {ServerCommand} from "tc-shared/connection/ConnectionBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {AbstractCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {Registry} from "tc-shared/events";
import {tr} from "tc-shared/i18n/localize";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import * as log from "../log";
import {LogCategory, LogType} from "../log";
import {PermissionType} from "../permission/PermissionType";
import {LaterPromise} from "../utils/LaterPromise";
import {ServerCommand} from "../connection/ConnectionBase";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {ConnectionHandler} from "../ConnectionHandler";
import {AbstractCommandHandler} from "../connection/AbstractCommandHandler";
import {Registry} from "../events";
import {tr} from "../i18n/localize";
import {ErrorCode} from "../connection/ErrorCode";
export class PermissionInfo {
name: string;

View File

@ -1,11 +1,11 @@
import {decode_identity, IdentitifyType, Identity} from "tc-shared/profiles/Identity";
import {guid} from "tc-shared/crypto/uid";
import {TeaForumIdentity} from "tc-shared/profiles/identities/TeaForumIdentity";
import {TeaSpeakIdentity} from "tc-shared/profiles/identities/TeamSpeakIdentity";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler";
import {createErrorModal} from "tc-shared/ui/elements/Modal";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {decode_identity, IdentitifyType, Identity} from "../profiles/Identity";
import {guid} from "../crypto/uid";
import {TeaForumIdentity} from "../profiles/identities/TeaForumIdentity";
import {TeaSpeakIdentity} from "../profiles/identities/TeamSpeakIdentity";
import {AbstractServerConnection} from "../connection/ConnectionBase";
import {HandshakeIdentityHandler} from "../connection/HandshakeHandler";
import {createErrorModal} from "../ui/elements/Modal";
import {formatMessage} from "../ui/frames/chat";
export class ConnectionProfile {
id: string;

View File

@ -1,6 +1,6 @@
import {AbstractServerConnection, ServerCommand} from "tc-shared/connection/ConnectionBase";
import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler";
import {AbstractCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {AbstractServerConnection, ServerCommand} from "../connection/ConnectionBase";
import {HandshakeIdentityHandler} from "../connection/HandshakeHandler";
import {AbstractCommandHandler} from "../connection/AbstractCommandHandler";
export enum IdentitifyType {
TEAFORO,

View File

@ -3,12 +3,12 @@ import {
HandshakeCommandHandler,
IdentitifyType,
Identity
} from "tc-shared/profiles/Identity";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler";
} from "../../profiles/Identity";
import * as log from "../../log";
import {LogCategory} from "../../log";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {AbstractServerConnection} from "../../connection/ConnectionBase";
import {HandshakeIdentityHandler} from "../../connection/HandshakeHandler";
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
readonly identity: NameIdentity;

View File

@ -3,12 +3,12 @@ import {
HandshakeCommandHandler,
IdentitifyType,
Identity
} from "tc-shared/profiles/Identity";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler";
} from "../../profiles/Identity";
import * as log from "../../log";
import {LogCategory} from "../../log";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {AbstractServerConnection} from "../../connection/ConnectionBase";
import {HandshakeIdentityHandler} from "../../connection/HandshakeHandler";
import * as forum from "./teaspeak-forum";
class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {

View File

@ -1,18 +1,18 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import * as asn1 from "tc-shared/crypto/asn1";
import * as sha from "tc-shared/crypto/sha";
import * as log from "../../log";
import {LogCategory} from "../../log";
import * as asn1 from "../../crypto/asn1";
import * as sha from "../../crypto/sha";
import {
AbstractHandshakeIdentityHandler,
HandshakeCommandHandler,
IdentitifyType,
Identity
} from "tc-shared/profiles/Identity";
import {arrayBufferBase64, base64_encode_ab, str2ab8} from "tc-shared/utils/buffers";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler";
} from "../../profiles/Identity";
import {arrayBufferBase64, base64_encode_ab, str2ab8} from "../../utils/buffers";
import {AbstractServerConnection} from "../../connection/ConnectionBase";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {HandshakeIdentityHandler} from "../../connection/HandshakeHandler";
export namespace CryptoHelper {
export function base64_url_encode(str){

View File

@ -1,4 +1,4 @@
import {settings, Settings} from "tc-shared/settings";
import {settings, Settings} from "../../settings";
import * as loader from "tc-loader";
import * as fidentity from "./TeaForumIdentity";
import * as log from "../../log";

View File

@ -1,8 +1,8 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import * as log from "./log";
import {LogCategory} from "./log";
import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import {Registry} from "tc-shared/events";
import {Registry} from "./events";
type ConfigValueTypes = boolean | number | string | object;
type ConfigValueTypeNames = "boolean" | "number" | "string" | "object";

View File

@ -1,7 +1,7 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {Settings, settings} from "tc-shared/settings";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import * as log from "../log";
import {LogCategory} from "../log";
import {Settings, settings} from "../settings";
import {ConnectionHandler} from "../ConnectionHandler";
import * as sbackend from "tc-backend/audio/sounds";
export enum Sound {

View File

@ -1,5 +1,5 @@
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {LogCategory} from "./log";
import * as log from "./log";
enum CloseCodes {
UNSET = 3000,

View File

@ -1,10 +1,10 @@
//https://regex101.com/r/YQbfcX/2
//static readonly URL_REGEX = /^(?<hostname>([a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]{2,63})(?:\/(?<path>(?:[^\s?]+)?)(?:\?(?<query>\S+))?)?$/gm;
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {Settings, settings} from "tc-shared/settings";
import {renderMarkdownAsBBCode} from "tc-shared/text/markdown";
import {escapeBBCode} from "tc-shared/text/bbcode";
import * as log from "../log";
import {LogCategory} from "../log";
import {Settings, settings} from "../settings";
import {renderMarkdownAsBBCode} from "../text/markdown";
import {escapeBBCode} from "../text/bbcode";
const URL_REGEX = /^(([a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]{2,63})(?:\/((?:[^\s?]+)?)(?:\?(\S+))?)?$/gm;
function process_urls(message: string) : string {

View File

@ -1,5 +1,5 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import * as log from "../log";
import {LogCategory} from "../log";
import {
CodeToken, Env, FenceToken, HeadingOpenToken,
ImageToken,
@ -10,7 +10,7 @@ import {
TextToken,
Token
} from "remarkable/lib";
import {escapeBBCode} from "tc-shared/text/bbcode";
import {escapeBBCode} from "../text/bbcode";
const { Remarkable } = require("remarkable");
export class MD2BBCodeRenderer {

View File

@ -1,28 +1,28 @@
import {ChannelTree} from "./ChannelTree";
import {ClientEntry, ClientEvents} from "./Client";
import * as log from "tc-shared/log";
import {LogCategory, LogType} from "tc-shared/log";
import {PermissionType} from "tc-shared/permission/PermissionType";
import {settings, Settings} from "tc-shared/settings";
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
import {MenuEntryType} from "tc-shared/ui/elements/ContextMenu";
import {Sound} from "tc-shared/sound/Sounds";
import {createErrorModal, createInfoModal, createInputModal} from "tc-shared/ui/elements/Modal";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import * as log from "../log";
import {LogCategory, LogType} from "../log";
import {PermissionType} from "../permission/PermissionType";
import {settings, Settings} from "../settings";
import * as contextmenu from "../ui/elements/ContextMenu";
import {MenuEntryType} from "../ui/elements/ContextMenu";
import {Sound} from "../sound/Sounds";
import {createErrorModal, createInfoModal, createInputModal} from "../ui/elements/Modal";
import {CommandResult} from "../connection/ServerConnectionDeclaration";
import * as htmltags from "../ui/htmltags";
import {hashPassword} from "tc-shared/utils/helpers";
import {openChannelInfo} from "tc-shared/ui/modal/ModalChannelInfo";
import {createChannelModal} from "tc-shared/ui/modal/ModalCreateChannel";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {hashPassword} from "../utils/helpers";
import {openChannelInfo} from "../ui/modal/ModalChannelInfo";
import {createChannelModal} from "../ui/modal/ModalCreateChannel";
import {formatMessage} from "../ui/frames/chat";
import * as React from "react";
import {Registry} from "tc-shared/events";
import {Registry} from "../events";
import {ChannelTreeEntry, ChannelTreeEntryEvents} from "./ChannelTreeEntry";
import {ChannelEntryView as ChannelEntryView} from "../ui/tree/Channel";
import {spawnFileTransferModal} from "tc-shared/ui/modal/transfer/ModalFileTransfer";
import {ViewReasonId} from "tc-shared/ConnectionHandler";
import {EventChannelData} from "tc-shared/ui/frames/log/Definitions";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {spawnFileTransferModal} from "../ui/modal/transfer/ModalFileTransfer";
import {ViewReasonId} from "../ConnectionHandler";
import {EventChannelData} from "../ui/frames/log/Definitions";
import {ErrorCode} from "../connection/ErrorCode";
export enum ChannelType {
PERMANENT,

View File

@ -1,4 +1,4 @@
import {Registry} from "tc-shared/events";
import {Registry} from "../events";
export interface ChannelTreeEntryEvents {
notify_select_state_change: { selected: boolean },

View File

@ -1,35 +1,35 @@
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
import {Registry} from "tc-shared/events";
import * as contextmenu from "../ui/elements/ContextMenu";
import {Registry} from "../events";
import {ChannelTree} from "./ChannelTree";
import * as log from "tc-shared/log";
import {LogCategory, logInfo, LogType} from "tc-shared/log";
import {Settings, settings} from "tc-shared/settings";
import {Sound} from "tc-shared/sound/Sounds";
import {Group, GroupManager, GroupTarget, GroupType} from "tc-shared/permission/GroupManager";
import PermissionType from "tc-shared/permission/PermissionType";
import {createErrorModal, createInputModal} from "tc-shared/ui/elements/Modal";
import * as htmltags from "tc-shared/ui/htmltags";
import {CommandResult, PlaylistSong} from "tc-shared/connection/ServerConnectionDeclaration";
import * as log from "../log";
import {LogCategory, logInfo, LogType} from "../log";
import {Settings, settings} from "../settings";
import {Sound} from "../sound/Sounds";
import {Group, GroupManager, GroupTarget, GroupType} from "../permission/GroupManager";
import PermissionType from "../permission/PermissionType";
import {createErrorModal, createInputModal} from "../ui/elements/Modal";
import * as htmltags from "../ui/htmltags";
import {CommandResult, PlaylistSong} from "../connection/ServerConnectionDeclaration";
import {ChannelEntry} from "./Channel";
import {ConnectionHandler, ViewReasonId} from "tc-shared/ConnectionHandler";
import {createServerGroupAssignmentModal} from "tc-shared/ui/modal/ModalGroupAssignment";
import {openClientInfo} from "tc-shared/ui/modal/ModalClientInfo";
import {spawnBanClient} from "tc-shared/ui/modal/ModalBanClient";
import {spawnChangeLatency} from "tc-shared/ui/modal/ModalChangeLatency";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
import * as hex from "tc-shared/crypto/hex";
import {ConnectionHandler, ViewReasonId} from "../ConnectionHandler";
import {createServerGroupAssignmentModal} from "../ui/modal/ModalGroupAssignment";
import {openClientInfo} from "../ui/modal/ModalClientInfo";
import {spawnBanClient} from "../ui/modal/ModalBanClient";
import {spawnChangeLatency} from "../ui/modal/ModalChangeLatency";
import {formatMessage} from "../ui/frames/chat";
import {spawnYesNo} from "../ui/modal/ModalYesNo";
import * as hex from "../crypto/hex";
import {ClientEntry as ClientEntryView} from "../ui/tree/Client";
import * as React from "react";
import {ChannelTreeEntry, ChannelTreeEntryEvents} from "./ChannelTreeEntry";
import {spawnClientVolumeChange, spawnMusicBotVolumeChange} from "tc-shared/ui/modal/ModalChangeVolumeNew";
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
import {EventClient, EventType} from "tc-shared/ui/frames/log/Definitions";
import {W2GPluginCmdHandler} from "tc-shared/video-viewer/W2GPlugin";
import {global_client_actions} from "tc-shared/events/GlobalEvents";
import {spawnClientVolumeChange, spawnMusicBotVolumeChange} from "../ui/modal/ModalChangeVolumeNew";
import {spawnPermissionEditorModal} from "../ui/modal/permission/ModalPermissionEditor";
import {EventClient, EventType} from "../ui/frames/log/Definitions";
import {W2GPluginCmdHandler} from "../video-viewer/W2GPlugin";
import {global_client_actions} from "../events/GlobalEvents";
import {ClientIcon} from "svg-sprites/client-icons";
import {VoiceClient} from "tc-shared/voice/VoiceClient";
import {VoicePlayerEvents, VoicePlayerState} from "tc-shared/voice/VoicePlayer";
import {VoiceClient} from "../voice/VoiceClient";
import {VoicePlayerEvents, VoicePlayerState} from "../voice/VoicePlayer";
export enum ClientType {
CLIENT_VOICE,

View File

@ -1,22 +1,22 @@
import {ChannelTree} from "./ChannelTree";
import {Settings, settings} from "tc-shared/settings";
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
import * as log from "tc-shared/log";
import {LogCategory, LogType} from "tc-shared/log";
import {Sound} from "tc-shared/sound/Sounds";
import * as bookmarks from "tc-shared/bookmarks";
import {spawnInviteEditor} from "tc-shared/ui/modal/ModalInvite";
import {openServerInfo} from "tc-shared/ui/modal/ModalServerInfo";
import {createServerModal} from "tc-shared/ui/modal/ModalServerEdit";
import {spawnIconSelect} from "tc-shared/ui/modal/ModalIconSelect";
import {spawnAvatarList} from "tc-shared/ui/modal/ModalAvatarList";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {connection_log} from "tc-shared/ui/modal/ModalConnect";
import {Settings, settings} from "../settings";
import * as contextmenu from "../ui/elements/ContextMenu";
import * as log from "../log";
import {LogCategory, LogType} from "../log";
import {Sound} from "../sound/Sounds";
import * as bookmarks from "../bookmarks";
import {spawnInviteEditor} from "../ui/modal/ModalInvite";
import {openServerInfo} from "../ui/modal/ModalServerInfo";
import {createServerModal} from "../ui/modal/ModalServerEdit";
import {spawnIconSelect} from "../ui/modal/ModalIconSelect";
import {spawnAvatarList} from "../ui/modal/ModalAvatarList";
import {server_connections} from "../ui/frames/connection_handlers";
import {connection_log} from "../ui/modal/ModalConnect";
import * as top_menu from "../ui/frames/MenuBar";
import {control_bar_instance} from "tc-shared/ui/frames/control-bar";
import {control_bar_instance} from "../ui/frames/control-bar";
import { ServerEntry as ServerEntryView } from "../ui/tree/Server";
import * as React from "react";
import {Registry} from "tc-shared/events";
import {Registry} from "../events";
import {ChannelTreeEntry, ChannelTreeEntryEvents} from "./ChannelTreeEntry";
export class ServerProperties {

View File

@ -1,6 +1,6 @@
import {Settings, settings} from "tc-shared/settings";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {Settings, settings} from "../../settings";
import {LogCategory} from "../../log";
import * as log from "../../log";
declare global {
interface JQuery<TElement = HTMLElement> {

View File

@ -1,6 +1,6 @@
import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import {KeyCode} from "tc-shared/PPTListener";
import {KeyCode} from "../../PPTListener";
import * as $ from "jquery";
export enum ElementType {

View File

@ -1,4 +1,4 @@
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import * as tooltip from "../../ui/elements/Tooltip";
export interface SliderOptions {
min_value?: number;

View File

@ -1,4 +1,4 @@
import {spawnBookmarkModal} from "tc-shared/ui/modal/ModalBookmarks";
import {spawnBookmarkModal} from "../../ui/modal/ModalBookmarks";
import {
add_server_to_bookmarks,
Bookmark,
@ -6,25 +6,25 @@ import {
BookmarkType,
boorkmak_connect,
DirectoryBookmark
} from "tc-shared/bookmarks";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {Sound} from "tc-shared/sound/Sounds";
import {spawnConnectModal} from "tc-shared/ui/modal/ModalConnect";
import {createErrorModal, createInfoModal, createInputModal} from "tc-shared/ui/elements/Modal";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {PermissionType} from "tc-shared/permission/PermissionType";
import {openBanList} from "tc-shared/ui/modal/ModalBanList";
import {spawnQueryManage} from "tc-shared/ui/modal/ModalQueryManage";
import {spawnQueryCreate} from "tc-shared/ui/modal/ModalQuery";
import {spawnSettingsModal} from "tc-shared/ui/modal/ModalSettings";
import {spawnAbout} from "tc-shared/ui/modal/ModalAbout";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
} from "../../bookmarks";
import {ConnectionHandler} from "../../ConnectionHandler";
import {Sound} from "../../sound/Sounds";
import {spawnConnectModal} from "../../ui/modal/ModalConnect";
import {createErrorModal, createInfoModal, createInputModal} from "../../ui/elements/Modal";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {PermissionType} from "../../permission/PermissionType";
import {openBanList} from "../../ui/modal/ModalBanList";
import {spawnQueryManage} from "../../ui/modal/ModalQueryManage";
import {spawnQueryCreate} from "../../ui/modal/ModalQuery";
import {spawnSettingsModal} from "../../ui/modal/ModalSettings";
import {spawnAbout} from "../../ui/modal/ModalAbout";
import {server_connections} from "../../ui/frames/connection_handlers";
import * as loader from "tc-loader";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {control_bar_instance} from "tc-shared/ui/frames/control-bar";
import {icon_cache_loader, IconManager, LocalIcon} from "tc-shared/file/Icons";
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
import {spawnModalCssVariableEditor} from "tc-shared/ui/modal/css-editor/Controller";
import {formatMessage} from "../../ui/frames/chat";
import {control_bar_instance} from "../../ui/frames/control-bar";
import {icon_cache_loader, IconManager, LocalIcon} from "../../file/Icons";
import {spawnPermissionEditorModal} from "../../ui/modal/permission/ModalPermissionEditor";
import {spawnModalCssVariableEditor} from "../../ui/modal/css-editor/Controller";
export interface HRItem { }

View File

@ -1,6 +1,6 @@
import {LogCategory} from "tc-shared/log";
import {settings, Settings} from "tc-shared/settings";
import * as log from "tc-shared/log";
import {LogCategory} from "../../log";
import {settings, Settings} from "../../settings";
import * as log from "../../log";
import * as loader from "tc-loader";
export enum ChatType {

View File

@ -1,14 +1,14 @@
/* the bar on the right with the chats (Channel & Client) */
import {ClientEntry, MusicClientEntry} from "tc-shared/tree/Client";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {ChannelEntry} from "tc-shared/tree/Channel";
import {ServerEntry} from "tc-shared/tree/Server";
import {openMusicManage} from "tc-shared/ui/modal/ModalMusicManage";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {ClientInfo} from "tc-shared/ui/frames/side/client_info";
import {MusicInfo} from "tc-shared/ui/frames/side/music_info";
import {ConversationManager} from "tc-shared/ui/frames/side/ConversationManager";
import {PrivateConversationManager} from "tc-shared/ui/frames/side/PrivateConversationManager";
import {ClientEntry, MusicClientEntry} from "../../tree/Client";
import {ConnectionHandler} from "../../ConnectionHandler";
import {ChannelEntry} from "../../tree/Channel";
import {ServerEntry} from "../../tree/Server";
import {openMusicManage} from "../../ui/modal/ModalMusicManage";
import {formatMessage} from "../../ui/frames/chat";
import {ClientInfo} from "../../ui/frames/side/client_info";
import {MusicInfo} from "../../ui/frames/side/music_info";
import {ConversationManager} from "../../ui/frames/side/ConversationManager";
import {PrivateConversationManager} from "../../ui/frames/side/PrivateConversationManager";
export enum InfoFrameMode {
NONE = "none",

View File

@ -1,7 +1,7 @@
import {ConnectionHandler, DisconnectReason} from "tc-shared/ConnectionHandler";
import {Settings, settings} from "tc-shared/settings";
import {ConnectionHandler, DisconnectReason} from "../../ConnectionHandler";
import {Settings, settings} from "../../settings";
import * as top_menu from "./MenuBar";
import {Registry} from "tc-shared/events";
import {Registry} from "../../events";
export let server_connections: ConnectionManager;
export function initialize() {

View File

@ -1,7 +1,7 @@
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {settings, Settings} from "tc-shared/settings";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {ConnectionHandler} from "../../ConnectionHandler";
import {settings, Settings} from "../../settings";
import {LogCategory} from "../../log";
import * as log from "../../log";
export class Hostbanner {
readonly html_tag: JQuery<HTMLElement>;

View File

@ -1,7 +1,7 @@
import {PermissionInfo} from "tc-shared/permission/PermissionManager";
import {ViewReasonId} from "tc-shared/ConnectionHandler";
import {PermissionInfo} from "../../../permission/PermissionManager";
import {ViewReasonId} from "../../../ConnectionHandler";
import * as React from "react";
import {ServerEventLog} from "tc-shared/ui/frames/log/ServerEventLog";
import {ServerEventLog} from "../../../ui/frames/log/ServerEventLog";
export enum EventType {
CONNECTION_BEGIN = "connection.begin",

View File

@ -1,5 +1,5 @@
import {EventType} from "tc-shared/ui/frames/log/Definitions";
import {Settings, settings} from "tc-shared/settings";
import {EventType} from "../../../ui/frames/log/Definitions";
import {Settings, settings} from "../../../settings";
const focusDefaultStatus = {};
focusDefaultStatus[EventType.CLIENT_POKE_RECEIVED] = true;

View File

@ -2,14 +2,14 @@ import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import * as log from "../../../log";
import {LogCategory} from "../../../log";
import {EventClient, EventServerAddress, EventType, TypeInfo} from "tc-shared/ui/frames/log/Definitions";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {renderBBCodeAsText} from "tc-shared/text/bbcode";
import {format_time} from "tc-shared/ui/frames/chat";
import {ViewReasonId} from "tc-shared/ConnectionHandler";
import {findLogDispatcher} from "tc-shared/ui/frames/log/DispatcherLog";
import {formatDate} from "tc-shared/MessageFormatter";
import {Settings, settings} from "tc-shared/settings";
import {EventClient, EventServerAddress, EventType, TypeInfo} from "../../../ui/frames/log/Definitions";
import {server_connections} from "../../../ui/frames/connection_handlers";
import {renderBBCodeAsText} from "../../../text/bbcode";
import {format_time} from "../../../ui/frames/chat";
import {ViewReasonId} from "../../../ConnectionHandler";
import {findLogDispatcher} from "../../../ui/frames/log/DispatcherLog";
import {formatDate} from "../../../MessageFormatter";
import {Settings, settings} from "../../../settings";
export type DispatcherLog<T extends keyof TypeInfo> = (data: TypeInfo[T], handlerId: string, eventType: T) => void;

View File

@ -3,15 +3,15 @@ import {
ChatEventMessage, ChatHistoryState, ChatMessage,
ChatState, ConversationHistoryResponse,
ConversationUIEvents
} from "tc-shared/ui/frames/side/ConversationDefinitions";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {EventHandler, Registry} from "tc-shared/events";
import {preprocessChatMessageForSend} from "tc-shared/text/chat";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {tra} from "tc-shared/i18n/localize";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
} from "../../../ui/frames/side/ConversationDefinitions";
import {ConnectionHandler} from "../../../ConnectionHandler";
import {EventHandler, Registry} from "../../../events";
import {preprocessChatMessageForSend} from "../../../text/chat";
import {CommandResult} from "../../../connection/ServerConnectionDeclaration";
import * as log from "../../../log";
import {LogCategory} from "../../../log";
import {tra} from "../../../i18n/localize";
import {ErrorCode} from "../../../connection/ErrorCode";
export const kMaxChatFrameMessageSize = 50; /* max 100 messages, since the server does not support more than 100 messages queried at once */

View File

@ -1,21 +1,21 @@
import * as React from "react";
import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import {EventHandler, Registry} from "tc-shared/events";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ServerCommand} from "tc-shared/connection/ConnectionBase";
import {Settings} from "tc-shared/settings";
import {traj} from "tc-shared/i18n/localize";
import {createErrorModal} from "tc-shared/ui/elements/Modal";
import {ConnectionHandler, ConnectionState} from "../../../ConnectionHandler";
import {EventHandler, Registry} from "../../../events";
import * as log from "../../../log";
import {LogCategory} from "../../../log";
import {CommandResult} from "../../../connection/ServerConnectionDeclaration";
import {ServerCommand} from "../../../connection/ConnectionBase";
import {Settings} from "../../../settings";
import {traj} from "../../../i18n/localize";
import {createErrorModal} from "../../../ui/elements/Modal";
import ReactDOM = require("react-dom");
import {
ChatMessage, ConversationHistoryResponse,
ConversationUIEvents
} from "tc-shared/ui/frames/side/ConversationDefinitions";
import {ConversationPanel} from "tc-shared/ui/frames/side/ConversationUI";
} from "../../../ui/frames/side/ConversationDefinitions";
import {ConversationPanel} from "../../../ui/frames/side/ConversationUI";
import {AbstractChat, AbstractChatManager, kMaxChatFrameMessageSize} from "./AbstractConversion";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {ErrorCode} from "../../../connection/ErrorCode";
const kSuccessQueryThrottle = 5 * 1000;
const kErrorQueryThrottle = 30 * 1000;

View File

@ -1,4 +1,4 @@
import {ConversationUIEvents} from "tc-shared/ui/frames/side/ConversationDefinitions";
import {ConversationUIEvents} from "../../../ui/frames/side/ConversationDefinitions";
export type PrivateConversationInfo = {
nickname: string;

View File

@ -1,8 +1,8 @@
import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {ChatEvent} from "tc-shared/ui/frames/side/ConversationDefinitions";
import * as log from "../../../log";
import {LogCategory} from "../../../log";
import {ChatEvent} from "../../../ui/frames/side/ConversationDefinitions";
const clientUniqueId2StoreName = uniqueId => "conversation-" + uniqueId;

View File

@ -1,23 +1,23 @@
import {ClientEntry} from "tc-shared/tree/Client";
import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import {EventHandler, Registry} from "tc-shared/events";
import {ClientEntry} from "../../../tree/Client";
import {ConnectionHandler, ConnectionState} from "../../../ConnectionHandler";
import {EventHandler, Registry} from "../../../events";
import {
PrivateConversationInfo,
PrivateConversationUIEvents
} from "tc-shared/ui/frames/side/PrivateConversationDefinitions";
} from "../../../ui/frames/side/PrivateConversationDefinitions";
import * as ReactDOM from "react-dom";
import * as React from "react";
import {PrivateConversationsPanel} from "tc-shared/ui/frames/side/PrivateConversationUI";
import {PrivateConversationsPanel} from "../../../ui/frames/side/PrivateConversationUI";
import {
ChatEvent,
ChatMessage,
ConversationHistoryResponse,
ConversationUIEvents
} from "tc-shared/ui/frames/side/ConversationDefinitions";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {queryConversationEvents, registerConversationEvent} from "tc-shared/ui/frames/side/PrivateConversationHistory";
import {AbstractChat, AbstractChatManager} from "tc-shared/ui/frames/side/AbstractConversion";
} from "../../../ui/frames/side/ConversationDefinitions";
import * as log from "../../../log";
import {LogCategory} from "../../../log";
import {queryConversationEvents, registerConversationEvent} from "../../../ui/frames/side/PrivateConversationHistory";
import {AbstractChat, AbstractChatManager} from "../../../ui/frames/side/AbstractConversion";
export type OutOfViewClient = {
nickname: string,

View File

@ -1,11 +1,11 @@
import {GroupManager} from "tc-shared/permission/GroupManager";
import {Frame, FrameContent} from "tc-shared/ui/frames/chat_frame";
import {openClientInfo} from "tc-shared/ui/modal/ModalClientInfo";
import * as htmltags from "tc-shared/ui/htmltags";
import {GroupManager} from "../../../permission/GroupManager";
import {Frame, FrameContent} from "../../../ui/frames/chat_frame";
import {openClientInfo} from "../../../ui/modal/ModalClientInfo";
import * as htmltags from "../../../ui/htmltags";
import * as image_preview from "../image_preview";
import * as i18nc from "tc-shared/i18n/country";
import {ClientEntry, LocalClientEntry} from "tc-shared/tree/Client";
import {format_online_time} from "tc-shared/utils/TimeUtils";
import * as i18nc from "../../../i18n/country";
import {ClientEntry, LocalClientEntry} from "../../../tree/Client";
import {format_online_time} from "../../../utils/TimeUtils";
export class ClientInfo {
readonly handle: Frame;

View File

@ -1,12 +1,12 @@
import {Frame, FrameContent} from "tc-shared/ui/frames/chat_frame";
import {LogCategory} from "tc-shared/log";
import {CommandResult, PlaylistSong} from "tc-shared/connection/ServerConnectionDeclaration";
import {createErrorModal, createInputModal} from "tc-shared/ui/elements/Modal";
import * as log from "tc-shared/log";
import {Frame, FrameContent} from "../../../ui/frames/chat_frame";
import {LogCategory} from "../../../log";
import {CommandResult, PlaylistSong} from "../../../connection/ServerConnectionDeclaration";
import {createErrorModal, createInputModal} from "../../../ui/elements/Modal";
import * as log from "../../../log";
import * as image_preview from "../image_preview";
import {Registry} from "tc-shared/events";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {ClientEvents, MusicClientEntry, SongInfo} from "tc-shared/tree/Client";
import {Registry} from "../../../events";
import {ErrorCode} from "../../../connection/ErrorCode";
import {ClientEvents, MusicClientEntry, SongInfo} from "../../../tree/Client";
export interface MusicSidebarEvents {
"open": {}, /* triggers when frame should be shown */

View File

@ -1,10 +1,10 @@
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {ChannelEntry} from "tc-shared/tree/Channel";
import {ClientEntry} from "tc-shared/tree/Client";
import {htmlEscape} from "tc-shared/ui/frames/chat";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {guid} from "tc-shared/crypto/uid";
import * as log from "../log";
import {LogCategory} from "../log";
import {ChannelEntry} from "../tree/Channel";
import {ClientEntry} from "../tree/Client";
import {htmlEscape} from "../ui/frames/chat";
import {server_connections} from "../ui/frames/connection_handlers";
import {guid} from "../crypto/uid";
let mouse_coordinates: {x: number, y: number} = {x: 0, y: 0};

View File

@ -1,7 +1,7 @@
import * as loader from "tc-loader";
import * as moment from "moment";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import * as log from "../log";
import {LogCategory} from "../log";
export function setupJSRender() : boolean {
if(!$.views) {

View File

@ -1,6 +1,6 @@
import {createModal} from "tc-shared/ui/elements/Modal";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {createModal} from "../../ui/elements/Modal";
import * as log from "../../log";
import {LogCategory} from "../../log";
function format_date(date: number) {
const d = new Date(date);
@ -29,7 +29,7 @@ export function spawnAbout() {
connectModal.htmlTag.find(".modal-body").addClass("modal-about");
connectModal.open();
if(__build.target !== "web") {
if (__build.target !== "web") {
(window as any).native.client_version().then(version => {
connectModal.htmlTag.find(".version-client").text(version);
}).catch(error => {

View File

@ -1,7 +1,7 @@
//TODO: Test if we could render this image and not only the browser by knowing the type.
import {createErrorModal, createModal} from "tc-shared/ui/elements/Modal";
import {tra} from "tc-shared/i18n/localize";
import {arrayBufferBase64} from "tc-shared/utils/buffers";
import {createErrorModal, createModal} from "../../ui/elements/Modal";
import {tra} from "../../i18n/localize";
import {arrayBufferBase64} from "../../utils/buffers";
export function spawnAvatarUpload(callback_data: (data: ArrayBuffer | undefined | null) => any) {
const modal = createModal({
@ -20,7 +20,7 @@ export function spawnAvatarUpload(callback_data: (data: ArrayBuffer | undefined
});
modal.htmlTag.find(".button-delete").on('click', () => {
if(_data_submitted)
if (_data_submitted)
return;
_data_submitted = true;
modal.close();
@ -54,7 +54,7 @@ export function spawnAvatarUpload(callback_data: (data: ArrayBuffer | undefined
(async () => {
const data = await read_file(input_node.files[0]);
if(!data.startsWith("data:image/")) {
if (!data.startsWith("data:image/")) {
console.error(tr("Failed to load file %s: Invalid data media type (%o)"), input_node.files[0].name, data);
createErrorModal(tr("Icon upload failed"), tra("Failed to select avatar {}.<br>File is not an image", input_node.files[0].name)).open();
return;

View File

@ -1,15 +1,15 @@
import {createErrorModal, createModal} from "tc-shared/ui/elements/Modal";
import {LogCategory} from "tc-shared/log";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {base64_encode_ab} from "tc-shared/utils/buffers";
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
import {ClientEntry} from "tc-shared/tree/Client";
import * as log from "tc-shared/log";
import {createErrorModal, createModal} from "../../ui/elements/Modal";
import * as log from "../../log";
import {LogCategory} from "../../log";
import {ConnectionHandler} from "../../ConnectionHandler";
import {base64_encode_ab} from "../../utils/buffers";
import {spawnYesNo} from "../../ui/modal/ModalYesNo";
import {ClientEntry} from "../../tree/Client";
import * as moment from "moment";
const avatar_to_uid = (id: string) => {
const buffer = new Uint8Array(id.length / 2);
for(let index = 0; index < id.length; index += 2) {
for (let index = 0; index < id.length; index += 2) {
const upper_nibble = id.charCodeAt(index) - 97;
const lower_nibble = id.charCodeAt(index + 1) - 97;
buffer[index / 2] = (upper_nibble << 4) | lower_nibble;
@ -18,7 +18,7 @@ const avatar_to_uid = (id: string) => {
};
export const human_file_size = (size: number) => {
if(size < 1000)
if (size < 1000)
return size + "B";
const exp = Math.floor(Math.log2(size) / 10);
return (size / Math.pow(1024, exp)).toFixed(2) + 'KMGTPE'.charAt(exp - 1) + "iB";
@ -48,7 +48,7 @@ export function spawnAvatarList(client: ConnectionHandler) {
const set_selected_avatar = (unique_id: string, avatar_id: string, size: number) => {
button_download.prop("disabled", true);
callback_download = undefined;
if(!unique_id) {
if (!unique_id) {
overlay_no_user.show();
return;
}
@ -93,7 +93,7 @@ export function spawnAvatarList(client: ConnectionHandler) {
callback_delete = () => {
spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this avatar?"), result => {
if(result) {
if (result) {
createErrorModal(tr("Not implemented"), tr("Avatar delete hasn't implemented yet")).open();
//TODO Implement avatar delete
}
@ -108,8 +108,8 @@ export function spawnAvatarList(client: ConnectionHandler) {
list_entries.empty();
client.fileManager.requestFileList("/").then(files => {
const username_resolve: {[unique_id: string]:((name:string) => any)[]} = {};
for(const entry of files) {
const username_resolve: { [unique_id: string]: ((name: string) => any)[] } = {};
for (const entry of files) {
const avatar_id = entry.name.substr('avatar_'.length);
const unique_id = avatar_to_uid(avatar_id);
@ -122,7 +122,7 @@ export function spawnAvatarList(client: ConnectionHandler) {
(username_resolve[unique_id] || (username_resolve[unique_id] = [])).push(name => {
const tag_username = tag.find(".column-username").empty();
if(name) {
if (name) {
tag_username.append(ClientEntry.chatTag(0, name, unique_id, false));
} else {
tag_username.text("unknown");
@ -138,15 +138,15 @@ export function spawnAvatarList(client: ConnectionHandler) {
});
}
if(container_list.hasScrollBar())
if (container_list.hasScrollBar())
container_list.addClass("scrollbar");
client.serverConnection.command_helper.getInfoFromUniqueId(...Object.keys(username_resolve)).then(result => {
for(const info of result) {
for (const info of result) {
username_resolve[info.clientUniqueId].forEach(e => e(info.clientNickname));
delete username_resolve[info.clientUniqueId];
}
for(const uid of Object.keys(username_resolve)) {
for (const uid of Object.keys(username_resolve)) {
(username_resolve[uid] || []).forEach(e => e(undefined));
}
}).catch(error => {
@ -160,8 +160,10 @@ export function spawnAvatarList(client: ConnectionHandler) {
});
};
button_download.on('click', () => (callback_download || (() => {}))());
button_delete.on('click', () => (callback_delete || (() => {}))());
button_download.on('click', () => (callback_download || (() => {
}))());
button_delete.on('click', () => (callback_delete || (() => {
}))());
setTimeout(() => update_avatar_list(), 250);
modal.open();
}

View File

@ -1,13 +1,14 @@
import PermissionType from "tc-shared/permission/PermissionType";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {createModal} from "tc-shared/ui/elements/Modal";
import {duration_data} from "tc-shared/ui/modal/ModalBanList";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import PermissionType from "../../permission/PermissionType";
import {ConnectionHandler} from "../../ConnectionHandler";
import {createModal} from "../../ui/elements/Modal";
import {duration_data} from "../../ui/modal/ModalBanList";
import * as tooltip from "../../ui/elements/Tooltip";
export type BanEntry = {
name?: string;
unique_id: string;
}
export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | BanEntry[], callback: (data: {
length: number,
reason: string,
@ -58,8 +59,8 @@ export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | Ba
const disabled = input_duration_type.prop("disabled");
input_duration_value.prop("disabled", type === "perm" || disabled).firstParent(".input-boxed").toggleClass("disabled", type === "perm" || disabled);
if(type !== "perm") {
if(input_duration_value.attr("x-saved-value")) {
if (type !== "perm") {
if (input_duration_value.attr("x-saved-value")) {
input_duration_value.val(parseInt(input_duration_value.attr("x-saved-value")));
input_duration_value.attr("x-saved-value", null);
}
@ -68,18 +69,18 @@ export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | Ba
const max = parseInt(selected_option.attr("duration-max"));
input_duration_value.attr("max", max);
if((value > max && max != -1) || value < 1) {
if ((value > max && max != -1) || value < 1) {
input_duration_value.firstParent(".input-boxed").addClass("is-invalid");
} else {
input_duration_value.firstParent(".input-boxed").removeClass("is-invalid");
}
if(max != -1)
if (max != -1)
tooltip_duration_max.html(tr("You're allowed to ban a maximum of ") + "<b>" + max + " " + duration_data[type][max == 1 ? "1-text" : "text"] + "</b>");
else
tooltip_duration_max.html(tr("You're allowed to ban <b>permanent</b>."));
} else {
if(value && !Number.isNaN(value))
if (value && !Number.isNaN(value))
input_duration_value.attr("x-saved-value", value);
input_duration_value.attr("placeholder", tr("for ever")).val(null);
tooltip_duration_max.html(tr("You're allowed to ban <b>permanent</b>."));
@ -88,15 +89,17 @@ export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | Ba
};
/* initialize ban time */
Promise.resolve(max_ban_time).catch(error => { /* TODO: Error handling? */ return 0; }).then(max_time => {
Promise.resolve(max_ban_time).catch(error => { /* TODO: Error handling? */
return 0;
}).then(max_time => {
let unlimited = max_time == 0 || max_time == -1;
if(unlimited || typeof(max_time) === "undefined") max_time = 0;
if (unlimited || typeof (max_time) === "undefined") max_time = 0;
for(const value of Object.keys(duration_data)) {
for (const value of Object.keys(duration_data)) {
input_duration_type.find("option[value='" + value + "']")
.prop("disabled", !unlimited && max_time >= duration_data[value].scale)
.attr("duration-scale", duration_data[value].scale)
.attr("duration-max", unlimited ? -1 : Math.floor(max_time / duration_data[value].scale));
.attr("duration-max", unlimited ? -1 : Math.floor(max_time / duration_data[value].scale));
}
input_duration_type.find("option[value='perm']")
@ -114,7 +117,7 @@ export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | Ba
const input = container_reason.find("textarea");
const insert_tag = (open: string, close: string) => {
if(input.prop("disabled"))
if (input.prop("disabled"))
return;
const node = input[0] as HTMLTextAreaElement;
@ -145,7 +148,7 @@ export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | Ba
{
button_cancel.on('click', event => modal.close());
button_ok.on('click', event => {
const duration = input_duration_type.val() === "perm" ? 0 : (1000 * parseInt(input_duration_type.find("option[value='" + input_duration_type.val() + "']").attr("duration-scale")) * parseInt(input_duration_value.val() as string));
const duration = input_duration_type.val() === "perm" ? 0 : (1000 * parseInt(input_duration_type.find("option[value='" + input_duration_type.val() + "']").attr("duration-scale")) * parseInt(input_duration_value.val() as string));
modal.close();
callback({

View File

@ -1,15 +1,15 @@
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {createErrorModal, createInfoModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {SingleCommandHandler} from "tc-shared/connection/ConnectionBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import PermissionType from "tc-shared/permission/PermissionType";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import * as htmltags from "tc-shared/ui/htmltags";
import {format_time, formatMessage} from "tc-shared/ui/frames/chat";
import {ConnectionHandler} from "../../ConnectionHandler";
import {createErrorModal, createInfoModal, createModal, Modal} from "../../ui/elements/Modal";
import {SingleCommandHandler} from "../../connection/ConnectionBase";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import PermissionType from "../../permission/PermissionType";
import * as log from "../../log";
import {LogCategory} from "../../log";
import * as tooltip from "../../ui/elements/Tooltip";
import * as htmltags from "../../ui/htmltags";
import {format_time, formatMessage} from "../../ui/frames/chat";
import * as moment from "moment";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {ErrorCode} from "../../connection/ErrorCode";
export function openBanList(client: ConnectionHandler) {
let modal: Modal;
@ -22,7 +22,7 @@ export function openBanList(client: ConnectionHandler) {
const json = command.arguments;
let bans: BanEntry[] = [];
for(const entry of json) {
for (const entry of json) {
bans.push({
server_id: parseInt(entry["sid"]),
banid: parseInt(entry["banid"]),
@ -55,7 +55,7 @@ export function openBanList(client: ConnectionHandler) {
const json = command.arguments;
let triggers: TriggerEntry[] = [];
for(const entry of json) {
for (const entry of json) {
triggers.push({
unique_id: entry["client_unique_identifier"],
client_nickname: entry["client_nickname"],
@ -86,20 +86,20 @@ export function openBanList(client: ConnectionHandler) {
};
Promise.all([
client.serverConnection.send_command("banlist", { sid: 0 }, {process_result: false}).catch(error => {
client.serverConnection.send_command("banlist", {sid: 0}, {process_result: false}).catch(error => {
//TODO: May lookup for permissions
}),
client.serverConnection.send_command("banlist").catch(async error => {
if(error instanceof CommandResult)
if(error.id === ErrorCode.DATABASE_EMPTY_RESULT)
if (error instanceof CommandResult)
if (error.id === ErrorCode.DATABASE_EMPTY_RESULT)
return;
throw error;
})
]).then(() => {
if(_callback_bans) resolve();
if (_callback_bans) resolve();
cleanup();
}).catch(error => {
if(_callback_bans) reject(error);
if (_callback_bans) reject(error);
cleanup();
});
});
@ -118,18 +118,18 @@ export function openBanList(client: ConnectionHandler) {
};
const data = {banid: ban.ban_id};
if(typeof ban.server_id !== "undefined")
if (typeof ban.server_id !== "undefined")
data["sid"] = ban.server_id;
client.serverConnection.send_command("bantriggerlist", data).catch(async error => {
if(error instanceof CommandResult)
if(error.id === ErrorCode.DATABASE_EMPTY_RESULT)
if (error instanceof CommandResult)
if (error.id === ErrorCode.DATABASE_EMPTY_RESULT)
return;
throw error;
}).then(() => {
if(_callback_triggers) resolve();
if (_callback_triggers) resolve();
cleanup();
}).catch(error => {
if(_callback_triggers) reject(error);
if (_callback_triggers) reject(error);
cleanup();
});
});
@ -153,27 +153,33 @@ export function openBanList(client: ConnectionHandler) {
add_ban(entry: BanEntry): Promise<void> {
const data = {};
if(entry.ip) data["ip"] = entry.ip;
if(entry.name) data["name"] = entry.name;
if(entry.unique_id) data["uid"] = entry.unique_id;
if(entry.hardware_id) data["hwid"] = entry.hardware_id;
if(entry.reason) data["banreason"] = entry.reason;
if(entry.timestamp_expire) data["time"] = Math.floor((entry.timestamp_expire - entry.timestamp_created) / 1000);
if(typeof(entry.server_id) === "number") data["sid"] = entry.server_id;
if (entry.ip) data["ip"] = entry.ip;
if (entry.name) data["name"] = entry.name;
if (entry.unique_id) data["uid"] = entry.unique_id;
if (entry.hardware_id) data["hwid"] = entry.hardware_id;
if (entry.reason) data["banreason"] = entry.reason;
if (entry.timestamp_expire) data["time"] = Math.floor((entry.timestamp_expire - entry.timestamp_created) / 1000);
if (typeof (entry.server_id) === "number") data["sid"] = entry.server_id;
return client.serverConnection.send_command("banadd", data).then(e => { if(!e.success) throw e; });
return client.serverConnection.send_command("banadd", data).then(e => {
if (!e.success) throw e;
});
},
edit_ban(data: any): Promise<void> {
return client.serverConnection.send_command("banedit", data).then(e => { if(!e.success) throw e; });
return client.serverConnection.send_command("banedit", data).then(e => {
if (!e.success) throw e;
});
},
delete_ban(entry_id, server_id): Promise<void> {
const data = {
banid: entry_id
};
if(typeof(server_id) === "number")
if (typeof (server_id) === "number")
data["sid"] = server_id;
return client.serverConnection.send_command("bandel", data).then(e => { if(!e.success) throw e; });
return client.serverConnection.send_command("bandel", data).then(e => {
if (!e.success) throw e;
});
}
};
@ -232,16 +238,21 @@ interface TriggerEntry {
}
interface BanListController {
request_list(callback_bans: (entries: BanEntry[]) => any) : Promise<void>;
request_trigger_list(ban: {ban_id: number, server_id: number | undefined}, callback_triggers: (entries: TriggerEntry[]) => any) : Promise<void>;
request_list(callback_bans: (entries: BanEntry[]) => any): Promise<void>;
max_bantime() : Promise<number>;
permission_edit() : Promise<boolean[]>;
permission_add() : Promise<boolean[]>;
request_trigger_list(ban: { ban_id: number, server_id: number | undefined }, callback_triggers: (entries: TriggerEntry[]) => any): Promise<void>;
add_ban(entry: BanEntry) : Promise<void>;
edit_ban(data: any) : Promise<void>;
delete_ban(entry_id: number, server_id: number | undefined) : Promise<void>;
max_bantime(): Promise<number>;
permission_edit(): Promise<boolean[]>;
permission_add(): Promise<boolean[]>;
add_ban(entry: BanEntry): Promise<void>;
edit_ban(data: any): Promise<void>;
delete_ban(entry_id: number, server_id: number | undefined): Promise<void>;
}
//Note: This object must be sorted (from shortest to longest)!
@ -272,7 +283,7 @@ export const duration_data = {
},
};
function generate_dom(controller: BanListController) : JQuery {
function generate_dom(controller: BanListController): JQuery {
const template = $("#tmpl_ban_list").renderTag();
let callback_ban_filter: ((text: string, flag_own: boolean, highlight_own: boolean) => boolean)[] = [];
@ -312,17 +323,17 @@ function generate_dom(controller: BanListController) : JQuery {
controller.permission_add().then(result => permission_add = result).catch(error => {
log.error(LogCategory.CLIENT, tr("Failed to query ban add permissions: %o"), error);
}).then(() => {
if(permission_add[0] !== permission_add[1]) {
if (permission_add[0] !== permission_add[1]) {
const input_global = container_add.find(".group-global input");
input_global.prop("checked", permission_add[1]).prop("disabled", true).firstParent(".checkbox").addClass("disabled");
} else if(!permission_add[0])
} else if (!permission_add[0])
container_add_no_permissions.show();
});
controller.permission_edit().then(result => permission_edit = result).catch(error => {
log.error(LogCategory.CLIENT, tr("Failed to query ban edit permissions: %o"), error);
}).then(() => {
if(selected_ban) update_edit_window(false);
if (selected_ban) update_edit_window(false);
});
/* category switch */
@ -342,7 +353,7 @@ function generate_dom(controller: BanListController) : JQuery {
});
category_edit.on('click', event => {
if(!selected_ban) return;
if (!selected_ban) return;
container_add.addClass("hidden");
category_add.removeClass("selected");
@ -377,7 +388,7 @@ function generate_dom(controller: BanListController) : JQuery {
);
tag.on('click', event => {
if(selected_ban === entry || event.isDefaultPrevented()) return;
if (selected_ban === entry || event.isDefaultPrevented()) return;
selected_ban = entry;
container_ban_entries.find(".entry.selected").removeClass("selected");
@ -391,19 +402,19 @@ function generate_dom(controller: BanListController) : JQuery {
controller.delete_ban(entry.banid, entry.server_id).then(() => {
tag.css({opacity: 1}).animate({opacity: 0}, 250, () => tag.animate({"max-height": 0}, 250, () => tag.remove()));
if(entry === selected_ban) {
if (entry === selected_ban) {
selected_ban = undefined;
update_edit_window(false);
}
}).catch(error => {
log.error(LogCategory.CLIENT, tr("Failed to delete ban: %o"), error);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS ? "no permissions" : error.extra_message || error.message;
createErrorModal(tr("Failed to delete ban"), formatMessage(tr("Failed to delete ban. {:br:}Error: {}"), error)).open();
});
});
if(selected) {
if (selected) {
selected_ban = entry;
update_edit_window(false);
}
@ -415,12 +426,12 @@ function generate_dom(controller: BanListController) : JQuery {
(entry.ip || "").toLowerCase() + " " +
(entry.hardware_id || "").toLowerCase();
callback_ban_filter.push((text, flag_own, highlight_own) => {
if(text && lower_mesh.indexOf(text) == -1) {
if (text && lower_mesh.indexOf(text) == -1) {
tag.hide();
return false;
}
if(flag_own && !entry.flag_own) {
if (flag_own && !entry.flag_own) {
tag.hide();
return false;
}
@ -445,7 +456,7 @@ function generate_dom(controller: BanListController) : JQuery {
let bans = [];
controller.request_list(_bans => bans.push(..._bans)).then(() => {
if(bans.length) {
if (bans.length) {
container_ban_entries.append(...bans.map(e => build_ban_entry(e, e.banid === selected_ban)));
container_ban_entries_empty.hide();
} else {
@ -454,7 +465,7 @@ function generate_dom(controller: BanListController) : JQuery {
update_ban_filter();
}).catch(error => {
log.info(LogCategory.CLIENT, tr("Failed to update ban list: %o"), error);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS ? tr("no permissions") : error.extra_message || error.message;
container_ban_entries_error.show().find("a").text(tr("Failed to receive banlist: ") + error);
container_ban_entries_empty.hide();
@ -475,7 +486,7 @@ function generate_dom(controller: BanListController) : JQuery {
let cause_hwid = !cause_ip && !!selected_ban.hardware_id && selected_ban.hardware_id.toLowerCase() === (entry.hardware_id || "").toLowerCase();
/* we guess that IP is the cause because we dont see the IP and there is no other reason */
if(!cause_name && !cause_uid && !cause_ip && !cause_hwid && entry.connection_ip === "hidden")
if (!cause_name && !cause_uid && !cause_ip && !cause_hwid && entry.connection_ip === "hidden")
cause_ip = true;
const time_str = moment(entry.timestamp).format('DD.MM.YYYY hh:mm');
@ -498,7 +509,7 @@ function generate_dom(controller: BanListController) : JQuery {
time_str + " " +
entry.timestamp;
callback_trigger_filter.push(text => {
if(text && lower_mesh.indexOf(text) == -1) {
if (text && lower_mesh.indexOf(text) == -1) {
tag.hide();
return false;
}
@ -522,7 +533,7 @@ function generate_dom(controller: BanListController) : JQuery {
ban_id: selected_ban.banid,
server_id: selected_ban.server_id
}, _triggers => triggers.push(..._triggers)).then(() => {
if(triggers.length) {
if (triggers.length) {
container_trigger_entries.append(...triggers.sort((a, b) => b.timestamp - a.timestamp).map(e => build_trigger_entry(e)));
container_trigger_entries_empty.hide();
} else {
@ -532,7 +543,7 @@ function generate_dom(controller: BanListController) : JQuery {
update_trigger_filter();
}).catch(error => {
log.info(LogCategory.CLIENT, tr("Failed to update trigger list: %o"), error);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS ? tr("no permissions") : error.extra_message || error.message;
container_trigger_entries_error.show().find("a").text(tr("Failed to receive trigger list: ") + error);
container_trigger_entries_empty.hide();
@ -562,7 +573,7 @@ function generate_dom(controller: BanListController) : JQuery {
{
//TODO: Check if in regex mode or not
const value = input_name.val() as string || "";
if(value.length > 255) {
if (value.length > 255) {
_input_invalid = true;
input_name.firstParent(".input-boxed").addClass("is-invalid");
} else {
@ -574,7 +585,7 @@ function generate_dom(controller: BanListController) : JQuery {
{
//TODO: Check if in regex mode or not
const value = input_ip.val() as string || "";
if(value.length > 255) {
if (value.length > 255) {
_input_invalid = true;
input_ip.firstParent(".input-boxed").addClass("is-invalid");
} else {
@ -586,11 +597,11 @@ function generate_dom(controller: BanListController) : JQuery {
{
const value = input_uid.val() as string || "";
try {
if(value && atob(value).length != 20) throw "";
if (value && atob(value).length != 20) throw "";
_criteria_set = _criteria_set || !!value;
input_uid.firstParent(".input-boxed").removeClass("is-invalid");
} catch(e) {
} catch (e) {
_input_invalid = true;
input_uid.firstParent(".input-boxed").addClass("is-invalid");
}
@ -598,7 +609,7 @@ function generate_dom(controller: BanListController) : JQuery {
{
const value = input_hwid.val() as string || "";
if(value.length > 255) {
if (value.length > 255) {
_input_invalid = true;
input_hwid.firstParent(".input-boxed").addClass("is-invalid");
} else {
@ -609,7 +620,7 @@ function generate_dom(controller: BanListController) : JQuery {
{
const value = input_reason.val() as string || "";
if(value.length > 512) {
if (value.length > 512) {
_input_invalid = true;
input_reason.firstParent(".input-boxed").addClass("is-invalid");
} else {
@ -623,8 +634,8 @@ function generate_dom(controller: BanListController) : JQuery {
const disabled = input_duration_type.prop("disabled");
input_duration_value.prop("disabled", type === "perm" || disabled).firstParent(".input-boxed").toggleClass("disabled", type === "perm" || disabled);
if(type !== "perm") {
if(input_duration_value.attr("x-saved-value")) {
if (type !== "perm") {
if (input_duration_value.attr("x-saved-value")) {
input_duration_value.val(parseInt(input_duration_value.attr("x-saved-value")));
input_duration_value.attr("x-saved-value", null);
}
@ -633,19 +644,19 @@ function generate_dom(controller: BanListController) : JQuery {
const max = parseInt(selected_option.attr("duration-max"));
input_duration_value.attr("max", max);
if((value > max && max != -1) || value < 1) {
if ((value > max && max != -1) || value < 1) {
_input_invalid = true;
input_duration_value.firstParent(".input-boxed").addClass("is-invalid");
} else {
input_duration_value.firstParent(".input-boxed").removeClass("is-invalid");
}
if(max != -1)
if (max != -1)
tooltip_duration_max.html(tr("You're allowed to ban a maximum of ") + "<b>" + max + " " + duration_data[type][max == 1 ? "1-text" : "text"] + "</b>");
else
tooltip_duration_max.html(tr("You're allowed to ban <b>permanent</b>."));
} else {
if(value && !Number.isNaN(value))
if (value && !Number.isNaN(value))
input_duration_value.attr("x-saved-value", value);
input_duration_value.attr("placeholder", tr("for ever")).val(null);
tooltip_duration_max.html(tr("You're allowed to ban <b>permanent</b>."));
@ -656,15 +667,17 @@ function generate_dom(controller: BanListController) : JQuery {
};
/* initialize ban time */
controller.max_bantime().catch(error => { /* TODO: Error handling? */ return 0; }).then(max_time => {
controller.max_bantime().catch(error => { /* TODO: Error handling? */
return 0;
}).then(max_time => {
let unlimited = max_time == 0 || max_time == -1;
if(unlimited) max_time = 0;
if (unlimited) max_time = 0;
for(const value of Object.keys(duration_data)) {
for (const value of Object.keys(duration_data)) {
input_duration_type.find("option[value='" + value + "']")
.prop("disabled", !unlimited && max_time >= duration_data[value].scale)
.attr("duration-scale", duration_data[value].scale)
.attr("duration-max", unlimited ? -1 : Math.floor(max_time / duration_data[value].scale));
.attr("duration-max", unlimited ? -1 : Math.floor(max_time / duration_data[value].scale));
}
input_duration_type.find("option[value='perm']")
@ -706,7 +719,7 @@ function generate_dom(controller: BanListController) : JQuery {
input_hwid.val(selected_ban ? selected_ban.hardware_id : null).prop("disabled", !editable).firstParent(".input-boxed").toggleClass("disabled", !editable);
input_reason.val(selected_ban ? selected_ban.reason : null).prop("disabled", !editable).firstParent(".input-boxed").toggleClass("disabled", !editable);
input_interpret.find("option").eq(selected_ban && typeof(selected_ban.name_type) === "number" ? selected_ban.name_type : 2).prop("selected", true).prop("disabled", !editable).firstParent(".input-boxed").toggleClass("disabled", !editable);
input_interpret.find("option").eq(selected_ban && typeof (selected_ban.name_type) === "number" ? selected_ban.name_type : 2).prop("selected", true).prop("disabled", !editable).firstParent(".input-boxed").toggleClass("disabled", !editable);
label_enforcement_count.text((selected_ban ? selected_ban.enforcements : 0) || 0);
button_enforcement_list.prop("disabled", !selected_ban || selected_ban.enforcements == 0);
@ -715,17 +728,17 @@ function generate_dom(controller: BanListController) : JQuery {
input_duration_type.prop("disabled", !editable).firstParent(".input-boxed").toggleClass("disabled", !editable);
input_duration_value.prop("disabled", !editable).firstParent(".input-boxed").toggleClass("disabled", !editable);
if(selected_ban) {
if(selected_ban.timestamp_expire > selected_ban.timestamp_created) {
if (selected_ban) {
if (selected_ban.timestamp_expire > selected_ban.timestamp_created) {
const duration = Math.ceil((selected_ban.timestamp_expire - selected_ban.timestamp_created) / 1000);
const periods = Object.keys(duration_data);
let index;
for(index = 0; index < periods.length; index++) {
if(duration_data[periods[index]].scale > duration + 1 || ((duration + 1) % duration_data[periods[index]].scale) > 1.9)
for (index = 0; index < periods.length; index++) {
if (duration_data[periods[index]].scale > duration + 1 || ((duration + 1) % duration_data[periods[index]].scale) > 1.9)
break;
}
if(index > 0) index--;
if (index > 0) index--;
input_duration_type.find("option[value='" + periods[index] + "']").prop("selected", true);
input_duration_value.val(Math.ceil(duration / duration_data[periods[index]].scale));
tooltip_duration_detailed.text($.spawn("div").append(...formatMessage(tr("The ban lasts for exact {}."), format_time(duration * 1000, "never"))).text());
@ -737,7 +750,7 @@ function generate_dom(controller: BanListController) : JQuery {
}
container_creator.empty();
if(selected_ban) {
if (selected_ban) {
container_creator.append(
htmltags.generate_client_object({
client_id: 0,
@ -748,7 +761,7 @@ function generate_dom(controller: BanListController) : JQuery {
);
}
if(switch_to)
if (switch_to)
category_edit.trigger('click');
};
@ -757,26 +770,26 @@ function generate_dom(controller: BanListController) : JQuery {
const data = {banid: selected_ban.banid};
if(input_ip.val() != selected_ban.ip)
if (input_ip.val() != selected_ban.ip)
data["ip"] = input_ip.val();
if(input_name.val() != selected_ban.name)
if (input_name.val() != selected_ban.name)
data["name"] = input_name.val();
if(input_uid.val() != selected_ban.unique_id)
if (input_uid.val() != selected_ban.unique_id)
data["uid"] = input_uid.val();
if(input_hwid.val() != selected_ban.hardware_id)
if (input_hwid.val() != selected_ban.hardware_id)
data["hwid"] = input_hwid.val();
if(input_reason.val() != selected_ban.reason)
if (input_reason.val() != selected_ban.reason)
data["banreason"] = input_reason.val();
if(input_reason.val() != selected_ban.reason)
if (input_reason.val() != selected_ban.reason)
data["reason"] = input_reason.val();
const duration = input_duration_type.val() === "perm" ? 0 : (1000 * parseInt(input_duration_type.find("option[value='" + input_duration_type.val() + "']").attr("duration-scale")) * parseInt(input_duration_value.val() as string));
if(selected_ban.timestamp_expire > 0 ? (selected_ban.timestamp_expire - selected_ban.timestamp_created != duration) : duration != 0)
const duration = input_duration_type.val() === "perm" ? 0 : (1000 * parseInt(input_duration_type.find("option[value='" + input_duration_type.val() + "']").attr("duration-scale")) * parseInt(input_duration_value.val() as string));
if (selected_ban.timestamp_expire > 0 ? (selected_ban.timestamp_expire - selected_ban.timestamp_created != duration) : duration != 0)
data["time"] = Math.floor(duration / 1000);
controller.edit_ban(data).then(() => {
@ -788,7 +801,7 @@ function generate_dom(controller: BanListController) : JQuery {
createInfoModal(tr("Ban successfully edited"), tr("Your ban has been successfully edited.")).open();
}).catch(error => {
log.error(LogCategory.CLIENT, tr("Failed to edited ban: %o"), error);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS ? "no permissions" : error.extra_message || error.message;
createErrorModal(tr("Failed to edited ban"), formatMessage(tr("Failed to edited ban. {:br:}Error: {}"), error)).open();
});
@ -814,34 +827,34 @@ function generate_dom(controller: BanListController) : JQuery {
const input_duration_type = tag.find(".group-duration select");
button_apply.on('click', event => {
if(!button_apply_state[0] || button_apply_state_index != 0) return;
if (!button_apply_state[0] || button_apply_state_index != 0) return;
const data: BanEntry = {
banid: 0,
enforcements: 0,
} as any;
if(input_global.prop('checked'))
if (input_global.prop('checked'))
data.server_id = 0;
if(input_ip.val())
if (input_ip.val())
data.ip = input_ip.val() as any;
if(input_name.val())
if (input_name.val())
data.name = input_name.val() as any;
if(input_uid.val())
if (input_uid.val())
data.unique_id = input_uid.val() as any;
if(input_hwid.val())
if (input_hwid.val())
data.hardware_id = input_hwid.val() as any;
if(input_reason.val())
if (input_reason.val())
data.reason = input_reason.val() as any;
data.timestamp_created = Date.now();
data.timestamp_expire = input_duration_type.val() === "perm" ? 0 : (data.timestamp_created + 1000 * parseInt(input_duration_type.find("option[value='" + input_duration_type.val() + "']").attr("duration-scale")) * parseInt(input_duration_value.val() as string));
data.timestamp_expire = input_duration_type.val() === "perm" ? 0 : (data.timestamp_created + 1000 * parseInt(input_duration_type.find("option[value='" + input_duration_type.val() + "']").attr("duration-scale")) * parseInt(input_duration_value.val() as string));
//TODO: input_interpret (Currently not supported by TeaSpeak)
controller.add_ban(data).then(() => {
@ -856,7 +869,7 @@ function generate_dom(controller: BanListController) : JQuery {
createInfoModal(tr("Ban successfully added"), tr("Your ban has been successfully added.")).open();
}).catch(error => {
log.error(LogCategory.CLIENT, tr("Failed to add ban: %o"), error);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS ? "no permissions" : error.extra_message || error.message;
createErrorModal(tr("Failed to add ban"), formatMessage(tr("Failed to add ban. {:br:}Error: {}"), error)).open();
});
@ -875,11 +888,11 @@ function generate_dom(controller: BanListController) : JQuery {
const flag_hightlight_own = option_hightlight_own.prop('checked');
let count = 0;
for(const entry of callback_ban_filter)
if(entry(text, flag_show_own, flag_hightlight_own))
for (const entry of callback_ban_filter)
if (entry(text, flag_show_own, flag_hightlight_own))
count++;
if(callback_ban_filter.length != 0) {
if(count > 0)
if (callback_ban_filter.length != 0) {
if (count > 0)
container_ban_entries_empty.hide();
else
container_ban_entries_empty.show().find("a").text(tr("No bans found"));
@ -897,11 +910,11 @@ function generate_dom(controller: BanListController) : JQuery {
const text = (input_filter.val() as string || "").toLowerCase();
let count = 0;
for(const entry of callback_trigger_filter)
if(entry(text))
for (const entry of callback_trigger_filter)
if (entry(text))
count++;
if(callback_trigger_filter.length != 0) {
if(count > 0)
if (callback_trigger_filter.length != 0) {
if (count > 0)
container_trigger_entries_empty.hide();
else
container_trigger_entries_empty.show().find("a").text(tr("No trigger events found"));

View File

@ -1,4 +1,4 @@
import {createInputModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {createInputModal, createModal, Modal} from "../../ui/elements/Modal";
import {
Bookmark,
bookmarks,
@ -9,25 +9,25 @@ import {
delete_bookmark,
DirectoryBookmark,
save_bookmark
} from "tc-shared/bookmarks";
import {connection_log, Regex} from "tc-shared/ui/modal/ModalConnect";
import {profiles} from "tc-shared/profiles/ConnectionProfile";
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
import {Settings, settings} from "tc-shared/settings";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import * as i18nc from "tc-shared/i18n/country";
import {formatMessage} from "tc-shared/ui/frames/chat";
} from "../../bookmarks";
import {connection_log, Regex} from "../../ui/modal/ModalConnect";
import {profiles} from "../../profiles/ConnectionProfile";
import {spawnYesNo} from "../../ui/modal/ModalYesNo";
import {Settings, settings} from "../../settings";
import * as log from "../../log";
import {LogCategory} from "../../log";
import * as i18nc from "../../i18n/country";
import {formatMessage} from "../../ui/frames/chat";
import * as top_menu from "../frames/MenuBar";
import {control_bar_instance} from "tc-shared/ui/frames/control-bar";
import {icon_cache_loader, IconManager} from "tc-shared/file/Icons";
import {control_bar_instance} from "../../ui/frames/control-bar";
import {icon_cache_loader, IconManager} from "../../file/Icons";
export function spawnBookmarkModal() {
let modal: Modal;
modal = createModal({
header: tr("Manage bookmarks"),
body: () => {
let template = $("#tmpl_manage_bookmarks").renderTag({ });
let template = $("#tmpl_manage_bookmarks").renderTag({});
let selected_bookmark: Bookmark | DirectoryBookmark | undefined;
const button_delete = template.find(".button-delete");
@ -61,11 +61,11 @@ export function spawnBookmarkModal() {
};
const update_connect_info = () => {
if(selected_bookmark && selected_bookmark.type === BookmarkType.ENTRY) {
if (selected_bookmark && selected_bookmark.type === BookmarkType.ENTRY) {
const entry = selected_bookmark as Bookmark;
const history = connection_log.history().find(e => e.address.hostname === entry.server_properties.server_address && e.address.port === entry.server_properties.server_port);
if(history) {
if (history) {
label_server_name.text(history.name);
label_server_region.empty().append(
$.spawn("div").addClass("country flag-" + history.country.toLowerCase()),
@ -99,12 +99,12 @@ export function spawnBookmarkModal() {
input_server_address.prop("disabled", !selected_bookmark || selected_bookmark.type !== BookmarkType.ENTRY);
input_server_password.prop("disabled", !selected_bookmark || selected_bookmark.type !== BookmarkType.ENTRY);
if(selected_bookmark) {
if (selected_bookmark) {
input_bookmark_name.val(selected_bookmark.display_name);
label_bookmark_name.text(selected_bookmark.display_name);
}
if(selected_bookmark && selected_bookmark.type === BookmarkType.ENTRY) {
if (selected_bookmark && selected_bookmark.type === BookmarkType.ENTRY) {
const entry = selected_bookmark as Bookmark;
const address = entry.server_properties.server_address + (entry.server_properties.server_port == 9987 ? "" : (" " + entry.server_properties.server_port));
@ -112,7 +112,7 @@ export function spawnBookmarkModal() {
input_server_address.val(address);
let profile = input_connect_profile.find("option[value='" + entry.connect_profile + "']");
if(profile.length == 0) {
if (profile.length == 0) {
log.warn(LogCategory.GENERAL, tr("Failed to find bookmark profile %s. Displaying default one."), entry.connect_profile);
profile = input_connect_profile.find("option[value=default]");
}
@ -136,7 +136,7 @@ export function spawnBookmarkModal() {
update_selected();
const hide_links: boolean[] = [];
const build_entry = (entry: Bookmark | DirectoryBookmark, sibling_data: {first: boolean; last: boolean;}, index: number) => {
const build_entry = (entry: Bookmark | DirectoryBookmark, sibling_data: { first: boolean; last: boolean; }, index: number) => {
let container = $.spawn("div")
.addClass(entry.type === BookmarkType.ENTRY ? "bookmark" : "directory")
.addClass(index > 0 ? "linked" : "")
@ -169,7 +169,7 @@ export function spawnBookmarkModal() {
container.appendTo(container_bookmarks);
container.on('click', event => {
if(selected_bookmark === entry)
if (selected_bookmark === entry)
return;
selected_bookmark = entry;
@ -178,7 +178,7 @@ export function spawnBookmarkModal() {
update_buttons();
update_selected();
});
if(entry.unique_id === _current_selected)
if (entry.unique_id === _current_selected)
container.trigger('click');
hide_links.push(sibling_data.last);
@ -203,7 +203,7 @@ export function spawnBookmarkModal() {
.text("")
.css("display", "none")
);
for(const profile of profiles()) {
for (const profile of profiles()) {
input_connect_profile.append(
$.spawn("option")
.attr("value", profile.id)
@ -215,11 +215,11 @@ export function spawnBookmarkModal() {
/* buttons */
{
button_delete.on('click', event => {
if(!selected_bookmark) return;
if (!selected_bookmark) return;
if(selected_bookmark.type === BookmarkType.DIRECTORY && (selected_bookmark as DirectoryBookmark).content.length > 0) {
if (selected_bookmark.type === BookmarkType.DIRECTORY && (selected_bookmark as DirectoryBookmark).content.length > 0) {
spawnYesNo(tr("Are you sure"), tr("Do you really want to delete this non empty directory?"), answer => {
if(answer) {
if (answer) {
delete_bookmark(selected_bookmark);
save_bookmark(selected_bookmark);
update_bookmark_list(undefined);
@ -236,7 +236,7 @@ export function spawnBookmarkModal() {
createInputModal(tr("Enter a folder name"), tr("Enter the folder name"), text => {
return true;
}, result => {
if(result) {
if (result) {
const mark = create_bookmark_directory(
selected_bookmark ?
selected_bookmark.type === BookmarkType.DIRECTORY ?
@ -255,7 +255,7 @@ export function spawnBookmarkModal() {
createInputModal(tr("Enter a bookmark name"), tr("Enter the bookmark name"), text => {
return true;
}, result => {
if(result) {
if (result) {
const mark = create_bookmark(result as string,
selected_bookmark ?
selected_bookmark.type === BookmarkType.DIRECTORY ?
@ -285,8 +285,8 @@ export function spawnBookmarkModal() {
button_duplicate.on('click', event => {
createInputModal(tr("Enter a bookmark name"), tr("Enter the bookmark name for the duplicate"), text => text.length > 0, result => {
if(result) {
if(!selected_bookmark) return;
if (result) {
if (!selected_bookmark) return;
const original = selected_bookmark as Bookmark;
const mark = create_bookmark(result as string,
@ -307,7 +307,7 @@ export function spawnBookmarkModal() {
const valid = name.length > 3;
input_bookmark_name.firstParent(".input-boxed").toggleClass("is-invalid", !valid);
if(event.type === "change" && valid) {
if (event.type === "change" && valid) {
selected_bookmark.display_name = name;
label_bookmark_name.text(name);
save_bookmark(selected_bookmark);
@ -319,11 +319,11 @@ export function spawnBookmarkModal() {
const valid = !!address.match(Regex.IP_V4) || !!address.match(Regex.IP_V6) || !!address.match(Regex.DOMAIN);
input_server_address.firstParent(".input-boxed").toggleClass("is-invalid", !valid);
if(valid) {
if (valid) {
const entry = selected_bookmark as Bookmark;
let _v6_end = address.indexOf(']');
let idx = address.lastIndexOf(':');
if(idx != -1 && idx > _v6_end) {
if (idx != -1 && idx > _v6_end) {
entry.server_properties.server_port = parseInt(address.substr(idx + 1));
entry.server_properties.server_address = address.substr(0, idx);
} else {
@ -346,7 +346,7 @@ export function spawnBookmarkModal() {
input_connect_profile.on('change', event => {
const id = input_connect_profile.val() as string;
const profile = profiles().find(e => e.id === id);
if(profile) {
if (profile) {
(selected_bookmark as Bookmark).connect_profile = id;
save_bookmark(selected_bookmark);
} else {
@ -364,8 +364,8 @@ export function spawnBookmarkModal() {
_focus_listener = event => {
_focused = false;
let element = event.target as HTMLElement;
while(element) {
if(element === container_bookmarks[0]) {
while (element) {
if (element === container_bookmarks[0]) {
_focused = true;
break;
}
@ -374,11 +374,11 @@ export function spawnBookmarkModal() {
};
_key_listener = event => {
if(!_focused) return;
if (!_focused) return;
if(event.key.toLowerCase() === "arrowdown") {
if (event.key.toLowerCase() === "arrowdown") {
container_bookmarks.find(".selected").next().trigger('click');
} else if(event.key.toLowerCase() === "arrowup") {
} else if (event.key.toLowerCase() === "arrowup") {
container_bookmarks.find(".selected").prev().trigger('click');
}
};
@ -404,7 +404,7 @@ export function spawnBookmarkModal() {
modal.htmlTag.dividerfy().find(".modal-body").addClass("modal-bookmarks");
modal.close_listener.push(() => {
control_bar_instance()?.events().fire("update_state", { state: "bookmarks" });
control_bar_instance()?.events().fire("update_state", {state: "bookmarks"});
top_menu.rebuild_bookmarks();
});

View File

@ -1,8 +1,8 @@
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import {ClientEntry} from "tc-shared/tree/Client";
import {Slider, sliderfy} from "tc-shared/ui/elements/Slider";
import * as htmltags from "tc-shared/ui/htmltags";
import {VoicePlayerLatencySettings} from "tc-shared/voice/VoicePlayer";
import {createModal, Modal} from "../../ui/elements/Modal";
import {ClientEntry} from "../../tree/Client";
import {Slider, sliderfy} from "../../ui/elements/Slider";
import * as htmltags from "../../ui/htmltags";
import {VoicePlayerLatencySettings} from "../../voice/VoicePlayer";
let modalInstance: Modal;
export function spawnChangeLatency(client: ClientEntry, current: VoicePlayerLatencySettings, reset: () => VoicePlayerLatencySettings, apply: (settings: VoicePlayerLatencySettings) => void, callback_flush?: () => any) {

View File

@ -1,13 +1,14 @@
//TODO: Use the max limit!
import {sliderfy} from "tc-shared/ui/elements/Slider";
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import {ClientEntry} from "tc-shared/tree/Client";
import * as htmltags from "tc-shared/ui/htmltags";
import {sliderfy} from "../../ui/elements/Slider";
import {createModal, Modal} from "../../ui/elements/Modal";
import {ClientEntry} from "../../tree/Client";
import * as htmltags from "../../ui/htmltags";
let modal: Modal;
export function spawnChangeVolume(client: ClientEntry, local: boolean, current: number, max: number | undefined, callback: (number) => void) {
if(modal) modal.close();
if (modal) modal.close();
let new_value: number;
modal = createModal({
@ -29,7 +30,7 @@ export function spawnChangeVolume(client: ClientEntry, local: boolean, current:
container_value.html((value == 100 ? "&plusmn;" : value > 100 ? "+" : "-") + number + "%");
new_value = value / 100;
if(local) callback(new_value);
if (local) callback(new_value);
};
set_value(current * 100);
@ -45,7 +46,7 @@ export function spawnChangeVolume(client: ClientEntry, local: boolean, current:
slider_tag.on('change', event => set_value(parseInt(slider_tag.attr("value"))));
tag.find(".button-save").on('click', event => {
if(typeof(new_value) !== "undefined") callback(new_value);
if (typeof (new_value) !== "undefined") callback(new_value);
modal.close();
});

View File

@ -1,8 +1,8 @@
import {createInfoModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {ChannelEntry} from "tc-shared/tree/Channel";
import {copy_to_clipboard} from "tc-shared/utils/helpers";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {createInfoModal, createModal, Modal} from "../../ui/elements/Modal";
import {ChannelEntry} from "../../tree/Channel";
import {copy_to_clipboard} from "../../utils/helpers";
import * as tooltip from "../../ui/elements/Tooltip";
import {formatMessage} from "../../ui/frames/chat";
export function openChannelInfo(channel: ChannelEntry) {
let modal: Modal;
@ -39,12 +39,13 @@ export function openChannelInfo(channel: ChannelEntry) {
}
declare const xbbcode;
function apply_channel_description(container: JQuery, channel: ChannelEntry) {
const container_value = container.find(".value");
const container_no_value = container.find(".no-value");
channel.getChannelDescription().then(description => {
if(description) {
if (description) {
const result = xbbcode.parse(description, {});
container_value[0].innerHTML = result.build_html();
container_no_value.hide();
@ -71,9 +72,9 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
/* channel type */
{
const tag = container.find(".channel-type .value").empty();
if(channel.properties.channel_flag_permanent)
if (channel.properties.channel_flag_permanent)
tag.text(tr("Permanent"));
else if(channel.properties.channel_flag_semi_permanent)
else if (channel.properties.channel_flag_semi_permanent)
tag.text(tr("Semi permanent"));
else
//TODO: Channel delete delay!
@ -83,12 +84,12 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
/* chat mode */
{
const tag = container.find(".chat-mode .value").empty();
if(channel.properties.channel_flag_conversation_private || channel.properties.channel_flag_password) {
if (channel.properties.channel_flag_conversation_private || channel.properties.channel_flag_password) {
tag.text(tr("Private"));
} else {
if(channel.properties.channel_conversation_history_length == -1)
if (channel.properties.channel_conversation_history_length == -1)
tag.text(tr("Public; Semi permanent message saving"));
else if(channel.properties.channel_conversation_history_length == 0)
else if (channel.properties.channel_conversation_history_length == 0)
tag.text(tr("Public; Permanent message saving"));
else
tag.append(formatMessage(tr("Public; Saving last {} messages"), channel.properties.channel_conversation_history_length));
@ -99,13 +100,13 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
{
const tag = container.find(".current-clients .value").empty();
if(channel.flag_subscribed) {
if (channel.flag_subscribed) {
const current = channel.clients().length;
let channel_limit = tr("Unlimited");
if(!channel.properties.channel_flag_maxclients_unlimited)
if (!channel.properties.channel_flag_maxclients_unlimited)
channel_limit = "" + channel.properties.channel_maxclients;
else if(!channel.properties.channel_flag_maxfamilyclients_unlimited) {
if(channel.properties.channel_maxfamilyclients >= 0)
else if (!channel.properties.channel_flag_maxfamilyclients_unlimited) {
if (channel.properties.channel_maxfamilyclients >= 0)
channel_limit = "" + channel.properties.channel_maxfamilyclients;
}
@ -126,9 +127,9 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
const tag = container.find(".audio-encrypted .value").empty();
const mode = channel.channelTree.server.properties.virtualserver_codec_encryption_mode;
let appendix;
if(mode == 1)
if (mode == 1)
appendix = tr("Overridden by the server with Unencrypted!");
else if(mode == 2)
else if (mode == 2)
appendix = tr("Overridden by the server with Encrypted!");
tag.html((channel.properties.channel_codec_is_unencrypted ? tr("Unencrypted") : tr("Encrypted")) + (appendix ? "<br>" + appendix : ""))
@ -137,7 +138,7 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
/* flag password */
{
const tag = container.find(".flag-password .value").empty();
if(channel.properties.channel_flag_password)
if (channel.properties.channel_flag_password)
tag.text(tr("Yes"));
else
tag.text(tr("No"));
@ -147,7 +148,7 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
{
const container_tag = container.find(".topic");
const tag = container_tag.find(".value").empty();
if(channel.properties.channel_topic) {
if (channel.properties.channel_topic) {
container_tag.show();
tag.text(channel.properties.channel_topic);
} else {

View File

@ -1,13 +1,14 @@
import {ClientConnectionInfo, ClientEntry} from "tc-shared/tree/Client";
import PermissionType from "tc-shared/permission/PermissionType";
import {createInfoModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {copy_to_clipboard} from "tc-shared/utils/helpers";
import * as i18nc from "tc-shared/i18n/country";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import {ClientConnectionInfo, ClientEntry} from "../../tree/Client";
import PermissionType from "../../permission/PermissionType";
import {createInfoModal, createModal, Modal} from "../../ui/elements/Modal";
import {copy_to_clipboard} from "../../utils/helpers";
import * as i18nc from "../../i18n/country";
import * as tooltip from "../../ui/elements/Tooltip";
import * as moment from "moment";
import {format_number, network} from "tc-shared/ui/frames/chat";
import {format_number, network} from "../../ui/frames/chat";
type InfoUpdateCallback = (info: ClientConnectionInfo) => any;
export function openClientInfo(client: ClientEntry) {
let modal: Modal;
let update_callbacks: InfoUpdateCallback[] = [];
@ -64,31 +65,31 @@ const TIME_WEEK = 7 * TIME_DAY;
function format_time(time: number, default_value: string) {
let result = "";
if(time > TIME_WEEK) {
if (time > TIME_WEEK) {
const amount = Math.floor(time / TIME_WEEK);
result += " " + amount + " " + (amount > 1 ? tr("Weeks") : tr("Week"));
time -= amount * TIME_WEEK;
}
if(time > TIME_DAY) {
if (time > TIME_DAY) {
const amount = Math.floor(time / TIME_DAY);
result += " " + amount + " " + (amount > 1 ? tr("Days") : tr("Day"));
time -= amount * TIME_DAY;
}
if(time > TIME_HOUR) {
if (time > TIME_HOUR) {
const amount = Math.floor(time / TIME_HOUR);
result += " " + amount + " " + (amount > 1 ? tr("Hours") : tr("Hour"));
time -= amount * TIME_HOUR;
}
if(time > TIME_MINUTE) {
if (time > TIME_MINUTE) {
const amount = Math.floor(time / TIME_MINUTE);
result += " " + amount + " " + (amount > 1 ? tr("Minutes") : tr("Minute"));
time -= amount * TIME_MINUTE;
}
if(time > TIME_SECOND) {
if (time > TIME_SECOND) {
const amount = Math.floor(time / TIME_SECOND);
result += " " + amount + " " + (amount > 1 ? tr("Seconds") : tr("Second"));
time -= amount * TIME_SECOND;
@ -99,7 +100,10 @@ function format_time(time: number, default_value: string) {
function apply_static_info(client: ClientEntry, tag: JQuery, modal: Modal, callbacks: InfoUpdateCallback[]) {
tag.find(".container-avatar").append(
client.channelTree.client.fileManager.avatars.generate_chat_tag({database_id: client.properties.client_database_id, id: client.clientId()}, client.properties.client_unique_identifier)
client.channelTree.client.fileManager.avatars.generate_chat_tag({
database_id: client.properties.client_database_id,
id: client.clientId()
}, client.properties.client_unique_identifier)
);
tag.find(".container-name").append(
@ -120,7 +124,7 @@ function apply_client_status(client: ClientEntry, tag: JQuery, modal: Modal, cal
tag.find(".status-away").toggle(client.properties.client_away);
if(client.properties.client_away_message) {
if (client.properties.client_away_message) {
tag.find(".container-away-message").show().find("a").text(client.properties.client_away_message);
} else {
tag.find(".container-away-message").hide();
@ -145,15 +149,15 @@ function apply_basic_info(client: ClientEntry, tag: JQuery, modal: Modal, callba
{
const container = tag.find(".property-teaforo .value").empty();
if(client.properties.client_teaforo_id) {
if (client.properties.client_teaforo_id) {
container.children().remove();
let text = client.properties.client_teaforo_name;
if((client.properties.client_teaforo_flags & 0x01) > 0)
if ((client.properties.client_teaforo_flags & 0x01) > 0)
text += " (" + tr("Banned") + ")";
if((client.properties.client_teaforo_flags & 0x02) > 0)
if ((client.properties.client_teaforo_flags & 0x02) > 0)
text += " (" + tr("Stuff") + ")";
if((client.properties.client_teaforo_flags & 0x04) > 0)
if ((client.properties.client_teaforo_flags & 0x04) > 0)
text += " (" + tr("Premium") + ")";
$.spawn("a")
@ -186,7 +190,7 @@ function apply_basic_info(client: ClientEntry, tag: JQuery, modal: Modal, callba
timestamp = parseInt(ts);
return "";
});
if(timestamp > 0) {
if (timestamp > 0) {
container_timestamp.find(".value-timestamp").text(moment(timestamp * 1000).format('MMMM Do YYYY, h:mm:ss a'));
container_timestamp.show();
} else {
@ -248,7 +252,7 @@ function apply_basic_info(client: ClientEntry, tag: JQuery, modal: Modal, callba
const container = tag.find(".property-online-since");
const node = container.find(".value a")[0];
if(node) {
if (node) {
const update = () => {
node.innerText = format_time(client.calculateOnlineTime() * 1000, tr("0 Seconds"));
};
@ -262,7 +266,7 @@ function apply_basic_info(client: ClientEntry, tag: JQuery, modal: Modal, callba
{
const container = tag.find(".property-idle-time");
const node = container.find(".value a")[0];
if(node) {
if (node) {
callbacks.push(info => {
node.innerText = format_time(info.connection_idle_time, tr("Currently active"));
});
@ -275,11 +279,11 @@ function apply_basic_info(client: ClientEntry, tag: JQuery, modal: Modal, callba
const container = tag.find(".property-ping");
const node = container.find(".value a")[0];
if(node) {
if (node) {
callbacks.push(info => {
if(info.connection_ping >= 0)
if (info.connection_ping >= 0)
node.innerText = info.connection_ping.toFixed(0) + "ms ± " + info.connection_ping_deviation.toFixed(2) + "ms";
else if(info.connection_ping == -1 && info.connection_ping_deviation == -1)
else if (info.connection_ping == -1 && info.connection_ping_deviation == -1)
node.innerText = tr("Not calculated");
else
node.innerText = tr("loading...");
@ -299,12 +303,12 @@ function apply_groups(client: ClientEntry, tag: JQuery, modal: Modal, callbacks:
container_entries.empty();
container_empty.show();
for(const group_id of client.assignedServerGroupIds()) {
if(group_id == client.channelTree.server.properties.virtualserver_default_server_group)
for (const group_id of client.assignedServerGroupIds()) {
if (group_id == client.channelTree.server.properties.virtualserver_default_server_group)
continue;
const group = client.channelTree.client.groups.findServerGroup(group_id);
if(!group) continue; //This shall never happen!
if (!group) continue; //This shall never happen!
container_empty.hide();
container_entries.append($.spawn("div").addClass("entry").append(
@ -339,14 +343,14 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
const node_downstream = container.find(".downstream .value")[0];
const node_upstream = container.find(".upstream .value")[0];
if(node_downstream) {
if (node_downstream) {
callbacks.push(info => {
node_downstream.innerText = info.connection_server2client_packetloss_control < 0 ? tr("Not calculated") : (info.connection_server2client_packetloss_control || 0).toFixed();
});
node_downstream.innerText = tr("loading...");
}
if(node_upstream) {
if (node_upstream) {
callbacks.push(info => {
node_upstream.innerText = info.connection_client2server_packetloss_total < 0 ? tr("Not calculated") : (info.connection_client2server_packetloss_total || 0).toFixed();
});
@ -360,13 +364,13 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
const node_downstream = container.find(".downstream .value")[0];
const node_upstream = container.find(".upstream .value")[0];
if(node_downstream) {
if (node_downstream) {
callbacks.push(info => {
let packets = 0;
packets += info.connection_packets_received_speech > 0 ? info.connection_packets_received_speech : 0;
packets += info.connection_packets_received_control > 0 ? info.connection_packets_received_control : 0;
packets += info.connection_packets_received_keepalive > 0 ? info.connection_packets_received_keepalive : 0;
if(packets == 0 && info.connection_packets_received_keepalive == -1)
if (packets == 0 && info.connection_packets_received_keepalive == -1)
node_downstream.innerText = tr("Not calculated");
else
node_downstream.innerText = format_number(packets, {unit: "Packets"});
@ -374,13 +378,13 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
node_downstream.innerText = tr("loading...");
}
if(node_upstream) {
if (node_upstream) {
callbacks.push(info => {
let packets = 0;
packets += info.connection_packets_sent_speech > 0 ? info.connection_packets_sent_speech : 0;
packets += info.connection_packets_sent_control > 0 ? info.connection_packets_sent_control : 0;
packets += info.connection_packets_sent_keepalive > 0 ? info.connection_packets_sent_keepalive : 0;
if(packets == 0 && info.connection_packets_sent_keepalive == -1)
if (packets == 0 && info.connection_packets_sent_keepalive == -1)
node_upstream.innerText = tr("Not calculated");
else
node_upstream.innerText = format_number(packets, {unit: "Packets"});
@ -395,13 +399,13 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
const node_downstream = container.find(".downstream .value")[0];
const node_upstream = container.find(".upstream .value")[0];
if(node_downstream) {
if (node_downstream) {
callbacks.push(info => {
let bytes = 0;
bytes += info.connection_bytes_received_speech > 0 ? info.connection_bytes_received_speech : 0;
bytes += info.connection_bytes_received_control > 0 ? info.connection_bytes_received_control : 0;
bytes += info.connection_bytes_received_keepalive > 0 ? info.connection_bytes_received_keepalive : 0;
if(bytes == 0 && info.connection_bytes_received_keepalive == -1)
if (bytes == 0 && info.connection_bytes_received_keepalive == -1)
node_downstream.innerText = tr("Not calculated");
else
node_downstream.innerText = network.format_bytes(bytes);
@ -409,13 +413,13 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
node_downstream.innerText = tr("loading...");
}
if(node_upstream) {
if (node_upstream) {
callbacks.push(info => {
let bytes = 0;
bytes += info.connection_bytes_sent_speech > 0 ? info.connection_bytes_sent_speech : 0;
bytes += info.connection_bytes_sent_control > 0 ? info.connection_bytes_sent_control : 0;
bytes += info.connection_bytes_sent_keepalive > 0 ? info.connection_bytes_sent_keepalive : 0;
if(bytes == 0 && info.connection_bytes_sent_keepalive == -1)
if (bytes == 0 && info.connection_bytes_sent_keepalive == -1)
node_upstream.innerText = tr("Not calculated");
else
node_upstream.innerText = network.format_bytes(bytes);
@ -430,27 +434,27 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
const node_downstream = container.find(".downstream .value")[0];
const node_upstream = container.find(".upstream .value")[0];
if(node_downstream) {
if (node_downstream) {
callbacks.push(info => {
let bytes = 0;
bytes += info.connection_bandwidth_received_last_second_speech > 0 ? info.connection_bandwidth_received_last_second_speech : 0;
bytes += info.connection_bandwidth_received_last_second_control > 0 ? info.connection_bandwidth_received_last_second_control : 0;
bytes += info.connection_bandwidth_received_last_second_keepalive > 0 ? info.connection_bandwidth_received_last_second_keepalive : 0;
if(bytes == 0 && info.connection_bandwidth_received_last_second_keepalive == -1)
if (bytes == 0 && info.connection_bandwidth_received_last_second_keepalive == -1)
node_downstream.innerText = tr("Not calculated");
else
node_downstream.innerText = network.format_bytes(bytes, {time: "s"});
});
});
node_downstream.innerText = tr("loading...");
}
if(node_upstream) {
if (node_upstream) {
callbacks.push(info => {
let bytes = 0;
bytes += info.connection_bandwidth_sent_last_second_speech > 0 ? info.connection_bandwidth_sent_last_second_speech : 0;
bytes += info.connection_bandwidth_sent_last_second_control > 0 ? info.connection_bandwidth_sent_last_second_control : 0;
bytes += info.connection_bandwidth_sent_last_second_keepalive > 0 ? info.connection_bandwidth_sent_last_second_keepalive : 0;
if(bytes == 0 && info.connection_bandwidth_sent_last_second_keepalive == -1)
if (bytes == 0 && info.connection_bandwidth_sent_last_second_keepalive == -1)
node_upstream.innerText = tr("Not calculated");
else
node_upstream.innerText = network.format_bytes(bytes, {time: "s"});
@ -465,13 +469,13 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
const node_downstream = container.find(".downstream .value")[0];
const node_upstream = container.find(".upstream .value")[0];
if(node_downstream) {
if (node_downstream) {
callbacks.push(info => {
let bytes = 0;
bytes += info.connection_bandwidth_received_last_minute_speech > 0 ? info.connection_bandwidth_received_last_minute_speech : 0;
bytes += info.connection_bandwidth_received_last_minute_control > 0 ? info.connection_bandwidth_received_last_minute_control : 0;
bytes += info.connection_bandwidth_received_last_minute_keepalive > 0 ? info.connection_bandwidth_received_last_minute_keepalive : 0;
if(bytes == 0 && info.connection_bandwidth_received_last_minute_keepalive == -1)
if (bytes == 0 && info.connection_bandwidth_received_last_minute_keepalive == -1)
node_downstream.innerText = tr("Not calculated");
else
node_downstream.innerText = network.format_bytes(bytes, {time: "s"});
@ -479,13 +483,13 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
node_downstream.innerText = tr("loading...");
}
if(node_upstream) {
if (node_upstream) {
callbacks.push(info => {
let bytes = 0;
bytes += info.connection_bandwidth_sent_last_minute_speech > 0 ? info.connection_bandwidth_sent_last_minute_speech : 0;
bytes += info.connection_bandwidth_sent_last_minute_control > 0 ? info.connection_bandwidth_sent_last_minute_control : 0;
bytes += info.connection_bandwidth_sent_last_minute_keepalive > 0 ? info.connection_bandwidth_sent_last_minute_keepalive : 0;
if(bytes == 0 && info.connection_bandwidth_sent_last_minute_keepalive == -1)
if (bytes == 0 && info.connection_bandwidth_sent_last_minute_keepalive == -1)
node_upstream.innerText = tr("Not calculated");
else
node_upstream.innerText = network.format_bytes(bytes, {time: "s"});
@ -500,7 +504,7 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
const node_downstream = container.find(".downstream .value")[0];
const node_upstream = container.find(".upstream .value")[0];
if(node_downstream) {
if (node_downstream) {
client.updateClientVariables().then(info => {
//TODO: Test for own client info and if so then show the max quota (needed permission)
node_downstream.innerText = network.format_bytes(client.properties.client_month_bytes_downloaded, {exact: false});
@ -508,7 +512,7 @@ function apply_packets(client: ClientEntry, tag: JQuery, modal: Modal, callbacks
node_downstream.innerText = tr("loading...");
}
if(node_upstream) {
if (node_upstream) {
client.updateClientVariables().then(info => {
//TODO: Test for own client info and if so then show the max quota (needed permission)
node_upstream.innerText = network.format_bytes(client.properties.client_month_bytes_uploaded, {exact: false});

View File

@ -1,14 +1,14 @@
import {Settings, settings} from "tc-shared/settings";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {Settings, settings} from "../../settings";
import * as log from "../../log";
import {LogCategory} from "../../log";
import * as loader from "tc-loader";
import {createModal} from "tc-shared/ui/elements/Modal";
import {ConnectionProfile, default_profile, find_profile, profiles} from "tc-shared/profiles/ConnectionProfile";
import {KeyCode} from "tc-shared/PPTListener";
import * as i18nc from "tc-shared/i18n/country";
import {spawnSettingsModal} from "tc-shared/ui/modal/ModalSettings";
import {server_connections} from "tc-shared/ui/frames/connection_handlers";
import {icon_cache_loader, IconManager} from "tc-shared/file/Icons";
import {createModal} from "../../ui/elements/Modal";
import {ConnectionProfile, default_profile, find_profile, profiles} from "../../profiles/ConnectionProfile";
import {KeyCode} from "../../PPTListener";
import * as i18nc from "../../i18n/country";
import {spawnSettingsModal} from "../../ui/modal/ModalSettings";
import {server_connections} from "../../ui/frames/connection_handlers";
import {icon_cache_loader, IconManager} from "../../file/Icons";
//FIXME: Move this shit out of this file!
export namespace connection_log {
@ -36,9 +36,10 @@ export namespace connection_log {
}
let _history: ConnectionEntry[] = [];
export function log_connect(address: { hostname: string; port: number }) {
let entry = _history.find(e => e.address.hostname.toLowerCase() == address.hostname.toLowerCase() && e.address.port == address.port);
if(!entry) {
if (!entry) {
_history.push(entry = {
last_timestamp: Date.now(),
first_timestamp: Date.now(),
@ -62,8 +63,8 @@ export namespace connection_log {
export function update_address_info(address: { hostname: string; port: number }, data: ConnectionData) {
_history.filter(e => e.address.hostname.toLowerCase() == address.hostname.toLowerCase() && e.address.port == address.port).forEach(e => {
for(const key of Object.keys(data)) {
if(typeof(data[key]) !== "undefined") {
for (const key of Object.keys(data)) {
if (typeof (data[key]) !== "undefined") {
e[key] = data[key];
}
}
@ -82,7 +83,7 @@ export namespace connection_log {
settings.changeGlobal(Settings.KEY_CONNECT_HISTORY, JSON.stringify(_history));
}
export function history() : ConnectionEntry[] {
export function history(): ConnectionEntry[] {
return _history.sort((a, b) => b.last_timestamp - a.last_timestamp);
}
@ -98,7 +99,7 @@ export namespace connection_log {
_history = [];
try {
_history = JSON.parse(settings.global(Settings.KEY_CONNECT_HISTORY, "[]"));
} catch(error) {
} catch (error) {
log.warn(LogCategory.CLIENT, tr("Failed to load connection history: {}"), error);
}
}
@ -106,9 +107,13 @@ export namespace connection_log {
}
declare const native_client;
export function spawnConnectModal(options: {
default_connect_new_tab?: boolean /* default false */
}, defaultHost: { url: string, enforce: boolean} = { url: "ts.TeaSpeak.de", enforce: false}, connect_profile?: { profile: ConnectionProfile, enforce: boolean}) {
}, defaultHost: { url: string, enforce: boolean } = {
url: "ts.TeaSpeak.de",
enforce: false
}, connect_profile?: { profile: ConnectionProfile, enforce: boolean }) {
let selected_profile: ConnectionProfile;
const random_id = (() => {
@ -124,7 +129,7 @@ export function spawnConnectModal(options: {
forum_path: "https://forum.teaspeak.de/",
password_id: random_id,
multi_tab: !settings.static_global(Settings.KEY_DISABLE_MULTI_SESSION),
default_connect_new_tab: typeof(options.default_connect_new_tab) === "boolean" && options.default_connect_new_tab
default_connect_new_tab: typeof (options.default_connect_new_tab) === "boolean" && options.default_connect_new_tab
}),
footer: () => undefined,
min_width: "28em"
@ -162,7 +167,7 @@ export function spawnConnectModal(options: {
const input_password = body.find(".container-password input");
let updateFields = (reset_current_data: boolean) => {
if(reset_current_data) {
if (reset_current_data) {
current_connect_data = undefined;
container_last_server_body.find(".selected").removeClass("selected");
}
@ -172,7 +177,7 @@ export function spawnConnectModal(options: {
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.IP_V6) || !!address.match(Regex.DOMAIN);
let nickname = input_nickname.val().toString();
if(nickname)
if (nickname)
settings.changeGlobal(Settings.KEY_CONNECT_USERNAME, nickname);
else
nickname = input_nickname.attr("placeholder") || "";
@ -190,7 +195,7 @@ export function spawnConnectModal(options: {
input_address
.on("keyup", () => updateFields(true))
.on('keydown', event => {
if(event.keyCode == KeyCode.KEY_ENTER && !event.shiftKey)
if (event.keyCode == KeyCode.KEY_ENTER && !event.shiftKey)
button_connect.trigger('click');
});
button_manage.on('click', event => {
@ -203,7 +208,7 @@ export function spawnConnectModal(options: {
/* Connect Profiles */
{
for(const profile of profiles()) {
for (const profile of profiles()) {
input_profile.append(
$.spawn("option").text(profile.profile_name).val(profile.id)
);
@ -229,7 +234,7 @@ export function spawnConnectModal(options: {
}
const last_nickname = settings.static_global(Settings.KEY_CONNECT_USERNAME, undefined);
if(last_nickname) /* restore */
if (last_nickname) /* restore */
settings.changeGlobal(Settings.KEY_CONNECT_USERNAME, last_nickname);
input_nickname.val(last_nickname);
@ -238,7 +243,7 @@ export function spawnConnectModal(options: {
const server_address = () => {
let address = input_address.val().toString();
if(address.match(Regex.IP_V6) && !address.startsWith("["))
if (address.match(Regex.IP_V6) && !address.startsWith("["))
return "[" + address + "]";
return address;
};
@ -246,14 +251,17 @@ export function spawnConnectModal(options: {
modal.close();
const connection = server_connections.active_connection();
if(connection) {
if (connection) {
connection.startConnection(
current_connect_data ? current_connect_data.address.hostname + ":" + current_connect_data.address.port : server_address(),
selected_profile,
true,
{
nickname: input_nickname.val().toString() || input_nickname.attr("placeholder"),
password: (current_connect_data && current_connect_data.password_hash) ? {password: current_connect_data.password_hash, hashed: true} : {password: input_password.val().toString(), hashed: false}
nickname: input_nickname.val().toString() || input_nickname.attr("placeholder"),
password: (current_connect_data && current_connect_data.password_hash) ? {
password: current_connect_data.password_hash,
hashed: true
} : {password: input_password.val().toString(), hashed: false}
}
);
} else {
@ -266,12 +274,15 @@ export function spawnConnectModal(options: {
const connection = server_connections.spawn_server_connection();
server_connections.set_active_connection(connection);
connection.startConnection(
current_connect_data ? current_connect_data.address.hostname + ":" + current_connect_data.address.port : server_address(),
current_connect_data ? current_connect_data.address.hostname + ":" + current_connect_data.address.port : server_address(),
selected_profile,
true,
{
nickname: input_nickname.val().toString() || input_nickname.attr("placeholder"),
password: (current_connect_data && current_connect_data.password_hash) ? {password: current_connect_data.password_hash, hashed: true} : {password: input_password.val().toString(), hashed: false}
nickname: input_nickname.val().toString() || input_nickname.attr("placeholder"),
password: (current_connect_data && current_connect_data.password_hash) ? {
password: current_connect_data.password_hash,
hashed: true
} : {password: input_password.val().toString(), hashed: false}
}
);
});
@ -279,7 +290,7 @@ export function spawnConnectModal(options: {
/* connect history show */
{
for(const entry of connection_log.history().slice(0, 10)) {
for (const entry of connection_log.history().slice(0, 10)) {
$.spawn("div").addClass("row").append(
$.spawn("div").addClass("column delete").append($.spawn("div").addClass("icon_em client-delete")).on('click', event => {
event.preventDefault();
@ -310,7 +321,7 @@ export function spawnConnectModal(options: {
).append(
$.spawn("div").addClass("column connections").text(entry.total_connection + "")
).on('click', event => {
if(event.isDefaultPrevented())
if (event.isDefaultPrevented())
return;
event.preventDefault();

View File

@ -1,15 +1,15 @@
import PermissionType from "tc-shared/permission/PermissionType";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {ChannelEntry, ChannelProperties} from "tc-shared/tree/Channel";
import {PermissionManager, PermissionValue} from "tc-shared/permission/PermissionManager";
import {LogCategory} from "tc-shared/log";
import {createModal} from "tc-shared/ui/elements/Modal";
import * as log from "tc-shared/log";
import {Settings, settings} from "tc-shared/settings";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import {spawnIconSelect} from "tc-shared/ui/modal/ModalIconSelect";
import {hashPassword} from "tc-shared/utils/helpers";
import {sliderfy} from "tc-shared/ui/elements/Slider";
import PermissionType from "../../permission/PermissionType";
import {ConnectionHandler} from "../../ConnectionHandler";
import {ChannelEntry, ChannelProperties} from "../../tree/Channel";
import {PermissionManager, PermissionValue} from "../../permission/PermissionManager";
import {LogCategory} from "../../log";
import {createModal} from "../../ui/elements/Modal";
import * as log from "../../log";
import {Settings, settings} from "../../settings";
import * as tooltip from "../../ui/elements/Tooltip";
import {spawnIconSelect} from "../../ui/modal/ModalIconSelect";
import {hashPassword} from "../../utils/helpers";
import {sliderfy} from "../../ui/elements/Slider";
export function createChannelModal(connection: ConnectionHandler, channel: ChannelEntry | undefined, parent: ChannelEntry | undefined, permissions: PermissionManager, callback: (properties?: ChannelProperties, permissions?: PermissionValue[]) => any) {
let properties: ChannelProperties = { } as ChannelProperties; //The changes properties

View File

@ -1,9 +1,9 @@
import {LogCategory} from "tc-shared/log";
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import * as log from "tc-shared/log";
import {ClientEntry} from "tc-shared/tree/Client";
import {GroupManager, GroupType} from "tc-shared/permission/GroupManager";
import PermissionType from "tc-shared/permission/PermissionType";
import {LogCategory} from "../../log";
import {createModal, Modal} from "../../ui/elements/Modal";
import * as log from "../../log";
import {ClientEntry} from "../../tree/Client";
import {GroupManager, GroupType} from "../../permission/GroupManager";
import PermissionType from "../../permission/PermissionType";
let current_modal: Modal;
export function createServerGroupAssignmentModal(client: ClientEntry, callback: (groups: number[], flag: boolean) => Promise<boolean>) {

View File

@ -1,15 +1,15 @@
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import PermissionType from "tc-shared/permission/PermissionType";
import {createErrorModal, createModal} from "tc-shared/ui/elements/Modal";
import * as log from "tc-shared/log";
import {LogCategory} from "tc-shared/log";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {tra, traj} from "tc-shared/i18n/localize";
import {arrayBufferBase64} from "tc-shared/utils/buffers";
import * as crc32 from "tc-shared/crypto/crc32";
import {FileInfo} from "tc-shared/file/FileManager";
import {FileTransferState, TransferProvider} from "tc-shared/file/Transfer";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {ConnectionHandler} from "../../ConnectionHandler";
import PermissionType from "../../permission/PermissionType";
import {createErrorModal, createModal} from "../../ui/elements/Modal";
import * as log from "../../log";
import {LogCategory} from "../../log";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {tra, traj} from "../../i18n/localize";
import {arrayBufferBase64} from "../../utils/buffers";
import * as crc32 from "../../crypto/crc32";
import {FileInfo} from "../../file/FileManager";
import {FileTransferState, TransferProvider} from "../../file/Transfer";
import {ErrorCode} from "../../connection/ErrorCode";
export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: number) => any, selected_icon?: number) {
selected_icon = selected_icon || 0;
@ -49,9 +49,9 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
const update_local_icons = (icons: number[]) => {
container_icons_local.empty();
for(const icon_id of icons) {
for (const icon_id of icons) {
const tag = client.fileManager.icons.generateTag(icon_id, {animate: false}).attr('title', "Icon " + icon_id);
if(callback_icon) {
if (callback_icon) {
tag.on('click', event => {
container_icons.find(".selected").removeClass("selected");
tag.addClass("selected");
@ -64,7 +64,7 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
callback_icon(icon_id);
modal.close();
});
if(icon_id == selected_icon)
if (icon_id == selected_icon)
tag.trigger('click');
}
tag.appendTo(container_icons_local);
@ -76,7 +76,7 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
container_error.hide();
container_loading.show();
const display_remote_error = (error?: string) => {
if(typeof(error) === "string") {
if (typeof (error) === "string") {
container_error.find(".error-message").text(error);
container_error.show();
} else {
@ -91,23 +91,23 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
const chunk_size = 50;
const icon_chunks: FileInfo[][] = [];
let index = 0;
while(icons.length > index) {
while (icons.length > index) {
icon_chunks.push(icons.slice(index, index + chunk_size));
index += chunk_size;
}
const process_next_chunk = () => {
const chunk = icon_chunks.pop_front();
if(!chunk) return;
if (!chunk) return;
for(const icon of chunk) {
for (const icon of chunk) {
const icon_id = parseInt(icon.name.substr("icon_".length));
if(Number.isNaN(icon_id)) {
if (Number.isNaN(icon_id)) {
log.warn(LogCategory.GENERAL, tr("Received an unparsable icon within icon list (%o)"), icon);
continue;
}
const tag = client.fileManager.icons.generateTag(icon_id, {animate: false}).attr('title', "Icon " + icon_id);
if(callback_icon || allow_manage) {
if (callback_icon || allow_manage) {
tag.on('click', event => {
container_icons.find(".selected").removeClass("selected");
tag.addClass("selected");
@ -118,13 +118,13 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
button_delete.prop("disabled", !allow_manage);
});
tag.on('dblclick', event => {
if(!callback_icon)
if (!callback_icon)
return;
callback_icon(icon_id);
modal.close();
});
if(icon_id == selected_icon)
if (icon_id == selected_icon)
tag.trigger('click');
}
tag.appendTo(container_icons_remote);
@ -138,7 +138,7 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
container_loading.hide();
container_no_permissions.hide();
}).catch(error => {
if(error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
if (error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
container_no_permissions.show();
} else {
log.error(LogCategory.GENERAL, tr("Failed to fetch icon list. Error: %o"), error);
@ -149,19 +149,19 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
};
button_delete.on('click', event => {
if(!selected_icon)
if (!selected_icon)
return;
const selected = modal.htmlTag.find(".selected");
if(selected.length != 1)
if (selected.length != 1)
console.warn(tr("UI selected icon length does not equal with 1! (%o)"), selected.length);
if(selected_icon < 1000) return; /* we cant delete local icons */
if (selected_icon < 1000) return; /* we cant delete local icons */
client.fileManager.icons.delete_icon(selected_icon).then(() => {
selected.detach();
}).catch(error => {
if(error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS)
if (error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS)
return;
console.warn(tr("Failed to delete icon %d: %o"), selected_icon, error);
@ -177,11 +177,11 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id:
update_remote_icons();
modal.htmlTag.find('.button-reload').on('click', () => update_remote_icons());
button_select.prop("disabled", true).on('click', () => {
if(callback_icon) callback_icon(selected_icon);
if (callback_icon) callback_icon(selected_icon);
modal.close();
});
modal.htmlTag.find(".button-select-no-icon").on('click', () => {
if(callback_icon) callback_icon(0);
if (callback_icon) callback_icon(0);
modal.close();
});
modal.open();
@ -203,7 +203,7 @@ interface UploadingIcon {
icon_id: string;
}
function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIcon {
function handle_icon_upload(file: File, client: ConnectionHandler): UploadingIcon {
const icon = {} as UploadingIcon;
icon.file = file;
icon.upload_state = "unset";
@ -213,9 +213,9 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.<br>The given file is too big!", file.name)).open();
icon.state = "error";
};
if(file.size > 1024 * 1024 * 512) {
if (file.size > 1024 * 1024 * 512) {
file_too_big();
} else if((file.size | 0) <= 0) {
} else if ((file.size | 0) <= 0) {
console.error(tr("Failed to load file %s: Your browser does not support file sizes!"), file.name);
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.<br>Your browser does not support file sizes!", file.name)).open();
icon.state = "error";
@ -231,7 +231,7 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
reader.onerror = reject;
reader.readAsDataURL(file);
});
} catch(error) {
} catch (error) {
console.log("Image failed to load (%o)", error);
console.error(tr("Failed to load file %s: Image failed to load"), file.name);
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.<br>Failed to load image", file.name)).open();
@ -240,7 +240,7 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
}
const result = reader.result as string;
if(typeof(result) !== "string") {
if (typeof (result) !== "string") {
console.error(tr("Failed to load file %s: Result is not an media string (%o)"), file.name, result);
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.<br>Result is not an media string", file.name)).open();
icon.state = "error";
@ -250,7 +250,7 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
/* get the CRC32 sum */
{
if(!result.startsWith("data:image/")) {
if (!result.startsWith("data:image/")) {
console.error(tr("Failed to load file %s: Invalid data media type (%o)"), file.name, result);
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.<br>File is not an image", file.name)).open();
icon.state = "error";
@ -259,7 +259,7 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
const semi = result.indexOf(';');
const type = result.substring(11, semi);
console.log(tr("Given image has type %s"), type);
if(!result.substr(semi + 1).startsWith("base64,")) {
if (!result.substr(semi + 1).startsWith("base64,")) {
console.error(tr("Failed to load file %s: Mimetype isnt base64 encoded (%o)"), file.name, result.substr(semi + 1));
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.<br>Decoder returned unknown result", file.name)).open();
icon.state = "error";
@ -279,7 +279,7 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
image.onerror = reject;
image.src = result;
});
} catch(error) {
} catch (error) {
console.log("Image failed to load (%o)", error);
console.error(tr("Failed to load file %s: Image failed to load"), file.name);
createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.{:br:}Failed to load image", file.name)).open();
@ -292,16 +292,16 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
icon.state = "error";
};
if(!result.startsWith("data:image/svg+xml")) {
if(image.naturalWidth > 128 && image.naturalHeight > 128) {
if (!result.startsWith("data:image/svg+xml")) {
if (image.naturalWidth > 128 && image.naturalHeight > 128) {
width_error("width and height (max 32px). Given: " + image.naturalWidth + "x" + image.naturalHeight);
return;
}
if(image.naturalWidth > 128) {
if (image.naturalWidth > 128) {
width_error("width (max 32px)");
return;
}
if(image.naturalHeight > 128) {
if (image.naturalHeight > 128) {
width_error("height (max 32px)");
return;
}
@ -322,7 +322,7 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
const message = $.spawn("div").addClass("progress-message");
const set_value = value => {
indicator.stop(true, false).animate({width: value + "%"}, 250);
if(value === 100)
if (value === 100)
setTimeout(() => indicator.removeClass("progress-bar-striped progress-bar-animated"), 900)
};
@ -349,14 +349,14 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
};
const html_tag = $.spawn("div")
.addClass("upload-entry")
.append(container_image)
.append(bar.html_tag);
.addClass("upload-entry")
.append(container_image)
.append(bar.html_tag);
icon.upload_html_tag = html_tag;
let icon_added = false;
if(icon.image_element) {
if (icon.image_element) {
container_image.append(icon.image_element());
icon_added = true;
}
@ -368,21 +368,21 @@ function handle_icon_upload(file: File, client: ConnectionHandler) : UploadingIc
return async () => {
const time_begin = Date.now();
if(icon.state === "loading") {
if (icon.state === "loading") {
bar.set_message(tr("Awaiting local processing"));
await icon.loader;
// @ts-ignore Could happen because the loader function updates the state
if(icon.state !== "valid") {
if (icon.state !== "valid") {
set_error(tr("local processing failed"));
icon.upload_state = "error";
return;
}
} else if(icon.state === "error") {
} else if (icon.state === "error") {
set_error(tr("local processing error"));
icon.upload_state = "error";
return;
}
if(!icon_added)
if (!icon_added)
container_image.append(icon.image_element());
bar.set_value(25);
@ -474,11 +474,11 @@ export function spawnIconUpload(client: ConnectionHandler) {
const add_icon = (icon: UploadingIcon) => {
icons.push(icon);
icon.loader.then(e => {
if(icon.state === "valid") {
if (icon.state === "valid") {
const image = icon.image_element();
const element = $.spawn("div")
.addClass("icon-container")
.append(image);
.addClass("icon-container")
.append(image);
container_icons.append(icon.html_tag = element);
element.on('click', event => {
@ -494,10 +494,10 @@ export function spawnIconUpload(client: ConnectionHandler) {
});
};
button_delete.on('click', event => {
if(!selected_icon)
if (!selected_icon)
return;
icons = icons.filter(e => e !== selected_icon);
if(selected_icon.html_tag)
if (selected_icon.html_tag)
selected_icon.html_tag.detach();
button_delete.prop("disabled", true);
update_upload_button();
@ -505,18 +505,18 @@ export function spawnIconUpload(client: ConnectionHandler) {
button_add.on('click', event => input_file.click());
input_file.on('change', event => {
if(input_file[0].files.length > 0) {
for(let index = 0; index < input_file[0].files.length; index++) {
if (input_file[0].files.length > 0) {
for (let index = 0; index < input_file[0].files.length; index++) {
const file = input_file[0].files.item(index);
{
let duplicate = false;
for(const icon of icons)
if(icon.file.name === file.name && icon.file.lastModified === file.lastModified && icon.state !== "error") {
for (const icon of icons)
if (icon.file.name === file.name && icon.file.lastModified === file.lastModified && icon.state !== "error") {
duplicate = true;
break;
}
if(duplicate)
if (duplicate)
continue;
}
@ -534,17 +534,17 @@ export function spawnIconUpload(client: ConnectionHandler) {
event.stopPropagation();
event.preventDefault();
for(let index = 0; index < event.dataTransfer.files.length; index++) {
for (let index = 0; index < event.dataTransfer.files.length; index++) {
const file = event.dataTransfer.files.item(index);
{
let duplicate = false;
for(const icon of icons)
if(icon.file === file && icon.state !== "error") {
for (const icon of icons)
if (icon.file === file && icon.state !== "error") {
duplicate = true;
break;
}
if(duplicate)
if (duplicate)
continue;
}
@ -568,7 +568,7 @@ export function spawnIconUpload(client: ConnectionHandler) {
const finish_upload = () => {
icons = icons.filter(e => {
if(e.upload_state === "uploaded") {
if (e.upload_state === "uploaded") {
e.html_tag.detach();
return false;
}
@ -585,13 +585,13 @@ export function spawnIconUpload(client: ConnectionHandler) {
const execute_upload = async () => {
if(!client || !client.fileManager) {
show_critical_error(tr("Invalid client handle"));
return;
if (!client || !client.fileManager) {
show_critical_error(tr("Invalid client handle"));
return;
}
if(!client.connected) {
show_critical_error(tr("Not connected"));
return;
if (!client.connected) {
show_critical_error(tr("Not connected"));
return;
}
let invoke_count = 0;
@ -600,28 +600,28 @@ export function spawnIconUpload(client: ConnectionHandler) {
const uploads = icons.filter(e => e.state !== "error");
const executes: {icon: UploadingIcon, task: () => Promise<void>}[] = [];
for(const icon of uploads) {
const executes: { icon: UploadingIcon, task: () => Promise<void> }[] = [];
for (const icon of uploads) {
executes.push({
icon: icon,
task: icon.upload_icon()
});
if(!icon.upload_html_tag)
if (!icon.upload_html_tag)
continue; /* TODO: error? */
icon.upload_html_tag.appendTo(container_process);
}
const update_state = () => container_statistics.text(invoke_count + " | " + succeed_count + " | " + failed_count);
for(const execute of executes) {
for (const execute of executes) {
invoke_count++;
update_state();
try {
await execute.task();
if(execute.icon.upload_state !== "uploaded")
if (execute.icon.upload_state !== "uploaded")
throw "failed";
succeed_count++;
} catch(error) {
} catch (error) {
failed_count++;
}
update_state();

View File

@ -1,7 +1,7 @@
import {createErrorModal, createInfoModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {TeaSpeakIdentity} from "tc-shared/profiles/identities/TeamSpeakIdentity";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {createErrorModal, createInfoModal, createModal, Modal} from "../../ui/elements/Modal";
import {TeaSpeakIdentity} from "../../profiles/identities/TeamSpeakIdentity";
import * as tooltip from "../../ui/elements/Tooltip";
import {formatMessage} from "../../ui/frames/chat";
export function spawnTeamSpeakIdentityImprove(identity: TeaSpeakIdentity, name: string): Modal {
let modal: Modal;
@ -125,7 +125,7 @@ export function spawnTeamSpeakIdentityImprove(identity: TeaSpeakIdentity, name:
export function spawnTeamSpeakIdentityImport(callback: (identity: TeaSpeakIdentity) => any): Modal {
let modal: Modal;
let selected_type: string;
let identities: {[key: string]: TeaSpeakIdentity} = {};
let identities: { [key: string]: TeaSpeakIdentity } = {};
modal = createModal({
header: tr("Import identity"),
@ -141,7 +141,7 @@ export function spawnTeamSpeakIdentityImport(callback: (identity: TeaSpeakIdenti
const set_status = (message: string | undefined, type: "error" | "loading" | "success") => {
container_status.toggleClass("hidden", !message);
if(message) {
if (message) {
container_status.toggleClass("error", type === "error");
container_status.toggleClass("loading", type === "loading");
container_status.find("a").text(message);
@ -173,7 +173,7 @@ export function spawnTeamSpeakIdentityImport(callback: (identity: TeaSpeakIdenti
});
};
/* file select button */
/* file select button */
input_file.on('change', event => {
const element = event.target as HTMLInputElement;
const file_reader = new FileReader();
@ -195,12 +195,12 @@ export function spawnTeamSpeakIdentityImport(callback: (identity: TeaSpeakIdenti
input_text.on('change keyup', event => {
const text = input_text.val() as string;
if(!text) {
if (!text) {
set_status("", "success");
return;
}
if(text.indexOf('V') == -1) {
if (text.indexOf('V') == -1) {
set_status(tr("Invalid identity string"), "error");
return;
}

View File

@ -1,7 +1,7 @@
import {settings, Settings} from "tc-shared/settings";
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {ServerAddress} from "tc-shared/tree/Server";
import {settings, Settings} from "../../settings";
import {createModal, Modal} from "../../ui/elements/Modal";
import {ConnectionHandler} from "../../ConnectionHandler";
import {ServerAddress} from "../../tree/Server";
type URLGeneratorSettings = {
flag_direct: boolean,
@ -23,16 +23,16 @@ type URLGenerator = {
};
const build_url = (base, params) => {
if(Object.keys(params).length == 0)
if (Object.keys(params).length == 0)
return base;
return base + "?" + Object.keys(params)
.map(e => e + "=" + encodeURIComponent(params[e]))
.join("&");
.map(e => e + "=" + encodeURIComponent(params[e]))
.join("&");
};
//TODO: Server password
const url_generators: {[key: string]:URLGenerator} = {
const url_generators: { [key: string]: URLGenerator } = {
"tea-web": {
generate: properties => {
const address = properties.resolved_address ? properties.resolved_address : properties.address;
@ -40,15 +40,15 @@ const url_generators: {[key: string]:URLGenerator} = {
const parameter = "connect_default=" + (properties.flag_direct ? 1 : 0) + "&connect_address=" + encodeURIComponent(address_str);
let pathbase = "";
if(document.location.protocol !== 'https:') {
if (document.location.protocol !== 'https:') {
/*
* Seems to be a test environment or the TeaClient for localhost where we dont have to use https.
*/
pathbase = "https://web.teaspeak.de/";
} else if(document.location.hostname === "localhost" || document.location.host.startsWith("127.")) {
} else if (document.location.hostname === "localhost" || document.location.host.startsWith("127.")) {
pathbase = "https://web.teaspeak.de/";
} else {
pathbase = document.location.origin + document.location.pathname;
pathbase = document.location.origin + document.location.pathname;
}
return pathbase + "?" + parameter;
},
@ -68,7 +68,7 @@ const url_generators: {[key: string]:URLGenerator} = {
connect_default: properties.flag_direct ? 1 : 0
};
if(address.port != 9987)
if (address.port != 9987)
parameters["port"] = address.port;
return build_url("teaclient://" + address.host + "/", parameters);
@ -85,7 +85,7 @@ const url_generators: {[key: string]:URLGenerator} = {
const address = properties.resolved_address ? properties.resolved_address : properties.address;
let parameters = {};
if(address.port != 9987)
if (address.port != 9987)
parameters["port"] = address.port;
/*
@ -138,7 +138,7 @@ export function spawnInviteEditor(connection: ConnectionHandler) {
value: node => node.prop('checked'),
set_value: (node, value) => node.prop('checked', value == "1"),
disable: (node, flag) => node.prop('disabled', flag)
.firstParent('.checkbox').toggleClass('disabled', flag)
.firstParent('.checkbox').toggleClass('disabled', flag)
},
{
@ -147,25 +147,25 @@ export function spawnInviteEditor(connection: ConnectionHandler) {
value: node => node.prop('checked'),
set_value: (node, value) => node.prop('checked', value == "1"),
disable: (node, flag) => node.prop('disabled', flag)
.firstParent('.checkbox').toggleClass('disabled', flag)
.firstParent('.checkbox').toggleClass('disabled', flag)
}
];
const update_buttons = () => {
const generator = url_generators[input_type.val() as string];
if(!generator) {
for(const s of invite_settings)
if (!generator) {
for (const s of invite_settings)
s.disable(s.node, true);
return;
}
for(const s of invite_settings)
for (const s of invite_settings)
s.disable(s.node, !generator.setting_available(s.key as any));
};
const update_link = () => {
const generator = url_generators[input_type.val() as string];
if(!generator) {
if (!generator) {
button_copy.prop('disabled', true);
label_output.text(tr("Missing link generator"));
return;
@ -176,14 +176,14 @@ export function spawnInviteEditor(connection: ConnectionHandler) {
address: connection.channelTree.server.remote_address,
resolved_address: connection.channelTree.client.serverConnection.remote_address()
};
for(const s of invite_settings)
for (const s of invite_settings)
properties[s.key] = s.value(s.node);
label_output.text(generator.generate(properties as any));
};
for(const s of invite_settings) {
for (const s of invite_settings) {
s.node.on('change keyup', () => {
settings.changeGlobal(Settings.FN_INVITE_LINK_SETTING(s.key), s.value(s.node));
update_link()
@ -193,10 +193,10 @@ export function spawnInviteEditor(connection: ConnectionHandler) {
}
input_type.on('change', () => {
settings.changeGlobal(Settings.KEY_LAST_INVITE_LINK_TYPE, input_type.val() as string);
update_buttons();
update_link();
}).val(settings.global(Settings.KEY_LAST_INVITE_LINK_TYPE));
settings.changeGlobal(Settings.KEY_LAST_INVITE_LINK_TYPE, input_type.val() as string);
update_buttons();
update_link();
}).val(settings.global(Settings.KEY_LAST_INVITE_LINK_TYPE));
button_copy.on('click', event => {
label_output.select();

View File

@ -1,11 +1,11 @@
import {createModal} from "tc-shared/ui/elements/Modal";
import {EventType, key_description, KeyEvent} from "tc-shared/PPTListener";
import {createModal} from "../../ui/elements/Modal";
import {EventType, key_description, KeyEvent} from "../../PPTListener";
import * as ppt from "tc-backend/ppt";
export function spawnKeySelect(callback: (key?: KeyEvent) => void) {
let modal = createModal({
header: tr("Select a key"),
body: () => $("#tmpl_key_select").renderTag().children(),
body: () => $("#tmpl_key_select").renderTag().children(),
footer: null,
width: "",
@ -20,7 +20,7 @@ export function spawnKeySelect(callback: (key?: KeyEvent) => void) {
let last_key: KeyEvent;
let current_key: KeyEvent;
const listener = (event: KeyEvent) => {
if(event.type === EventType.KEY_PRESS) {
if (event.type === EventType.KEY_PRESS) {
//console.log(tr("Key select got key press for %o"), event);
last_key = current_key;
current_key = event;
@ -33,9 +33,9 @@ export function spawnKeySelect(callback: (key?: KeyEvent) => void) {
button_save.on('click', () => {
if(__build.version !== "web") {
if (__build.version !== "web") {
/* Because pressing the close button is also a mouse action */
if(current_key_age + 1000 > Date.now() && current_key.key_code == "MOUSE1")
if (current_key_age + 1000 > Date.now() && current_key.key_code == "MOUSE1")
current_key = last_key;
}

View File

@ -1,18 +1,17 @@
import {createErrorModal, createModal} from "tc-shared/ui/elements/Modal";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {MusicClientEntry} from "tc-shared/tree/Client";
import {Registry} from "tc-shared/events";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {tra} from "tc-shared/i18n/localize";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import { modal } from "tc-shared/events";
import * as i18nc from "tc-shared/i18n/country";
import {find} from "tc-shared/permission/PermissionManager";
import {createErrorModal, createModal} from "../../ui/elements/Modal";
import {ConnectionHandler} from "../../ConnectionHandler";
import {MusicClientEntry} from "../../tree/Client";
import {modal, Registry} from "../../events";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import * as log from "../../log";
import {LogCategory} from "../../log";
import {tra} from "../../i18n/localize";
import * as tooltip from "../../ui/elements/Tooltip";
import * as i18nc from "../../i18n/country";
import {find} from "../../permission/PermissionManager";
import * as htmltags from "../../ui/htmltags";
import {ErrorCode} from "../../connection/ErrorCode";
import ServerGroup = find.ServerGroup;
import * as htmltags from "tc-shared/ui/htmltags";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
export function openMusicManage(client: ConnectionHandler, bot: MusicClientEntry) {
const ev_registry = new Registry<modal.music_manage>();
@ -22,7 +21,7 @@ export function openMusicManage(client: ConnectionHandler, bot: MusicClientEntry
let modal = createModal({
header: tr(tr("Playlist Manage")),
body: () => build_modal(ev_registry),
body: () => build_modal(ev_registry),
footer: null,
min_width: "35em",
@ -40,13 +39,13 @@ export function openMusicManage(client: ConnectionHandler, bot: MusicClientEntry
function permission_controller(event_registry: Registry<modal.music_manage>, bot: MusicClientEntry, client: ConnectionHandler) {
const error_msg = error => {
if(error instanceof CommandResult) {
if(error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
if (error instanceof CommandResult) {
if (error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
const permission = client.permissions.resolveInfo(error.json["failed_permid"]);
return tr("failed on permission ") + (permission ? permission.name : tr("unknown"));
}
return error.extra_message || error.message;
} else if(typeof error === "string")
} else if (typeof error === "string")
return error;
else
return tr("command error");
@ -85,14 +84,14 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
};
Promise.resolve().then(() => {
if(event.key === "notify_song_change") {
if (event.key === "notify_song_change") {
return client.serverConnection.send_command("clientedit", {
clid: bot.clientId(),
client_flag_notify_song_change: event.value
});
} else {
const property = property_map[event.key];
if(!property) return Promise.reject(tr("unknown property"));
if (!property) return Promise.reject(tr("unknown property"));
const data = {
playlist_id: playlist_id
@ -158,7 +157,7 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
Promise.resolve().then(() => {
const property = property_map[event.key];
if(!property) return Promise.reject(tr("unknown property"));
if (!property) return Promise.reject(tr("unknown property"));
const data = {
clid: bot.clientId()
@ -188,8 +187,8 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
const playlist_id = bot.properties.client_playlist_id;
client.permissions.requestPlaylistPermissions(playlist_id).then(result => {
const permissions = {};
for(const permission of result)
if(permission.hasValue())
for (const permission of result)
if (permission.hasValue())
permissions[permission.type.name] = permission.value;
event_registry.fire("general_permissions", {
status: "success",
@ -234,8 +233,8 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
const client_id = event.client_database_id;
client.permissions.requestPlaylistClientPermissions(playlist_id, client_id).then(result => {
const permissions = {};
for(const permission of result)
if(permission.hasValue())
for (const permission of result)
if (permission.hasValue())
permissions[permission.type.name] = permission.value;
event_registry.fire("client_permissions", {
status: "success",
@ -307,24 +306,25 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
});
event_registry.on("search_client", event => {
if(!event.text) return;
if (!event.text) return;
const text = event.text;
Promise.resolve().then(() => {
let is_uuid = false;
try {
is_uuid = atob(text).length === 32;
} catch(e) {}
if(is_uuid) {
} catch (e) {
}
if (is_uuid) {
return client.serverConnection.command_helper.getInfoFromUniqueId(text);
} else if(text.match(/^[0-9]{1,7}$/) && !isNaN(parseInt(text))) {
} else if (text.match(/^[0-9]{1,7}$/) && !isNaN(parseInt(text))) {
return client.serverConnection.command_helper.getInfoFromClientDatabaseId(parseInt(text));
} else {
//TODO: Database name lookup?
return Promise.reject("no results");
}
}).then(result => {
if(result.length) {
if (result.length) {
const client = result[0];
event_registry.fire("search_client_result", {
status: "success",
@ -351,11 +351,11 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
event_registry.on("query_group_permissions", event => {
client.permissions.find_permission(event.permission_name).then(result => {
let groups = [];
for(const e of result) {
if(e.type !== "server_group") continue;
for (const e of result) {
if (e.type !== "server_group") continue;
const group = client.groups.findServerGroup((e as ServerGroup).group_id);
if(!group) continue;
if (!group) continue;
groups.push({
name: group.name,
@ -511,7 +511,7 @@ function dummy_controller(event_registry: Registry<modal.music_manage>) {
}
function build_modal(event_registry: Registry<modal.music_manage>) : JQuery<HTMLElement> {
function build_modal(event_registry: Registry<modal.music_manage>): JQuery<HTMLElement> {
const tag = $("#tmpl_music_manage").renderTag();
const container_settings = tag.find(".body > .category-settings");
@ -532,8 +532,8 @@ function build_modal(event_registry: Registry<modal.music_manage>) : JQuery<HTML
container_permissions.toggleClass("hidden", data.container !== "permissions");
});
category_permissions.on('click', event => {
if(shown_container === "permissions") return;
event_registry.fire("show_container", { container: "permissions" });
if (shown_container === "permissions") return;
event_registry.fire("show_container", {container: "permissions"});
});
const category_settings = header.find(".category-settings");
@ -542,8 +542,8 @@ function build_modal(event_registry: Registry<modal.music_manage>) : JQuery<HTML
container_settings.toggleClass("hidden", data.container !== "settings");
});
category_settings.on('click', event => {
if(shown_container === "settings") return;
event_registry.fire("show_container", { container: "settings" });
if (shown_container === "settings") return;
event_registry.fire("show_container", {container: "settings"});
});
event_registry.on("show_container", data => shown_container = data.container);
@ -554,13 +554,13 @@ function build_modal(event_registry: Registry<modal.music_manage>) : JQuery<HTML
const input = event.target as HTMLInputElement;
const max = parseInt(input.getAttribute("maxlength"));
const text = input.value;
if(!isNaN(max) && text && text.length > max)
if (!isNaN(max) && text && text.length > max)
//input.value = text.substr(text.length - max);
input.value = text.substr(0, max);
});
/* initialize */
event_registry.fire("show_container", { container: "settings" });
event_registry.fire("show_container", {container: "settings"});
return tag.children();
}
@ -587,7 +587,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("bot_status", event => {
if(event.status === "error")
if (event.status === "error")
input
.prop("disabled", true)
.val(null)
@ -600,9 +600,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_bot_status_result", event => {
if(event.key !== "name") return;
if (event.key !== "name") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to set bot name"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -616,8 +616,8 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("focusout", event => {
const value = input.val() as string;
if(value === last_value) return;
if(!value) {
if (value === last_value) return;
if (!value) {
input.val(last_value);
return;
}
@ -643,8 +643,8 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
const update_country_code = input => {
input = input || fallback_country || "ts";
flag.each((_, e) => {
for(const [index, klass] of e.classList.entries())
if(klass.startsWith("flag-"))
for (const [index, klass] of e.classList.entries())
if (klass.startsWith("flag-"))
e.classList.remove(klass);
});
flag.addClass("flag-" + input.toLowerCase());
@ -661,7 +661,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("bot_status", event => {
if(event.status === "error")
if (event.status === "error")
input
.prop("disabled", true)
.val(null)
@ -677,9 +677,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_bot_status_result", event => {
if(event.key !== "country_code") return;
if (event.key !== "country_code") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to set bots country"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -699,8 +699,8 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("focusout", event => {
const value = input.val() as string;
if(value === last_value) return;
if(value && value.length != 2) {
if (value === last_value) return;
if (value && value.length != 2) {
input.firstParent(".input-boxed").addClass("is-invalid");
return;
}
@ -734,7 +734,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("bot_status", event => {
if(event.status === "error") {
if (event.status === "error") {
label.addClass("disabled");
input
.prop("checked", false)
@ -748,9 +748,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_bot_status_result", event => {
if(event.key !== "channel_commander") return;
if (event.key !== "channel_commander") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to change channel commander state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -788,7 +788,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("bot_status", event => {
if(event.status === "error") {
if (event.status === "error") {
label.addClass("disabled");
input
.prop("checked", false)
@ -802,9 +802,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_bot_status_result", event => {
if(event.key !== "priority_speaker") return;
if (event.key !== "priority_speaker") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to change priority speaker state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -842,7 +842,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
/* set status timeout */
{
let timeouts: {[key: string]:any} = {};
let timeouts: { [key: string]: any } = {};
event_registry.on("set_bot_status", event => {
clearTimeout(timeouts[event.key]);
timeouts[event.key] = setTimeout(() => {
@ -870,11 +870,11 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
let last_value = undefined;
const update_value = text => {
if(text) {
if (text) {
input.prop("disabled", true).addClass("disabled");
input.val("-1");
input.find("option[value=-1]").text(text);
} else if(last_value >= 0 && last_value <= 3) {
} else if (last_value >= 0 && last_value <= 3) {
input
.prop("disabled", false)
.removeClass("disabled");
@ -890,7 +890,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("playlist_status", event => {
if(event.status === "error") {
if (event.status === "error") {
update_value(event.error_msg || tr("error while loading"));
} else {
last_value = event.data.replay_mode;
@ -899,9 +899,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "replay_mode") return;
if (event.key !== "replay_mode") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to change replay mode"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -912,7 +912,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
input.on("change", event => {
const value = parseInt(input.val() as string);
console.log(value);
if(isNaN(value)) return;
if (isNaN(value)) return;
update_value(tr("applying..."));
event_registry.fire("set_playlist_status", {
@ -937,7 +937,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("playlist_status", event => {
if(event.status === "error")
if (event.status === "error")
input
.prop("disabled", true)
.val(null)
@ -952,9 +952,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "max_size") return;
if (event.key !== "max_size") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to change max playlist size"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -970,12 +970,12 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("focusout", event => {
const value = input.val() as string;
if(value === last_value) return;
if(value === "") {
if (value === last_value) return;
if (value === "") {
input.val(last_value);
return;
}
if(isNaN(parseInt(value))) {
if (isNaN(parseInt(value))) {
input.parentsUntil(".input-boxed").addClass("is-invalid");
return;
}
@ -1010,7 +1010,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("playlist_status", event => {
if(event.status === "error") {
if (event.status === "error") {
label.addClass("disabled");
input
.prop("checked", false)
@ -1024,9 +1024,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "delete_played") return;
if (event.key !== "delete_played") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to change delete state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -1064,7 +1064,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("playlist_status", event => {
if(event.status === "error") {
if (event.status === "error") {
label.addClass("disabled");
input
.prop("checked", false)
@ -1078,9 +1078,9 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
});
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "notify_song_change") return;
if (event.key !== "notify_song_change") return;
if(event.status !== "success")
if (event.status !== "success")
show_change_error(tr("Failed to change notify state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
@ -1118,7 +1118,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
/* set status timeout */
{
let timeouts: {[key: string]:any} = {};
let timeouts: { [key: string]: any } = {};
event_registry.on("set_playlist_status", event => {
clearTimeout(timeouts[event.key]);
timeouts[event.key] = setTimeout(() => {
@ -1162,7 +1162,7 @@ function build_settings_container(event_registry: Registry<modal.music_manage>,
{
let initialized = false;
event_registry.on("show_container", event => {
if(event.container !== "settings" || initialized) return;
if (event.container !== "settings" || initialized) return;
initialized = true;
event_registry.fire("query_bot_status");
@ -1203,15 +1203,15 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
let last_query;
input_search.on('keyup', event => {
const text = input_search.val() as string;
if(text === last_query) return;
if (text === last_query) return;
if(text)
event_registry.fire("filter_client_list", { filter: text });
if (text)
event_registry.fire("filter_client_list", {filter: text});
else
event_registry.fire("filter_client_list", { filter: undefined });
event_registry.fire("filter_client_list", {filter: undefined});
input_search.toggleClass("is-invalid", !list_shown && text === last_query);
if(!list_shown) {
if (!list_shown) {
button_search.prop("disabled", !text || !!search_timeout);
} else {
last_query = text;
@ -1219,7 +1219,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
});
input_search.on('keydown', event => {
if(event.key === "Enter" && !list_shown && !button_search.prop("disabled"))
if (event.key === "Enter" && !list_shown && !button_search.prop("disabled"))
button_search.trigger("click");
});
@ -1252,10 +1252,10 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
search_timeout = 0;
button_search.prop("disabled", !input_search.val());
if(event.status === "timeout") {
if (event.status === "timeout") {
createErrorModal(tr("Client search failed"), tr("Failed to perform client search.<br>Search resulted in a timeout.")).open();
return;
} else if(event.status === "error" || event.status === "empty") {
} else if (event.status === "error" || event.status === "empty") {
//TODO: Display the error somehow?
input_search.addClass("is-invalid");
return;
@ -1280,18 +1280,18 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
event_registry.on("special_client_list", data => {
button_refresh.prop("disabled", false);
container.find(".overlay").addClass("hidden");
if(data.status === "error-permission") {
if (data.status === "error-permission") {
const overlay = container.find(".overlay-query-error-permissions");
overlay.find("a").text(tr("Insufficient permissions"));
overlay.removeClass("hidden");
} else if(data.status === "success") {
} else if (data.status === "success") {
container_entries.find(".client").remove(); /* clear */
if(!data.clients.length) {
if (!data.clients.length) {
const overlay = container.find(".overlay-empty-list");
overlay.removeClass("hidden");
} else {
for(const client of data.clients) {
for (const client of data.clients) {
const tag = $.spawn("div").addClass("client").append(
htmltags.generate_client_object({
add_braces: false,
@ -1301,7 +1301,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
client_unique_id: client.unique_id
})
);
tag.on('dblclick', event => event_registry.fire("special_client_set", { client: client }));
tag.on('dblclick', event => event_registry.fire("special_client_set", {client: client}));
tag.attr("x-filter", client.database_id + "_" + client.name + "_" + client.unique_id);
container_entries.append(tag);
}
@ -1339,7 +1339,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
{
let shown;
event_registry.on('show_client_list', event => {
if(shown) return;
if (shown) return;
shown = true;
event_registry.fire("query_special_clients");
@ -1355,7 +1355,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
let shown = 0, hidden = 0;
container_entries.find(".client").each(function () {
const text = this.getAttribute("x-filter");
if(!filter || text.toLowerCase().indexOf(filter) != -1) {
if (!filter || text.toLowerCase().indexOf(filter) != -1) {
this.classList.remove("hidden");
shown++;
} else {
@ -1363,7 +1363,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
hidden++;
}
});
if(shown == 0 && hidden == 0) return;
if (shown == 0 && hidden == 0) return;
overlay.toggleClass("hidden", shown != 0);
};
@ -1386,7 +1386,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
const container = tag.find(".table-head .column-client-specific .client-info");
container.find(".button-client-deselect").on("click", event => {
event_registry.fire("special_client_set", { client: undefined });
event_registry.fire("special_client_set", {client: undefined});
});
event_registry.on("special_client_set", event => {
@ -1394,7 +1394,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
const client_container = container.find(".container-selected-client");
client_container.find(".htmltag-client").remove();
if(event.client) {
if (event.client) {
client_container.append(htmltags.generate_client_object({
client_unique_id: event.client.unique_id,
client_name: event.client.name,
@ -1432,7 +1432,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
const elem = $(_e) as JQuery<HTMLDivElement>;
const permission_name = elem.attr("x-permission");
if(!permission_name) return;
if (!permission_name) return;
const input = elem.find("input");
input.attr("maxlength", 6);
@ -1446,9 +1446,9 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
event_registry.on("general_permissions", event => {
input.prop("disabled", true).val(null);
if(event.status === "timeout") {
if (event.status === "timeout") {
input.attr("placeholder", tr("load timeout"));
} else if(event.status === "success") {
} else if (event.status === "success") {
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
const value = event.permissions ? event.permissions[permission_name] || 0 : 0;
@ -1460,24 +1460,24 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
});
event_registry.on("set_general_permission_result", event => {
if(event.key !== permission_name) return;
if (event.key !== permission_name) return;
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
if(event.status === "success") {
if (event.status === "success") {
input.val(event.value);
last_sync_value = event.value;
} else if(event.status === "error") {
if(typeof last_sync_value === "number") input.val(last_sync_value);
} else if (event.status === "error") {
if (typeof last_sync_value === "number") input.val(last_sync_value);
createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:{:br:}{}", event.error_msg)).open();
}
});
input.on("focusout", event => {
if(input.prop("disabled")) return;
if (input.prop("disabled")) return;
const value = parseInt(input.val() as string);
if(value === last_sync_value) return;
if (value === last_sync_value) return;
input.prop("disabled", true).val(null);
input.attr("placeholder", tr("applying..."));
@ -1496,10 +1496,10 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
const elem = $(_e) as JQuery<HTMLDivElement>;
const permission_name = elem.attr("x-permission");
if(!permission_name) return;
if (!permission_name) return;
const required_power = needed_power_map[permission_name];
if(!required_power) return;
if (!required_power) return;
let last_sync_value = undefined;
let current_tag: JQuery;
@ -1516,14 +1516,14 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
};
event_registry.on("general_permissions", event => {
if(event.status === "success")
if (event.status === "success")
last_sync_value = event.permissions ? event.permissions[permission_name] || 0 : 0;
});
event_registry.on("set_general_permission_result", event => {
if(event.key !== permission_name) return;
if (event.key !== permission_name) return;
if(event.status === "success")
if (event.status === "success")
last_sync_value = event.value;
});
@ -1532,26 +1532,26 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
});
const show_query_result = () => {
if(!current_tag) return;
if (!current_tag) return;
const container_groups = current_tag.find(".container-groups");
container_groups.children().remove();
current_tag.find(".container-status").addClass("hidden");
if(loading) {
if (loading) {
current_tag.find(".status-loading").removeClass("hidden");
} else if(!query_result || query_result.status === "error") {
} else if (!query_result || query_result.status === "error") {
current_tag
.find(".status-error").removeClass("hidden")
.text((query_result ? query_result.error_msg : "") || tr("failed to query data"));
} else if(query_result.status === "timeout") {
} else if (query_result.status === "timeout") {
current_tag
.find(".status-error").removeClass("hidden")
.text(tr("timeout while loading"));
} else {
let count = 0;
for(const group of (query_result.groups || [])) {
if(group.value !== -1 && group.value < last_sync_value) continue;
for (const group of (query_result.groups || [])) {
if (group.value !== -1 && group.value < last_sync_value) continue;
count++;
container_groups.append($.spawn("div").addClass("group").text(
@ -1559,7 +1559,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
));
}
if(count === 0) current_tag.find(".status-no-groups").removeClass("hidden");
if (count === 0) current_tag.find(".status-no-groups").removeClass("hidden");
}
};
@ -1567,7 +1567,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
on_show(tag: JQuery<HTMLElement>) {
current_tag = tag;
if(!query_result && !loading) {
if (!query_result && !loading) {
event_registry.fire("query_group_permissions", {
permission_name: required_power
});
@ -1581,7 +1581,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
});
event_registry.on("group_permissions", event => {
if(event.permission_name !== required_power) return;
if (event.permission_name !== required_power) return;
loading = false;
query_result = event;
@ -1598,9 +1598,9 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
/* permission set timeout */
{
let permission_timers: {[key: string]:any} = {};
let permission_timers: { [key: string]: any } = {};
event_registry.on("set_general_permission", event => {
if(permission_timers[event.key])
if (permission_timers[event.key])
clearTimeout(permission_timers[event.key]);
permission_timers[event.key] = setTimeout(() => {
event_registry.fire("set_general_permission_result", {
@ -1619,9 +1619,9 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
/* group query timeout */
{
let timers: {[key: string]:any} = {};
let timers: { [key: string]: any } = {};
event_registry.on("query_group_permissions", event => {
if(timers[event.permission_name])
if (timers[event.permission_name])
clearTimeout(timers[event.permission_name]);
timers[event.permission_name] = setTimeout(() => {
event_registry.fire("group_permissions", {
@ -1700,12 +1700,12 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
const container = tag.find(".column-client-specific");
let client_database_id = 0;
let needed_permissions: {[key: string]:number} = {};
let needed_permissions: { [key: string]: number } = {};
/* needed permissions updater */
{
event_registry.on("general_permissions", event => {
if(event.status !== "success") return;
if (event.status !== "success") return;
needed_permissions = event.permissions;
});
@ -1721,8 +1721,8 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
client_database_id = event.client ? event.client.database_id : 0;
container.find(".client-permission").toggleClass("hidden", !event.client);
if(client_database_id)
event_registry.fire("query_client_permissions", { client_database_id: client_database_id });
if (client_database_id)
event_registry.fire("query_client_permissions", {client_database_id: client_database_id});
});
const enabled_class = "client-apply";
@ -1740,7 +1740,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
let last_sync_value = undefined;
let hide_indicator = false;
if(typeof permission_needed_name !== "string") {
if (typeof permission_needed_name !== "string") {
log.warn(LogCategory.GENERAL, tr("Missing permission needed mapping for %s"), permission_name);
return;
}
@ -1759,15 +1759,15 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
});
event_registry.on("general_permissions", event => update_indicator());
event_registry.on("set_general_permission_result", event => {
if(event.key !== permission_needed_name) return;
if(event.status !== "success") return;
if (event.key !== permission_needed_name) return;
if (event.status !== "success") return;
update_indicator();
});
/* loading the permission */
event_registry.on("query_client_permissions", event => {
if(event.client_database_id !== client_database_id) return;
if (event.client_database_id !== client_database_id) return;
last_sync_value = undefined;
hide_indicator = true;
@ -1777,13 +1777,13 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
});
event_registry.on('client_permissions', event => {
if(event.client_database_id !== client_database_id) return;
if (event.client_database_id !== client_database_id) return;
hide_indicator = false;
input.prop("disabled", true).val(null);
if(event.status === "timeout") {
if (event.status === "timeout") {
input.attr("placeholder", tr("load timeout"));
} else if(event.status === "success") {
} else if (event.status === "success") {
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
const value = event.permissions ? event.permissions[permission_name] || 0 : 0;
@ -1798,10 +1798,10 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
/* permission editing */
input.attr("maxlength", 6);
input.on("focusout", event => {
if(!client_database_id) return;
if (!client_database_id) return;
const value = parseInt(input.val() as string);
if(value === last_sync_value) return;
if (value === last_sync_value) return;
input.prop("disabled", true).val(null);
input.attr("placeholder", tr("applying..."));
@ -1818,15 +1818,15 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
input.on("keyup", event => event.key === "Enter" && input.blur());
event_registry.on("set_client_permission_result", event => {
if(event.key !== permission_name) return;
if (event.key !== permission_name) return;
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
if(event.status === "success") {
if (event.status === "success") {
input.val(event.value);
last_sync_value = event.value;
} else if(event.status === "error") {
if(typeof last_sync_value === "number") input.val(last_sync_value);
} else if (event.status === "error") {
if (typeof last_sync_value === "number") input.val(last_sync_value);
createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:{:br:}{}", event.error_msg)).open();
}
hide_indicator = false;
@ -1836,9 +1836,9 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
/* client permission query timeout */
{
let timeout: {[key: number]: any} = {};
let timeout: { [key: number]: any } = {};
event_registry.on("query_client_permissions", event => {
if(timeout[event.client_database_id])
if (timeout[event.client_database_id])
clearTimeout(timeout[event.client_database_id]);
timeout[event.client_database_id] = setTimeout(() => {
event_registry.fire("client_permissions", {
@ -1855,10 +1855,10 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
/* client permission set timeout */
{
let timeout: {[key: string]: any} = {};
let timeout: { [key: string]: any } = {};
event_registry.on("set_client_permission", event => {
const key = event.client_database_id + "_" + event.key;
if(timeout[key])
if (timeout[key])
clearTimeout(timeout[key]);
timeout[key] = setTimeout(() => {
@ -1873,7 +1873,7 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
event_registry.on("set_client_permission_result", event => {
const key = event.client_database_id + "_" + event.key;
if(timeout[key]) {
if (timeout[key]) {
clearTimeout(timeout[key]);
delete timeout[key];
}
@ -1881,8 +1881,8 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
}
event_registry.on("refresh_permissions", event => {
if(client_database_id)
event_registry.fire("query_client_permissions", { client_database_id: client_database_id });
if (client_database_id)
event_registry.fire("query_client_permissions", {client_database_id: client_database_id});
});
tooltip.initialize(container);
}
@ -1896,10 +1896,10 @@ function build_permission_container(event_registry: Registry<modal.music_manage>
{
let initialized = false;
event_registry.on("show_container", event => {
if(event.container !== "permissions" || initialized) return;
if (event.container !== "permissions" || initialized) return;
initialized = true;
event_registry.fire("special_client_set", { client: undefined });
event_registry.fire("special_client_set", {client: undefined});
event_registry.fire("query_general_permissions", {});
});
}

View File

@ -1,13 +1,12 @@
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import {tra} from "tc-shared/i18n/localize";
import {Registry} from "tc-shared/events";
import {modal as emodal, Registry} from "tc-shared/events";
import {modal_settings} from "tc-shared/ui/modal/ModalSettings";
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
import {initialize_audio_microphone_controller, MicrophoneSettingsEvents} from "tc-shared/ui/modal/settings/Microphone";
import {MicrophoneSettings} from "tc-shared/ui/modal/settings/MicrophoneRenderer";
import * as React from "react";
import * as ReactDOM from "react-dom";
import { modal as emodal } from "tc-shared/events";
export interface EventModalNewcomer {
"show_step": {
@ -25,25 +24,25 @@ export interface EventModalNewcomer {
}
}
const next_step: {[key: string]:string} = {
const next_step: { [key: string]: string } = {
"welcome": "microphone",
//"microphone": app.is_web() ? "identity" : "speaker", /* speaker setup only for the native client! */
"microphone": "identity",
"speaker": "identity",
"identity": "finish"
};
const last_step: {[key: string]:string} = (() => {
const last_step: { [key: string]: string } = (() => {
const result = {};
for(const key of Object.keys(next_step))
if(!result[next_step[key]])
for (const key of Object.keys(next_step))
if (!result[next_step[key]])
result[next_step[key]] = key;
return result;
})();
export function openModalNewcomer() : Modal {
export function openModalNewcomer(): Modal {
let modal = createModal({
header: tra("Welcome to the {}", __build.version === "web" ? "TeaSpeak - Web client" : "TeaSpeak - Client"),
body: () => $("#tmpl_newcomer").renderTag({
body: () => $("#tmpl_newcomer").renderTag({
is_web: __build.version === "web"
}).children(),
footer: null,
@ -64,9 +63,9 @@ export function openModalNewcomer() : Modal {
initializeStepFinish(modal.htmlTag.find(".container-body .step.step-finish"), event_registry);
event_registry.on("exit_guide", event => {
if(event.ask_yesno) {
if (event.ask_yesno) {
spawnYesNo(tr("Are you sure?"), tr("Do you really want to skip the basic setup guide?"), result => {
if(result)
if (result)
event_registry.fire("exit_guide", {ask_yesno: false});
});
} else {
@ -101,23 +100,23 @@ function initializeBasicFunctionality(tag: JQuery, event_registry: Registry<Even
let allowNextStep = true;
button_last_step.on('click', () => {
if(last_step[current_step])
event_registry.fire("show_step", { step: last_step[current_step] as any });
if (last_step[current_step])
event_registry.fire("show_step", {step: last_step[current_step] as any});
else
event_registry.fire("exit_guide", {ask_yesno: true});
});
let current_step;
button_next_step.on('click', event => {
if(!allowNextStep) {
if (!allowNextStep) {
event_registry.fire("action-next-help");
return;
}
if(next_step[current_step]) {
event_registry.fire("show_step", { step: next_step[current_step] as any });
if (next_step[current_step]) {
event_registry.fire("show_step", {step: next_step[current_step] as any});
} else {
event_registry.fire("exit_guide", { ask_yesno: false });
event_registry.fire("exit_guide", {ask_yesno: false});
}
});
@ -137,17 +136,17 @@ function initializeBasicFunctionality(tag: JQuery, event_registry: Registry<Even
function initializeStepWelcome(tag: JQuery, event_registry: Registry<EventModalNewcomer>) {
event_registry.on("show_step", e => {
if(e.step !== "welcome") return;
if (e.step !== "welcome") return;
event_registry.fire_async("step-status", { allowNextStep: true, allowPreviousStep: true });
event_registry.fire_async("step-status", {allowNextStep: true, allowPreviousStep: true});
});
}
function initializeStepFinish(tag: JQuery, event_registry: Registry<EventModalNewcomer>) {
event_registry.on("show_step", e => {
if(e.step !== "finish") return;
if (e.step !== "finish") return;
event_registry.fire_async("step-status", {allowNextStep: true, allowPreviousStep: true });
event_registry.fire_async("step-status", {allowNextStep: true, allowPreviousStep: true});
});
}
@ -155,17 +154,20 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<EventModal
const profile_events = new Registry<emodal.settings.profiles>();
profile_events.enableDebug("settings-identity");
modal_settings.initialize_identity_profiles_controller(profile_events);
modal_settings.initialize_identity_profiles_view(tag, profile_events, { forum_setuppable: false });
modal_settings.initialize_identity_profiles_view(tag, profile_events, {forum_setuppable: false});
let stepShown = false;
let help_animation_done = false;
const update_step_status = () => {
event_registry.fire_async("step-status", { allowNextStep: help_animation_done, allowPreviousStep: help_animation_done });
event_registry.fire_async("step-status", {
allowNextStep: help_animation_done,
allowPreviousStep: help_animation_done
});
};
profile_events.on("query-profile-validity-result", event => stepShown && event.status === "success" && event.valid && update_step_status());
event_registry.on("show_step", e => {
stepShown = e.step === "identity";
if(!stepShown) return;
if (!stepShown) return;
update_step_status();
});
@ -187,7 +189,7 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<EventModal
};
event_registry.on("show_step", event => {
if(helpStep > 0 || event.step !== "identity") {
if (helpStep > 0 || event.step !== "identity") {
document.body.removeEventListener("mousedown", listenerClick);
return;
}
@ -323,12 +325,12 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<EventModal
const listenerClick = () => event_registry.fire("action-next-help");
event_registry.on("action-next-help", () => {
if(!stepShown) {
if (!stepShown) {
return;
}
const fn = steps[helpStep++];
if(typeof fn === "function") {
if (typeof fn === "function") {
fn();
}
update_step_status();
@ -342,21 +344,21 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<EventMod
let stepShown = false;
const settingEvents = new Registry<MicrophoneSettingsEvents>();
settingEvents.on("query_help", () => settingEvents.fire_async("notify_highlight", { field: helpStep <= 2 ? ("hs-" + helpStep) as any : undefined }));
settingEvents.on("query_help", () => settingEvents.fire_async("notify_highlight", {field: helpStep <= 2 ? ("hs-" + helpStep) as any : undefined}));
settingEvents.on("action_help_click", () => {
if(!stepShown) {
if (!stepShown) {
return;
}
helpStep++;
settingEvents.fire("query_help");
event_registry.fire_async("step-status", { allowNextStep: helpStep > 2, allowPreviousStep: helpStep > 2 })
event_registry.fire_async("step-status", {allowNextStep: helpStep > 2, allowPreviousStep: helpStep > 2})
});
event_registry.on("action-next-help", () => settingEvents.fire("action_help_click"));
initialize_audio_microphone_controller(settingEvents);
ReactDOM.render(<MicrophoneSettings events={settingEvents} />, tag[0]);
ReactDOM.render(<MicrophoneSettings events={settingEvents}/>, tag[0]);
modal.close_listener.push(() => {
settingEvents.fire("notify_destroy");
@ -366,10 +368,10 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<EventMod
event_registry.on("show_step", event => {
stepShown = event.step === "microphone";
if(!stepShown) {
if (!stepShown) {
return;
}
event_registry.fire_async("step-status", { allowNextStep: helpStep > 2, allowPreviousStep: helpStep > 2 });
event_registry.fire_async("step-status", {allowNextStep: helpStep > 2, allowPreviousStep: helpStep > 2});
});
}

View File

@ -1,13 +1,14 @@
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import * as htmltags from "tc-shared/ui/htmltags";
import {ConnectionHandler} from "../../ConnectionHandler";
import {createModal, Modal} from "../../ui/elements/Modal";
import * as htmltags from "../../ui/htmltags";
import * as moment from "moment";
import {renderBBCodeAsJQuery} from "tc-shared/text/bbcode";
import {renderBBCodeAsJQuery} from "../../text/bbcode";
let global_modal: PokeModal;
export interface ServerEntry {
source: ConnectionHandler;
add_message(invoker: PokeInvoker, message: string);
}
@ -29,15 +30,18 @@ class PokeModal {
this._handle.close_listener.push(() => this._handle_close());
}
modal() { return this._handle; }
modal() {
return this._handle;
}
add_poke(source: ConnectionHandler, invoker: PokeInvoker, message: string) {
let handler: ServerEntry;
for(const entry of this.source_map)
if(entry.source === source) {
for (const entry of this.source_map)
if (entry.source === source) {
handler = entry;
break;
}
if(!handler) {
if (!handler) {
const html_tag = $.spawn("div").addClass("server");
const poke_list = $.spawn("div").addClass("poke-list");
$.spawn("div")
@ -58,9 +62,9 @@ class PokeModal {
client_name: invoker.name,
client_unique_id: invoker.unique_id
}))).appendTo(container);
if(message) {
if (message) {
$.spawn("div").addClass("text").text(tr("pokes you:")).appendTo(container);
$.spawn("div").addClass("poke-message").append(...renderBBCodeAsJQuery(message, { convertSingleUrls: false })).appendTo(container);
$.spawn("div").addClass("poke-message").append(...renderBBCodeAsJQuery(message, {convertSingleUrls: false})).appendTo(container);
} else {
$.spawn("div").addClass("text").text(tr("pokes you.")).appendTo(container);
}
@ -87,7 +91,7 @@ export type PokeInvoker = {
};
export function spawnPoke(source: ConnectionHandler, invoker: PokeInvoker, message: string) {
if(!global_modal)
if (!global_modal)
global_modal = new PokeModal();
global_modal.add_poke(source, invoker, message);
global_modal.modal().open();

View File

@ -1,7 +1,7 @@
import {createErrorModal, createModal} from "tc-shared/ui/elements/Modal";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {SingleCommandHandler} from "tc-shared/connection/ConnectionBase";
import {createErrorModal, createModal} from "../../ui/elements/Modal";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {ConnectionHandler} from "../../ConnectionHandler";
import {SingleCommandHandler} from "../../connection/ConnectionBase";
export function spawnQueryCreate(connection: ConnectionHandler, callback_created?: (user, pass) => any) {
let modal;
@ -14,7 +14,7 @@ export function spawnQueryCreate(connection: ConnectionHandler, callback_created
template.find(".button-close").on('click', event => modal.close());
template.find(".button-create").on('click', event => {
const name = template.find(".input-name").val() as string;
if(name.length < 3 || name.length > 64) {
if (name.length < 3 || name.length > 64) {
createErrorModal(tr("Invalid username"), tr("Please enter a valid name!")).open();
return;
}
@ -28,7 +28,7 @@ export function spawnQueryCreate(connection: ConnectionHandler, callback_created
password: json.client_login_password
}, true);
if(callback_created)
if (callback_created)
callback_created(name, json.client_login_password);
return true;
},
@ -38,7 +38,7 @@ export function spawnQueryCreate(connection: ConnectionHandler, callback_created
connection.serverConnection.send_command("querycreate", {
client_login_name: name
}).catch(error => {
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.extra_message || error.message;
createErrorModal(tr("Unable to create account"), tr("Failed to create account<br>Message: ") + error).open();
}).then(() => connection.serverConnection.command_handler_boss().remove_single_handler(single_handler));

View File

@ -157,18 +157,18 @@ export function spawnQueryManage(client: ConnectionHandler) {
*/
//tmpl_query_manager
import {createErrorModal, createInfoModal, createInputModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {CommandResult, QueryListEntry} from "tc-shared/connection/ServerConnectionDeclaration";
import {SingleCommandHandler} from "tc-shared/connection/ConnectionBase";
import {copy_to_clipboard} from "tc-shared/utils/helpers";
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
import {LogCategory} from "tc-shared/log";
import PermissionType from "tc-shared/permission/PermissionType";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import * as log from "tc-shared/log";
import {spawnQueryCreate, spawnQueryCreated} from "tc-shared/ui/modal/ModalQuery";
import {formatMessage} from "tc-shared/ui/frames/chat";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {createErrorModal, createInfoModal, createInputModal, createModal, Modal} from "../../ui/elements/Modal";
import {CommandResult, QueryListEntry} from "../../connection/ServerConnectionDeclaration";
import {SingleCommandHandler} from "../../connection/ConnectionBase";
import {copy_to_clipboard} from "../../utils/helpers";
import {spawnYesNo} from "../../ui/modal/ModalYesNo";
import * as log from "../../log";
import {LogCategory} from "../../log";
import PermissionType from "../../permission/PermissionType";
import {ConnectionHandler} from "../../ConnectionHandler";
import {spawnQueryCreate, spawnQueryCreated} from "../../ui/modal/ModalQuery";
import {formatMessage} from "../../ui/frames/chat";
import {ErrorCode} from "../../connection/ErrorCode";
export function spawnQueryManage(client: ConnectionHandler) {
let modal: Modal;
@ -210,7 +210,7 @@ export function spawnQueryManage(client: ConnectionHandler) {
button_create.prop('disabled', !permission_create);
const set_error = (error: string | undefined) => {
if(typeof(error) === "string")
if (typeof (error) === "string")
container_list_error.text(error).show();
else
container_list_error.hide();
@ -228,12 +228,12 @@ export function spawnQueryManage(client: ConnectionHandler) {
current_server = server_id;
client.serverConnection.command_helper.requestQueryList(server_id).then(result => {
if(!result || !result.queries.length) {
if (!result || !result.queries.length) {
container_list_empty.text(tr("No queries available"));
return;
}
for(const entry of result.queries) {
for (const entry of result.queries) {
const tag = $.spawn("div").addClass("entry").text(entry.username + " (" + entry.unique_id + ")");
tag.on('click', event => {
container_list.find(".selected").removeClass("selected");
@ -241,11 +241,11 @@ export function spawnQueryManage(client: ConnectionHandler) {
set_selected(entry, false);
});
container_list.append(tag);
if(entry.username === selected_entry) tag.trigger('click');
if (entry.username === selected_entry) tag.trigger('click');
const text_mesh = (entry.username + " " + entry.unique_id + " " + entry.bounded_server).toLowerCase();
filter_callbacks.push(text => {
if(typeof(text) === "undefined" || text_mesh.indexOf(text) != -1) {
if (typeof (text) === "undefined" || text_mesh.indexOf(text) != -1) {
tag.show();
return true;
} else {
@ -260,7 +260,7 @@ export function spawnQueryManage(client: ConnectionHandler) {
button_update.prop('disabled', false);
}).catch(error => {
button_update.prop('disabled', false);
if(error instanceof CommandResult && error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
if (error instanceof CommandResult && error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
set_error(tr("No permissions"));
return;
}
@ -275,10 +275,10 @@ export function spawnQueryManage(client: ConnectionHandler) {
};
const set_selected = (entry: QueryListEntry | undefined, force: boolean) => {
if(entry === selected_query && !force) return;
if (entry === selected_query && !force) return;
selected_query = entry;
if(!selected_query) {
if (!selected_query) {
detail_name.text("-");
detail_unique_id.text("-");
detail_bound_server.text("-");
@ -289,16 +289,16 @@ export function spawnQueryManage(client: ConnectionHandler) {
} else {
detail_name.text(selected_query.username);
detail_unique_id.text(selected_query.unique_id);
if(selected_query.bounded_server == 0)
if (selected_query.bounded_server == 0)
detail_bound_server.text(tr("On the instance"));
else if(selected_query.bounded_server === current_server)
else if (selected_query.bounded_server === current_server)
detail_bound_server.text(tr("On the current server"));
else
detail_bound_server.text(selected_query.bounded_server.toString());
button_delete.prop('disabled', !permission_delete && !(selected_query.unique_id === client.getClient().properties.client_unique_identifier && permission_delete_own));
button_rename.prop('disabled', !permission_rename && !(selected_query.unique_id === client.getClient().properties.client_unique_identifier && permission_rename_own));
if(selected_query.bounded_server != 0) {
if (selected_query.bounded_server != 0) {
button_change_password.prop('disabled', !permission_password && !(selected_query.unique_id === client.getClient().properties.client_unique_identifier && permission_password_own));
} else {
button_change_password.prop('disabled', !permission_password_global && !(selected_query.unique_id === client.getClient().properties.client_unique_identifier && permission_password_own));
@ -308,11 +308,11 @@ export function spawnQueryManage(client: ConnectionHandler) {
const update_filter = () => {
let value = input_filter.val() as string;
if(!value) value = undefined;
if (!value) value = undefined;
else value = value.toLowerCase();
const shown = filter_callbacks.filter(e => e(value)).length;
if(shown > 0) {
if (shown > 0) {
container_list_empty.hide();
} else {
container_list_empty.text(tr("No accounts found")).show();
@ -323,7 +323,7 @@ export function spawnQueryManage(client: ConnectionHandler) {
/* all buttons */
{
detail_unique_id_copy.on('click', event => {
if(!selected_query) return;
if (!selected_query) return;
copy_to_clipboard(selected_query.unique_id);
createInfoModal(tr("Unique ID copied"), tr("The unique id has been successfully copied to your clipboard.")).open();
@ -334,17 +334,17 @@ export function spawnQueryManage(client: ConnectionHandler) {
});
button_delete.on('click', event => {
if(!selected_query) return;
if (!selected_query) return;
spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this account?"), result => {
if(result) {
if (result) {
client.serverConnection.send_command("querydelete", {
client_login_name: selected_query.username
}).then(() => {
createInfoModal(tr("Account successfully deleted"), tr("The query account has been successfully deleted!")).open();
update_list(undefined);
}).catch(error => {
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.extra_message || error.message;
createErrorModal(tr("Unable to delete account"), formatMessage(tr("Failed to delete account{:br:}Message: {}"), error)).open();
});
@ -353,10 +353,10 @@ export function spawnQueryManage(client: ConnectionHandler) {
});
button_rename.on('click', () => {
if(!selected_query) return;
if (!selected_query) return;
createInputModal(tr("Change account name"), tr("Enter the new name for the login:"), text => text.length >= 3, result => {
if(result) {
if (result) {
client.serverConnection.send_command("queryrename", {
client_login_name: selected_query.username,
client_new_login_name: result
@ -364,7 +364,7 @@ export function spawnQueryManage(client: ConnectionHandler) {
createInfoModal(tr("Account successfully renamed"), tr("The query account has been renamed!")).open();
update_list(result as string);
}).catch(error => {
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.extra_message || error.message;
createErrorModal(tr("Unable to rename account"), formatMessage(tr("Failed to rename account{:br:}Message: {}"), error)).open();
});
@ -373,10 +373,10 @@ export function spawnQueryManage(client: ConnectionHandler) {
});
button_change_password.on('click', () => {
if(!selected_query) return;
if (!selected_query) return;
createInputModal(tr("Change account's password"), tr("Enter a new password (leave blank for auto generation):"), text => true, result => {
if(result !== false) {
if (result !== false) {
const single_handler: SingleCommandHandler = {
command: "notifyquerypasswordchanges",
function: command => {
@ -395,7 +395,7 @@ export function spawnQueryManage(client: ConnectionHandler) {
client_login_password: result
}).catch(error => {
client.serverConnection.command_handler_boss().remove_single_handler(single_handler);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.extra_message || error.message;
createErrorModal(tr("Unable to change password"), formatMessage(tr("Failed to change password{:br:}Message: {}"), error)).open();
});

View File

@ -1,35 +1,35 @@
import {ServerEntry, ServerProperties} from "tc-shared/tree/Server";
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import PermissionType from "tc-shared/permission/PermissionType";
import {GroupManager} from "tc-shared/permission/GroupManager";
import {hashPassword} from "tc-shared/utils/helpers";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import {spawnIconSelect} from "tc-shared/ui/modal/ModalIconSelect";
import {network} from "tc-shared/ui/frames/chat";
import {ServerEntry, ServerProperties} from "../../tree/Server";
import {createModal, Modal} from "../../ui/elements/Modal";
import PermissionType from "../../permission/PermissionType";
import {GroupManager} from "../../permission/GroupManager";
import {hashPassword} from "../../utils/helpers";
import * as tooltip from "../../ui/elements/Tooltip";
import {spawnIconSelect} from "../../ui/modal/ModalIconSelect";
import {network} from "../../ui/frames/chat";
export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => Promise<void>) {
const properties = Object.assign({}, server.properties);
let _valid_states: {[key: string]:boolean} = {
let _valid_states: { [key: string]: boolean } = {
general: false
};
let _toggle_valid = (key: string | undefined, value?: boolean) => {
if(typeof(key) === "string") {
if (typeof (key) === "string") {
_valid_states[key] = value;
}
let flag = true;
for(const key of Object.keys(_valid_states))
if(!_valid_states[key]) {
for (const key of Object.keys(_valid_states))
if (!_valid_states[key]) {
flag = false;
break;
}
if(flag) {
if (flag) {
flag = false;
for(const property_name of Object.keys(properties)) {
if(server.properties[property_name] !== properties[property_name]) {
for (const property_name of Object.keys(properties)) {
if (server.properties[property_name] !== properties[property_name]) {
flag = true;
break;
}
@ -43,7 +43,7 @@ export function createServerModal(server: ServerEntry, callback: (properties?: S
header: tr("Manage the Virtual Server"),
body: () => {
const template = $("#tmpl_server_edit").renderTag(Object.assign(Object.assign({}, server.properties), {
server_icon: server.channelTree.client.fileManager.icons.generateTag(server.properties.virtualserver_icon_id)
server_icon: server.channelTree.client.fileManager.icons.generateTag(server.properties.virtualserver_icon_id)
}));
/* the tab functionality */
@ -80,8 +80,8 @@ export function createServerModal(server: ServerEntry, callback: (properties?: S
const button_save = modal.htmlTag.find(".button-save");
button_save.on('click', event => {
const changed = {} as ServerProperties;
for(const property_name of Object.keys(properties))
if(server.properties[property_name] !== properties[property_name])
for (const property_name of Object.keys(properties))
if (server.properties[property_name] !== properties[property_name])
changed[property_name] = properties[property_name];
callback(changed).then(() => {
_toggle_valid(undefined);
@ -125,7 +125,7 @@ function apply_general_listener(tag: JQuery, server: ServerEntry, properties: Se
console.log("Selected icon ID: %d", id);
properties.virtualserver_icon_id = id;
callback_valid(undefined); //Toggle save button update
}, properties.virtualserver_icon_id);
}, properties.virtualserver_icon_id);
});
tag.find(".button-icon-remove").on('click', event => {
@ -148,7 +148,7 @@ function apply_general_listener(tag: JQuery, server: ServerEntry, properties: Se
container.on('change', event => {
const password = container.val() as string;
properties.virtualserver_flag_password = !!password;
if(properties.virtualserver_flag_password) {
if (properties.virtualserver_flag_password) {
hashPassword(password).then(pass => properties.virtualserver_password = pass);
}
callback_valid(undefined); //Toggle save button update
@ -196,7 +196,7 @@ function apply_general_listener(tag: JQuery, server: ServerEntry, properties: Se
const input = container.find("textarea");
const insert_tag = (open: string, close: string) => {
if(input.prop("disabled"))
if (input.prop("disabled"))
return;
const node = input[0] as HTMLTextAreaElement;
@ -347,27 +347,27 @@ function apply_network_listener(tag: JQuery, server: ServerEntry, properties: Se
}
/* quota update task */
if(server.channelTree.client.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CONNECTIONINFO_VIEW).granted(1)) {
if (server.channelTree.client.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CONNECTIONINFO_VIEW).granted(1)) {
const month_bytes_downloaded = tag.find(".value.virtualserver_month_bytes_downloaded")[0];
const month_bytes_uploaded = tag.find(".value.virtualserver_month_bytes_uploaded")[0];
const total_bytes_downloaded = tag.find(".value.virtualserver_total_bytes_downloaded")[0];
const total_bytes_uploaded = tag.find(".value.virtualserver_total_bytes_uploaded")[0];
let id = setInterval(() => {
if(!modal.shown) {
if (!modal.shown) {
clearInterval(id);
return;
}
server.request_connection_info().then(info => {
if(info.connection_filetransfer_bytes_sent_month && month_bytes_downloaded)
if (info.connection_filetransfer_bytes_sent_month && month_bytes_downloaded)
month_bytes_downloaded.innerText = network.format_bytes(info.connection_filetransfer_bytes_sent_month);
if(info.connection_filetransfer_bytes_received_month && month_bytes_uploaded)
if (info.connection_filetransfer_bytes_received_month && month_bytes_uploaded)
month_bytes_uploaded.innerText = network.format_bytes(info.connection_filetransfer_bytes_received_month);
if(info.connection_filetransfer_bytes_sent_total && total_bytes_downloaded)
if (info.connection_filetransfer_bytes_sent_total && total_bytes_downloaded)
total_bytes_downloaded.innerText = network.format_bytes(info.connection_filetransfer_bytes_sent_total);
if(info.connection_filetransfer_bytes_received_total && total_bytes_uploaded)
if (info.connection_filetransfer_bytes_received_total && total_bytes_uploaded)
total_bytes_uploaded.innerText = network.format_bytes(info.connection_filetransfer_bytes_received_total);
});
}, 1000);
@ -624,10 +624,10 @@ function apply_misc_listener(tag: JQuery, server: ServerEntry, properties: Serve
callback_valid(undefined); //Toggle save button update
}).prop("disabled", !permission).firstParent(".input-boxed").toggleClass("disabled", !permission);
for(const group of server.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
if(group.type != 2) continue;
for (const group of server.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
if (group.type != 2) continue;
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
if(group.id == server.properties.virtualserver_default_server_group)
if (group.id == server.properties.virtualserver_default_server_group)
group_tag.prop("selected", true);
group_tag.appendTo(container);
}
@ -643,10 +643,10 @@ function apply_misc_listener(tag: JQuery, server: ServerEntry, properties: Serve
callback_valid(undefined); //Toggle save button update
}).prop("disabled", !permission).firstParent(".input-boxed").toggleClass("disabled", !permission);
for(const group of server.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
if(group.type != 2) continue;
for (const group of server.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
if (group.type != 2) continue;
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
if(group.id == server.properties.virtualserver_default_music_group)
if (group.id == server.properties.virtualserver_default_music_group)
group_tag.prop("selected", true);
group_tag.appendTo(container);
}
@ -662,10 +662,10 @@ function apply_misc_listener(tag: JQuery, server: ServerEntry, properties: Serve
callback_valid(undefined); //Toggle save button update
}).prop("disabled", !permission).firstParent(".input-boxed").toggleClass("disabled", !permission);
for(const group of server.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
if(group.type != 2) continue;
for (const group of server.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
if (group.type != 2) continue;
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
if(group.id == server.properties.virtualserver_default_channel_admin_group)
if (group.id == server.properties.virtualserver_default_channel_admin_group)
group_tag.prop("selected", true);
group_tag.appendTo(container);
}
@ -681,10 +681,10 @@ function apply_misc_listener(tag: JQuery, server: ServerEntry, properties: Serve
callback_valid(undefined); //Toggle save button update
}).prop("disabled", !permission).firstParent(".input-boxed").toggleClass("disabled", !permission);
for(const group of server.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
if(group.type != 2) continue;
for (const group of server.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
if (group.type != 2) continue;
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
if(group.id == server.properties.virtualserver_default_channel_group)
if (group.id == server.properties.virtualserver_default_channel_group)
group_tag.prop("selected", true);
group_tag.appendTo(container);
}

View File

@ -2,18 +2,18 @@ import {
openServerInfoBandwidth,
RequestInfoStatus,
ServerBandwidthInfoUpdateCallback
} from "tc-shared/ui/modal/ModalServerInfoBandwidth";
import {ServerEntry} from "tc-shared/tree/Server";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {createErrorModal, createModal, Modal} from "tc-shared/ui/elements/Modal";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import * as i18nc from "tc-shared/i18n/country";
import {format_time, formatMessage} from "tc-shared/ui/frames/chat";
import {Hostbanner} from "tc-shared/ui/frames/hostbanner";
} from "../../ui/modal/ModalServerInfoBandwidth";
import {ServerEntry} from "../../tree/Server";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {createErrorModal, createModal, Modal} from "../../ui/elements/Modal";
import * as log from "../../log";
import {LogCategory} from "../../log";
import * as tooltip from "../../ui/elements/Tooltip";
import * as i18nc from "../../i18n/country";
import {format_time, formatMessage} from "../../ui/frames/chat";
import {Hostbanner} from "../../ui/frames/hostbanner";
import * as moment from "moment";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {ErrorCode} from "../../connection/ErrorCode";
export function openServerInfo(server: ServerEntry) {
let modal: Modal;
@ -41,7 +41,7 @@ export function openServerInfo(server: ServerEntry) {
update_values();
}).catch(error => {
log.warn(LogCategory.CLIENT, tr("Failed to refresh server properties: %o"), error);
if(error instanceof CommandResult)
if (error instanceof CommandResult)
error = error.extra_message || error.message;
createErrorModal(tr("Refresh failed"), formatMessage(tr("Failed to refresh server properties.{:br:}Error: {}"), error)).open();
}).then(() => {
@ -59,7 +59,7 @@ export function openServerInfo(server: ServerEntry) {
const updater = setInterval(() => {
server.request_connection_info().then(info => update_callbacks.forEach(e => e(RequestInfoStatus.SUCCESS, info))).catch(error => {
if(error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
if (error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) {
update_callbacks.forEach(e => e(RequestInfoStatus.NO_PERMISSION));
return;
}
@ -71,7 +71,9 @@ export function openServerInfo(server: ServerEntry) {
modal.htmlTag.find(".button-close").on('click', event => modal.close());
modal.htmlTag.find(".button-show-bandwidth").on('click', event => {
const custom_callbacks = [];
const custom_callback_caller = (status, info) => { custom_callbacks.forEach(e => e(status, info)); };
const custom_callback_caller = (status, info) => {
custom_callbacks.forEach(e => e(status, info));
};
update_callbacks.push(custom_callback_caller);
openServerInfoBandwidth(server, custom_callbacks).close_listener.push(() => {
@ -92,7 +94,7 @@ function apply_hostbanner(server: ServerEntry, tag: JQuery) {
const htag = Hostbanner.generate_tag(server.properties.virtualserver_hostbanner_gfx_url, server.properties.virtualserver_hostbanner_gfx_interval, server.properties.virtualserver_hostbanner_mode);
htag.then(t => {
if(!t) return;
if (!t) return;
tag.removeClass("hidden");
container.append(t);
@ -120,11 +122,11 @@ function apply_category_1(server: ServerEntry, tag: JQuery, update_callbacks: Se
const container = tag.find(".server-slots");
let text = server.properties.virtualserver_clientsonline + "/" + server.properties.virtualserver_maxclients;
if(server.properties.virtualserver_queryclientsonline)
if (server.properties.virtualserver_queryclientsonline)
text += " +" + (server.properties.virtualserver_queryclientsonline > 1 ?
server.properties.virtualserver_queryclientsonline + " " + tr("Queries") :
server.properties.virtualserver_queryclientsonline + " " + tr("Query"));
if(server.properties.virtualserver_reserved_slots)
server.properties.virtualserver_queryclientsonline + " " + tr("Queries") :
server.properties.virtualserver_queryclientsonline + " " + tr("Query"));
if (server.properties.virtualserver_reserved_slots)
text += " (" + server.properties.virtualserver_reserved_slots + " " + tr("Reserved") + ")";
container.text(text);
@ -184,9 +186,9 @@ function apply_category_2(server: ServerEntry, tag: JQuery, update_callbacks: Se
const container = tag.find(".server-ping");
container.text(tr("calculating..."));
update_callbacks.push((status, data) => {
if(status === RequestInfoStatus.SUCCESS)
if (status === RequestInfoStatus.SUCCESS)
container.text(data.connection_ping.toFixed(0) + " " + "ms");
else if(status === RequestInfoStatus.NO_PERMISSION)
else if (status === RequestInfoStatus.NO_PERMISSION)
container.text(tr("No Permissions"));
else
container.text(tr("receiving..."));
@ -198,9 +200,9 @@ function apply_category_2(server: ServerEntry, tag: JQuery, update_callbacks: Se
const container = tag.find(".server-packet-loss");
container.text(tr("receiving..."));
update_callbacks.push((status, data) => {
if(status === RequestInfoStatus.SUCCESS)
if (status === RequestInfoStatus.SUCCESS)
container.text(data.connection_packetloss_total.toFixed(2) + "%");
else if(status === RequestInfoStatus.NO_PERMISSION)
else if (status === RequestInfoStatus.NO_PERMISSION)
container.text(tr("No Permissions"));
else
container.text(tr("receiving..."));
@ -218,9 +220,9 @@ function apply_category_3(server: ServerEntry, tag: JQuery, update_callbacks: Se
/* voice encryption */
{
const container = tag.find(".server-voice-encryption");
if(server.properties.virtualserver_codec_encryption_mode == 0)
if (server.properties.virtualserver_codec_encryption_mode == 0)
container.text(tr("Globally off"));
else if(server.properties.virtualserver_codec_encryption_mode == 1)
else if (server.properties.virtualserver_codec_encryption_mode == 1)
container.text(tr("Individually configured per channel"));
else
container.text(tr("Globally on"));

View File

@ -1,10 +1,10 @@
import {ServerConnectionInfo, ServerEntry} from "tc-shared/tree/Server";
import {createModal, Modal} from "tc-shared/ui/elements/Modal";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {Graph} from "tc-shared/ui/elements/NetGraph";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import {network} from "tc-shared/ui/frames/chat";
import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {ServerConnectionInfo, ServerEntry} from "../../tree/Server";
import {createModal, Modal} from "../../ui/elements/Modal";
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
import {Graph} from "../../ui/elements/NetGraph";
import * as tooltip from "../../ui/elements/Tooltip";
import {network} from "../../ui/frames/chat";
import {ErrorCode} from "../../connection/ErrorCode";
export enum RequestInfoStatus {
SUCCESS,

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import {BodyCreator, createModal, ModalFunctions} from "tc-shared/ui/elements/Modal";
import {BodyCreator, createModal, ModalFunctions} from "../../ui/elements/Modal";
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: {
text_yes?: string,
@ -17,14 +17,14 @@ export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_:
props.header = header;
props.template_properties.question = ModalFunctions.jqueriefy(body);
props.closeable = typeof(properties.closeable) !== "boolean" || properties.closeable;
props.closeable = typeof (properties.closeable) !== "boolean" || properties.closeable;
const modal = createModal(props);
let submited = false;
const button_yes = modal.htmlTag.find(".button-yes");
const button_no = modal.htmlTag.find(".button-no");
button_yes.on('click', event => {
if(!submited) {
if (!submited) {
submited = true;
callback(true);
}
@ -32,7 +32,7 @@ export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_:
});
button_no.on('click', event => {
if(!submited) {
if (!submited) {
submited = true;
callback(false);
}

View File

@ -1,9 +1,9 @@
import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import {CssEditorEvents, CssVariable} from "tc-shared/ui/modal/css-editor/Definitions";
import {spawnExternalModal} from "tc-shared/ui/react-elements/external-modal";
import {Registry} from "tc-shared/events";
import {LogCategory, logWarn} from "tc-shared/log";
import {CssEditorEvents, CssVariable} from "../../../ui/modal/css-editor/Definitions";
import {spawnExternalModal} from "../../../ui/react-elements/external-modal";
import {Registry} from "../../../events";
import {LogCategory, logWarn} from "../../../log";
interface CustomVariable {
name: string;
@ -12,17 +12,17 @@ interface CustomVariable {
}
class CssVariableManager {
private customVariables: {[key: string]: CustomVariable} = {};
private customVariables: { [key: string]: CustomVariable } = {};
private htmlTag: HTMLStyleElement;
private loadLocalStorage() {
try {
const payloadString = localStorage.getItem("css-custom-variables");
if(typeof payloadString === "undefined" || !payloadString)
if (typeof payloadString === "undefined" || !payloadString)
return;
const payload = JSON.parse(payloadString);
if(payload.version !== 1)
if (payload.version !== 1)
throw "invalid payload version";
this.customVariables = payload["customVariables"];
@ -39,24 +39,24 @@ class CssVariableManager {
this.updateCustomVariables(false);
}
getAllCssVariables() : CssVariable[] {
let variables: {[key: string]: CssVariable} = {};
getAllCssVariables(): CssVariable[] {
let variables: { [key: string]: CssVariable } = {};
const ownStyleSheets = Array.from(document.styleSheets)
.filter(sheet => sheet.href === null || sheet.href.startsWith(window.location.origin)) as CSSStyleSheet[];
for(const sheet of ownStyleSheets) {
for(const rule of sheet.cssRules) {
if(!(rule instanceof CSSStyleRule))
for (const sheet of ownStyleSheets) {
for (const rule of sheet.cssRules) {
if (!(rule instanceof CSSStyleRule))
continue;
if(rule.selectorText !== "html:root" && rule.selectorText !== ":root")
if (rule.selectorText !== "html:root" && rule.selectorText !== ":root")
continue;
for(const entry of rule.style) {
if(!entry.startsWith("--"))
for (const entry of rule.style) {
if (!entry.startsWith("--"))
continue;
if(variables[entry])
if (variables[entry])
continue;
const customVariable = this.customVariables[entry];
@ -74,7 +74,11 @@ class CssVariableManager {
}
setVariable(name: string, value: string) {
const customVariable = this.customVariables[name] || (this.customVariables[name] = { name: name, value: undefined, enabled: false });
const customVariable = this.customVariables[name] || (this.customVariables[name] = {
name: name,
value: undefined,
enabled: false
});
customVariable.enabled = true;
customVariable.value = value;
this.updateCustomVariables(true);
@ -82,25 +86,25 @@ class CssVariableManager {
toggleCustomVariable(name: string, flag: boolean, value?: string) {
let customVariable = this.customVariables[name];
if(!customVariable) {
if(!flag)
if (!customVariable) {
if (!flag)
return;
customVariable = this.customVariables[name] = { name: name, value: value, enabled: true };
customVariable = this.customVariables[name] = {name: name, value: value, enabled: true};
}
customVariable.enabled = flag;
if(flag && typeof value === "string")
if (flag && typeof value === "string")
customVariable.value = value;
this.updateCustomVariables(true);
}
exportConfig(allValues: boolean) {
if(allValues) {
if (allValues) {
return JSON.stringify({
version: 1,
variables: this.getAllCssVariables().map<CustomVariable>(variable => {
if(this.customVariables[variable.name]) {
if (this.customVariables[variable.name]) {
return this.customVariables[variable.name];
}
@ -121,7 +125,7 @@ class CssVariableManager {
importConfig(config: string) {
const data = JSON.parse(config);
if(data.version !== 1)
if (data.version !== 1)
throw "unsupported config version";
this.customVariables = data.variables;
@ -147,12 +151,12 @@ class CssVariableManager {
private updateCustomVariables(updateConfig: boolean) {
let text = "html:root {\n";
for(const variable of Object.values(this.customVariables))
for (const variable of Object.values(this.customVariables))
text += " " + variable.name + ": " + variable.value + ";\n";
text += "}";
this.htmlTag.textContent = text;
if(updateConfig) {
if (updateConfig) {
localStorage.setItem("css-custom-variables", JSON.stringify({
version: 1,
customVariables: this.customVariables
@ -160,6 +164,7 @@ class CssVariableManager {
}
}
}
let cssVariableManager: CssVariableManager;
export function spawnModalCssVariableEditor() {
@ -194,24 +199,24 @@ function cssVariableEditorController(events: Registry<CssEditorEvents>) {
events.on("action_import", event => {
try {
cssVariableManager.importConfig(event.config);
events.fire_async("notify_import_result", { success: true });
events.fire_async("action_select_entry", { variable: undefined });
events.fire_async("notify_import_result", {success: true});
events.fire_async("action_select_entry", {variable: undefined});
events.fire_async("query_css_variables");
} catch (error) {
console.warn("Failed to import CSS variable values: %o", error);
events.fire_async("notify_import_result", { success: false });
events.fire_async("notify_import_result", {success: false});
}
});
events.on("action_reset", () => {
cssVariableManager.reset();
events.fire_async("action_select_entry", { variable: undefined });
events.fire_async("action_select_entry", {variable: undefined});
events.fire_async("query_css_variables");
});
events.on("action_randomize", () => {
cssVariableManager.randomize();
events.fire_async("action_select_entry", { variable: undefined });
events.fire_async("action_select_entry", {variable: undefined});
events.fire_async("query_css_variables");
});
}

View File

@ -15,7 +15,7 @@ export interface CssEditorEvents {
action_select_entry: { variable: CssVariable },
action_override_toggle: { variableName: string, enabled: boolean, value?: string }
action_change_override_value: { variableName: string, value: string },
action_reset: { },
action_reset: {},
action_randomize: {},
action_export: { allValues: boolean },

View File

@ -1,9 +1,9 @@
import * as React from "react";
import {useState} from "react";
import {CssEditorEvents, CssEditorUserData, CssVariable} from "tc-shared/ui/modal/css-editor/Definitions";
import {Registry} from "tc-shared/events";
import {Translatable} from "tc-shared/ui/react-elements/i18n";
import {BoxedInputField, FlatInputField} from "tc-shared/ui/react-elements/InputField";
import {useState} from "react";
import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots";
import {Checkbox} from "tc-shared/ui/react-elements/Checkbox";
import {Button} from "tc-shared/ui/react-elements/Button";
@ -13,22 +13,22 @@ import {AbstractModal} from "tc-shared/ui/react-elements/ModalDefinitions";
const cssStyle = require("./Renderer.scss");
const CssVariableRenderer = React.memo((props: { events: Registry<CssEditorEvents>, variable: CssVariable, selected: boolean }) => {
const [ selected, setSelected ] = useState(props.selected);
const [ override, setOverride ] = useState(props.variable.overwriteValue);
const [ overrideColor, setOverrideColor ] = useState(props.variable.customValue);
const [selected, setSelected] = useState(props.selected);
const [override, setOverride] = useState(props.variable.overwriteValue);
const [overrideColor, setOverrideColor] = useState(props.variable.customValue);
props.events.reactUse("action_select_entry", event => setSelected(event.variable === props.variable));
props.events.reactUse("action_override_toggle", event => {
if(event.variableName !== props.variable.name)
if (event.variableName !== props.variable.name)
return;
setOverride(event.enabled);
if(event.enabled)
if (event.enabled)
setOverrideColor(event.value);
});
props.events.reactUse("action_change_override_value", event => {
if(event.variableName !== props.variable.name)
if (event.variableName !== props.variable.name)
return;
setOverrideColor(event.value);
@ -38,22 +38,22 @@ const CssVariableRenderer = React.memo((props: { events: Registry<CssEditorEvent
<div
className={cssStyle.variable + " " + (selected ? cssStyle.selected : "")}
onClick={() => {
if(selected)
if (selected)
return;
props.events.fire("action_select_entry", { variable: props.variable })
props.events.fire("action_select_entry", {variable: props.variable})
}}
>
<div className={cssStyle.preview}>
<div
className={cssStyle.color}
style={{ backgroundColor: props.variable.defaultValue }}
style={{backgroundColor: props.variable.defaultValue}}
/>
</div>
<div className={cssStyle.preview}>
<div
className={cssStyle.color}
style={{ backgroundColor: override ? overrideColor : undefined }}
style={{backgroundColor: override ? overrideColor : undefined}}
/>
</div>
<a>{props.variable.name}</a>
@ -62,31 +62,31 @@ const CssVariableRenderer = React.memo((props: { events: Registry<CssEditorEvent
});
const CssVariableListBodyRenderer = (props: { events: Registry<CssEditorEvents> }) => {
const [ variables, setVariables ] = useState<"loading" | CssVariable[]>(() => {
const [variables, setVariables] = useState<"loading" | CssVariable[]>(() => {
props.events.fire_async("query_css_variables");
return "loading";
});
const [ filter, setFilter ] = useState(undefined);
const [ selectedVariable, setSelectedVariable ] = useState(undefined);
const [filter, setFilter] = useState(undefined);
const [selectedVariable, setSelectedVariable] = useState(undefined);
props.events.reactUse("action_select_entry", event => setSelectedVariable(event.variable));
props.events.reactUse("query_css_variables", () => setVariables("loading"));
let content;
if(variables === "loading") {
if (variables === "loading") {
content = (
<div className={cssStyle.overlay} key={"loading"}>
<a>
<Translatable>Loading</Translatable>&nbsp;
<LoadingDots />
<LoadingDots/>
</a>
</div>
);
} else {
content = [];
for(const variable of variables) {
if(filter && variable.name.toLowerCase().indexOf(filter) === -1)
for (const variable of variables) {
if (filter && variable.name.toLowerCase().indexOf(filter) === -1)
continue;
content.push(<CssVariableRenderer
@ -97,7 +97,7 @@ const CssVariableListBodyRenderer = (props: { events: Registry<CssEditorEvents>
/>);
}
if(content.length === 0) {
if (content.length === 0) {
content.push(
<div className={cssStyle.overlay} key={"no-match"}>
<a><Translatable>No variable matched your filter</Translatable></a>
@ -111,27 +111,27 @@ const CssVariableListBodyRenderer = (props: { events: Registry<CssEditorEvents>
return (
<div className={cssStyle.body} onKeyPress={event => {
if(variables === "loading")
if (variables === "loading")
return;
/* TODO: This isn't working since the div isn't focused properly yet */
let offset = 0;
if(event.key === "ArrowDown") {
if (event.key === "ArrowDown") {
offset = 1;
} else if(event.key === "ArrowUp") {
} else if (event.key === "ArrowUp") {
offset = -1;
}
if(offset !== 0) {
if (offset !== 0) {
const selectIndex = variables.findIndex(e => e === selectedVariable);
if(selectIndex === -1)
if (selectIndex === -1)
return;
const variable = variables[selectIndex + offset];
if(!variable)
if (!variable)
return;
props.events.fire("action_select_entry", { variable: variable });
props.events.fire("action_select_entry", {variable: variable});
}
}} tabIndex={0}>
{content}
@ -140,7 +140,7 @@ const CssVariableListBodyRenderer = (props: { events: Registry<CssEditorEvents>
};
const CssVariableListSearchRenderer = (props: { events: Registry<CssEditorEvents> }) => {
const [ isLoading, setLoading ] = useState(true);
const [isLoading, setLoading] = useState(true);
props.events.reactUse("notify_css_variables", () => setLoading(false));
props.events.reactUse("query_css_variables", () => setLoading(true));
@ -151,7 +151,7 @@ const CssVariableListSearchRenderer = (props: { events: Registry<CssEditorEvents
label={<Translatable>Filter variables</Translatable>}
labelType={"floating"}
className={cssStyle.input}
onInput={text => props.events.fire("action_set_filter", { filter: text })}
onInput={text => props.events.fire("action_set_filter", {filter: text})}
disabled={isLoading}
/>
</div>
@ -164,14 +164,14 @@ const CssVariableListRenderer = (props: { events: Registry<CssEditorEvents> }) =
<a><Translatable>CSS Variable list</Translatable></a>
</div>
<div className={cssStyle.list} onKeyPress={event => console.error(event.key)}>
<CssVariableListBodyRenderer events={props.events} />
<CssVariableListSearchRenderer events={props.events} />
<CssVariableListBodyRenderer events={props.events}/>
<CssVariableListSearchRenderer events={props.events}/>
</div>
</div>
);
const SelectedVariableInfo = (props: { events: Registry<CssEditorEvents> }) => {
const [ selectedVariable, setSelectedVariable ] = useState<CssVariable>(undefined);
const [selectedVariable, setSelectedVariable] = useState<CssVariable>(undefined);
props.events.reactUse("action_select_entry", event => setSelectedVariable(event.variable));
return (<>
@ -201,9 +201,9 @@ const SelectedVariableInfo = (props: { events: Registry<CssEditorEvents> }) => {
};
const OverrideVariableInfo = (props: { events: Registry<CssEditorEvents> }) => {
const [ selectedVariable, setSelectedVariable ] = useState<CssVariable>(undefined);
const [ overwriteValue, setOverwriteValue ] = useState<string>(undefined);
const [ overwriteEnabled, setOverwriteEnabled ] = useState(false);
const [selectedVariable, setSelectedVariable] = useState<CssVariable>(undefined);
const [overwriteValue, setOverwriteValue] = useState<string>(undefined);
const [overwriteEnabled, setOverwriteEnabled] = useState(false);
props.events.reactUse("action_select_entry", event => {
setSelectedVariable(event.variable);
@ -212,17 +212,17 @@ const OverrideVariableInfo = (props: { events: Registry<CssEditorEvents> }) => {
});
props.events.reactUse("action_override_toggle", event => {
if(event.variableName !== selectedVariable?.name)
if (event.variableName !== selectedVariable?.name)
return;
selectedVariable.overwriteValue = event.enabled;
setOverwriteEnabled(event.enabled);
if(event.enabled)
if (event.enabled)
setOverwriteValue(event.value);
});
props.events.reactUse("action_change_override_value", event => {
if(event.variableName !== selectedVariable?.name)
if (event.variableName !== selectedVariable?.name)
return;
setOverwriteValue(event.value);
@ -251,31 +251,34 @@ const OverrideVariableInfo = (props: { events: Registry<CssEditorEvents> }) => {
value={overwriteValue || " "}
onInput={text => {
selectedVariable.customValue = text;
props.events.fire("action_change_override_value", { value: text, variableName: selectedVariable.name });
props.events.fire("action_change_override_value", {
value: text,
variableName: selectedVariable.name
});
}}
/>
<CssVariableColorPicker events={props.events} selectedVariable={selectedVariable} />
<CssVariableColorPicker events={props.events} selectedVariable={selectedVariable}/>
</div>
</div>
</>);
};
const CssVariableColorPicker = (props: { events: Registry<CssEditorEvents>, selectedVariable: CssVariable }) => {
const [ overwriteValue, setOverwriteValue ] = useState<string>(undefined);
const [ overwriteEnabled, setOverwriteEnabled ] = useState(false);
const [overwriteValue, setOverwriteValue] = useState<string>(undefined);
const [overwriteEnabled, setOverwriteEnabled] = useState(false);
props.events.reactUse("action_override_toggle", event => {
if(event.variableName !== props.selectedVariable?.name)
if (event.variableName !== props.selectedVariable?.name)
return;
props.selectedVariable.overwriteValue = event.enabled;
setOverwriteEnabled(event.enabled);
if(event.enabled)
if (event.enabled)
setOverwriteValue(event.value);
});
props.events.reactUse("action_change_override_value", event => {
if(event.variableName !== props.selectedVariable?.name || 'cpInvoker' in event)
if (event.variableName !== props.selectedVariable?.name || 'cpInvoker' in event)
return;
setOverwriteValue(event.value);
@ -284,23 +287,26 @@ const CssVariableColorPicker = (props: { events: Registry<CssEditorEvents>, sele
let currentInput: string;
let inputTimeout: number;
return (
<label className={cssStyle.colorButton} >
<label className={cssStyle.colorButton}>
<input
disabled={!overwriteEnabled}
type={"color"}
value={overwriteValue}
onChange={event => {
currentInput = event.target.value;
if(inputTimeout)
if (inputTimeout)
return;
inputTimeout = setTimeout(() => {
inputTimeout = undefined;
props.events.fire("action_change_override_value", { value: currentInput, variableName: props.selectedVariable.name });
props.events.fire("action_change_override_value", {
value: currentInput,
variableName: props.selectedVariable.name
});
}, 150);
}}
/>
<a className="rainbow-letter" style={{ borderBottomColor: overwriteValue }}>C</a>
<a className="rainbow-letter" style={{borderBottomColor: overwriteValue}}>C</a>
</label>
)
};
@ -324,7 +330,7 @@ const ControlButtons = (props: { events: Registry<CssEditorEvents> }) => {
color={"blue"}
type={"normal"}
className={cssStyle.button}
onClick={event => props.events.fire("action_export", { allValues: event.shiftKey })}
onClick={event => props.events.fire("action_export", {allValues: event.shiftKey})}
title={tr("Click to export the changed values, Shift click to export all values")}
><Translatable>Export</Translatable></Button>
<Button
@ -332,7 +338,7 @@ const ControlButtons = (props: { events: Registry<CssEditorEvents> }) => {
type={"normal"}
className={cssStyle.button}
onClick={() => requestFileAsText().then(content => {
props.events.fire("action_import", { config: content })
props.events.fire("action_import", {config: content})
})}
><Translatable>Import</Translatable></Button>
</div>
@ -345,9 +351,9 @@ const CssVariableEditor = (props: { events: Registry<CssEditorEvents> }) => {
<div className={cssStyle.header}>
<a><Translatable>Variable details</Translatable></a>
</div>
<SelectedVariableInfo events={props.events} />
<OverrideVariableInfo events={props.events} />
<ControlButtons events={props.events} />
<SelectedVariableInfo events={props.events}/>
<OverrideVariableInfo events={props.events}/>
<ControlButtons events={props.events}/>
</div>
)
};
@ -374,7 +380,7 @@ const requestFileAsText = async (): Promise<string> => {
element.onchange = resolve;
});
if(element.files.length !== 1)
if (element.files.length !== 1)
return undefined;
const file = element.files[0];
element.remove();
@ -397,7 +403,7 @@ class PopoutConversationUI extends AbstractModal {
downloadTextAsFile(event.config, "teaweb-style.json");
});
this.events.on("notify_import_result", event => {
if(event.success)
if (event.success)
createInfoModal(tr("Config imported successfully"), tr("The config has been imported successfully.")).open();
else
createErrorModal(tr("Config imported failed"), tr("The config import has been failed.")).open();
@ -407,8 +413,8 @@ class PopoutConversationUI extends AbstractModal {
renderBody() {
return (
<div className={cssStyle.container}>
<CssVariableListRenderer events={this.events} />
<CssVariableEditor events={this.events} />
<CssVariableListRenderer events={this.events}/>
<CssVariableEditor events={this.events}/>
</div>
);
}

View File

@ -26,7 +26,7 @@ export function spawnEchoTestModal(connection: ConnectionHandler) {
renderBody(): React.ReactElement {
return (
<EchoTestEventRegistry.Provider value={events}>
<EchoTestModal />
<EchoTestModal/>
</EchoTestEventRegistry.Provider>
);
}
@ -50,10 +50,10 @@ export function spawnEchoTestModal(connection: ConnectionHandler) {
}
function initializeController(connection: ConnectionHandler, events: Registry<EchoTestEvents>) {
let testState: TestState = { state: "stopped" };
let testState: TestState = {state: "stopped"};
events.on("action_open_microphone_settings", () => {
global_client_actions.fire("action_open_window_settings", { defaultCategory: "audio-microphone" });
global_client_actions.fire("action_open_window_settings", {defaultCategory: "audio-microphone"});
});
events.on("action_toggle_tests", event => {
@ -61,57 +61,57 @@ function initializeController(connection: ConnectionHandler, events: Registry<Ec
});
events.on("query_test_state", () => {
events.fire_async("notify_tests_toggle", { enabled: settings.global(Settings.KEY_VOICE_ECHO_TEST_ENABLED) });
events.fire_async("notify_tests_toggle", {enabled: settings.global(Settings.KEY_VOICE_ECHO_TEST_ENABLED)});
});
events.on("notify_destroy", settings.globalChangeListener(Settings.KEY_VOICE_ECHO_TEST_ENABLED, value => {
events.fire_async("notify_tests_toggle", { enabled: value });
events.fire_async("notify_tests_toggle", {enabled: value});
}));
events.on("action_test_result", event => {
if(event.status === "success") {
if (event.status === "success") {
events.fire("action_close");
} else {
events.fire("action_stop_test");
events.fire("notify_test_phase", { phase: "troubleshooting" });
events.fire("notify_test_phase", {phase: "troubleshooting"});
}
});
events.on("action_troubleshooting_finished", event => {
if(event.status === "aborted") {
if (event.status === "aborted") {
events.fire("action_close");
} else {
events.fire("notify_test_phase", { phase: "testing" });
events.fire("notify_test_phase", {phase: "testing"});
events.fire("action_start_test");
}
});
const reportVoiceConnectionState = (state: VoiceConnectionStatus) => {
if(state === VoiceConnectionStatus.Connected) {
if (state === VoiceConnectionStatus.Connected) {
beginTest();
} else {
endTest();
}
switch (state) {
case VoiceConnectionStatus.Connected:
events.fire("notify_voice_connection_state", { state: "connected" });
events.fire("notify_voice_connection_state", {state: "connected"});
break;
case VoiceConnectionStatus.Disconnected:
case VoiceConnectionStatus.Disconnecting:
events.fire("notify_voice_connection_state", { state: "disconnected" });
events.fire("notify_voice_connection_state", {state: "disconnected"});
break;
case VoiceConnectionStatus.Connecting:
events.fire("notify_voice_connection_state", { state: "connecting" });
events.fire("notify_voice_connection_state", {state: "connecting"});
break;
case VoiceConnectionStatus.ClientUnsupported:
events.fire("notify_voice_connection_state", { state: "unsupported-client" });
events.fire("notify_voice_connection_state", {state: "unsupported-client"});
break;
case VoiceConnectionStatus.ServerUnsupported:
events.fire("notify_voice_connection_state", { state: "unsupported-server" });
events.fire("notify_voice_connection_state", {state: "unsupported-server"});
break;
}
@ -124,7 +124,7 @@ function initializeController(connection: ConnectionHandler, events: Registry<Ec
events.on("query_voice_connection_state", () => reportVoiceConnectionState(connection.getServerConnection().getVoiceConnection().getConnectionState()));
events.on("query_test_state", () => {
events.fire_async("notify_test_state", { state: testState });
events.fire_async("notify_test_state", {state: testState});
});
events.on("action_start_test", () => {
@ -133,51 +133,51 @@ function initializeController(connection: ConnectionHandler, events: Registry<Ec
const setTestState = (state: TestState) => {
testState = state;
events.fire("notify_test_state", { state: state });
events.fire("notify_test_state", {state: state});
}
let testId = 0;
const beginTest = () => {
if(testState.state === "initializing" || testState.state === "running") {
if (testState.state === "initializing" || testState.state === "running") {
return;
} else if(!connection.serverFeatures.supportsFeature(ServerFeature.WHISPER_ECHO)) {
setTestState({ state: "unsupported" });
} else if (!connection.serverFeatures.supportsFeature(ServerFeature.WHISPER_ECHO)) {
setTestState({state: "unsupported"});
return;
}
setTestState({ state: "initializing" });
setTestState({state: "initializing"});
const currentTestId = ++testId;
connection.startEchoTest().then(() => {
if(currentTestId !== testId) {
if (currentTestId !== testId) {
return;
}
setTestState({ state: "running" });
setTestState({state: "running"});
}).catch(error => {
if(currentTestId !== testId) {
if (currentTestId !== testId) {
return;
}
let message;
if(error instanceof CommandResult) {
if (error instanceof CommandResult) {
message = error.formattedMessage();
} else if(error instanceof Error) {
} else if (error instanceof Error) {
message = error.message;
} else if(typeof error === "string") {
} else if (typeof error === "string") {
message = error;
} else {
message = tr("lookup the console");
logError(LogCategory.AUDIO, tr("Failed to begin echo testing: %o"), error);
}
setTestState({ state: "start-failed", error: message });
setTestState({state: "start-failed", error: message});
});
}
const endTest = () => {
setTestState({ state: "stopped" });
setTestState({state: "stopped"});
connection.stopEchoTest();
}

View File

@ -1,5 +1,12 @@
export type VoiceConnectionState = "connecting" | "connected" | "disconnected" | "unsupported-client" | "unsupported-server";
export type TestState = { state: "initializing" | "running" | "stopped" | "microphone-invalid" | "unsupported" } | { state: "start-failed", error: string };
export type VoiceConnectionState =
"connecting"
| "connected"
| "disconnected"
| "unsupported-client"
| "unsupported-server";
export type TestState =
{ state: "initializing" | "running" | "stopped" | "microphone-invalid" | "unsupported" }
| { state: "start-failed", error: string };
export interface EchoTestEvents {
action_troubleshooting_finished: { status: "test-again" | "aborted" }

View File

@ -16,7 +16,7 @@ export const EchoTestEventRegistry = React.createContext<Registry<EchoTestEvents
const VoiceStateOverlay = () => {
const events = useContext(EchoTestEventRegistry);
const [ state, setState ] = useState<"loading" | VoiceConnectionState>(() => {
const [state, setState] = useState<"loading" | VoiceConnectionState>(() => {
events.fire("query_voice_connection_state");
return "loading";
});
@ -35,17 +35,17 @@ const VoiceStateOverlay = () => {
case "unsupported-client":
inner = <a key={state}>
<Translatable>Voice connection isn't supported by your browser.</Translatable><br />
<Translatable>Voice connection isn't supported by your browser.</Translatable><br/>
<Translatable>Please use another browser.</Translatable>
</a>;
break;
case "connecting":
inner = <a key={state}><Translatable>establishing voice connection</Translatable> <LoadingDots /></a>;
inner = <a key={state}><Translatable>establishing voice connection</Translatable> <LoadingDots/></a>;
break;
case "loading":
inner = <a key={state}><Translatable>loading</Translatable> <LoadingDots /></a>;
inner = <a key={state}><Translatable>loading</Translatable> <LoadingDots/></a>;
break;
case "connected":
@ -66,12 +66,12 @@ const VoiceStateOverlay = () => {
const TestStateOverlay = () => {
const events = useContext(EchoTestEventRegistry);
const [ state, setState ] = useState<{ state: "loading" } | TestState>(() => {
const [state, setState] = useState<{ state: "loading" } | TestState>(() => {
events.fire("query_test_state");
return { state: "loading" };
return {state: "loading"};
});
const [ voiceConnected, setVoiceConnected ] = useState<"loading" | boolean>(() => {
const [voiceConnected, setVoiceConnected] = useState<"loading" | boolean>(() => {
return "loading";
});
@ -90,13 +90,15 @@ const TestStateOverlay = () => {
<VariadicTranslatable text={"Failed to start echo test:\n{0}"}>
{state.error}
</VariadicTranslatable>
<br />
<Button type={"small"} color={"green"} onClick={() => events.fire("action_start_test")}><Translatable>Try again</Translatable></Button>
<br/>
<Button type={"small"} color={"green"} onClick={() => events.fire("action_start_test")}><Translatable>Try
again</Translatable></Button>
</a>;
break;
case "unsupported":
inner = <a key={"initializing"}><Translatable>Echo testing hasn't been supported by the server.</Translatable></a>;
inner = <a key={"initializing"}><Translatable>Echo testing hasn't been supported by the
server.</Translatable></a>;
break;
}
@ -110,7 +112,7 @@ const TestStateOverlay = () => {
const TroubleshootingSoundOverlay = () => {
const events = useContext(EchoTestEventRegistry);
const [ visible, setVisible ] = useState(false);
const [visible, setVisible] = useState(false);
events.reactUse("notify_test_phase", event => setVisible(event.phase === "troubleshooting"));
@ -118,50 +120,58 @@ const TroubleshootingSoundOverlay = () => {
<div className={cssStyle.overlay + " " + cssStyle.troubleshoot + " " + (visible ? cssStyle.shown : "")}>
<div className={cssStyle.top}>
<div className={cssStyle.containerIcon}>
<ClientIconRenderer icon={ClientIcon.MicrophoneBroken} className={cssStyle.icon} />
<ClientIconRenderer icon={ClientIcon.MicrophoneBroken} className={cssStyle.icon}/>
</div>
<div className={cssStyle.help}>
<h1><Translatable>Troubleshooting guide</Translatable></h1>
<ol>
<li>
<h2><Translatable>Correct microphone selected?</Translatable>
<Button type={"extra-small"} onClick={() => events.fire("action_open_microphone_settings")}>
<Button type={"extra-small"}
onClick={() => events.fire("action_open_microphone_settings")}>
<Translatable>Open Microphone settings</Translatable>
</Button>
</h2>
<p>
<Translatable>Check within the settings, if the right microphone has been selected.</Translatable>
<Translatable>Check within the settings, if the right microphone has been
selected.</Translatable>
<Translatable>The indicators will show you any voice activity.</Translatable>
</p>
</li>
<li>
<h2><Translatable>Are any addons blocking the microphone access?</Translatable></h2>
<p>
<Translatable>Some addons might block the access to your microphone. Try to disable all addons and reload the site.</Translatable>
<Translatable>Some addons might block the access to your microphone. Try to disable all
addons and reload the site.</Translatable>
</p>
</li>
<li>
<h2><Translatable>Has WebRTC been enabled?</Translatable></h2>
<p>
<VariadicTranslatable text={"In some cases, WebRTC has been disabled. Click {0} to troubleshoot any WebRTC related issues."}>
<a href={"https://test.webrtc.org"} hrefLang={"en"} target={"_blank"}><Translatable>here</Translatable></a>
<VariadicTranslatable
text={"In some cases, WebRTC has been disabled. Click {0} to troubleshoot any WebRTC related issues."}>
<a href={"https://test.webrtc.org"} hrefLang={"en"}
target={"_blank"}><Translatable>here</Translatable></a>
</VariadicTranslatable>
</p>
</li>
<li>
<h2><Translatable>Reload the site</Translatable></h2>
<p>
<Translatable>In some cases, reloading the site will already solve the issue for you.</Translatable>
<Translatable>In some cases, reloading the site will already solve the issue for
you.</Translatable>
</p>
</li>
<li>
<h2><Translatable>Nothing worked? Submit an issue</Translatable></h2>
<p>
<VariadicTranslatable text={"If still nothing worked, try to seek help in our {0}."}>
<a href={"https://forum.teaspeak.de"} hrefLang={"en"} target={"_blank"}><Translatable>forum</Translatable></a>
<a href={"https://forum.teaspeak.de"} hrefLang={"en"}
target={"_blank"}><Translatable>forum</Translatable></a>
</VariadicTranslatable>
<VariadicTranslatable text={"You can also create a new issue/bug report {0}."}>
<a href={"https://github.com/TeaSpeak/TeaWeb/issues"} hrefLang={"en"} target={"_blank"}><Translatable>here</Translatable></a>
<a href={"https://github.com/TeaSpeak/TeaWeb/issues"} hrefLang={"en"}
target={"_blank"}><Translatable>here</Translatable></a>
</VariadicTranslatable>
</p>
</li>
@ -169,11 +179,13 @@ const TroubleshootingSoundOverlay = () => {
</div>
</div>
<div className={cssStyle.buttons}>
<Button type={"small"} color={"red"} onClick={() => events.fire("action_troubleshooting_finished", { status: "aborted" })}>
<Button type={"small"} color={"red"}
onClick={() => events.fire("action_troubleshooting_finished", {status: "aborted"})}>
<Translatable>Abort test</Translatable>
</Button>
<Button type={"small"} color={"green"} onClick={() => events.fire("action_troubleshooting_finished", { status: "test-again" })}>
<Button type={"small"} color={"green"}
onClick={() => events.fire("action_troubleshooting_finished", {status: "test-again"})}>
<Translatable>Test again</Translatable>
</Button>
</div>
@ -184,7 +196,7 @@ const TroubleshootingSoundOverlay = () => {
export const TestToggle = () => {
const events = useContext(EchoTestEventRegistry);
const [ state, setState ] = useState<"loading" | boolean>(() => {
const [state, setState] = useState<"loading" | boolean>(() => {
events.fire("query_test_state");
return "loading";
});
@ -195,7 +207,7 @@ export const TestToggle = () => {
<Checkbox
value={state === true}
disabled={state === "loading"}
onChange={() => events.fire("action_toggle_tests", { enabled: state === false })}
onChange={() => events.fire("action_toggle_tests", {enabled: state === false})}
label={<Translatable>Show this on the next connect</Translatable>}
/>
)
@ -211,26 +223,29 @@ export const EchoTestModal = () => {
</h1>
<div className={cssStyle.buttons}>
<div className={cssStyle.buttonContainer}>
<div className={cssStyle.button + " " + cssStyle.success} title={tr("Yes")} onClick={() => events.fire("action_test_result", { status: "success" })}>
<ClientIconRenderer icon={ClientIcon.Apply} className={cssStyle.icon} />
<div className={cssStyle.button + " " + cssStyle.success} title={tr("Yes")}
onClick={() => events.fire("action_test_result", {status: "success"})}>
<ClientIconRenderer icon={ClientIcon.Apply} className={cssStyle.icon}/>
</div>
<a><Translatable>Yes</Translatable></a>
</div>
<div className={cssStyle.buttonContainer}>
<div className={cssStyle.button + " " + cssStyle.fail} title={tr("No")} onClick={() => events.fire("action_test_result", { status: "fail" })}>
<ClientIconRenderer icon={ClientIcon.Delete} className={cssStyle.icon} />
<div className={cssStyle.button + " " + cssStyle.fail} title={tr("No")}
onClick={() => events.fire("action_test_result", {status: "fail"})}>
<ClientIconRenderer icon={ClientIcon.Delete} className={cssStyle.icon}/>
</div>
<a><Translatable>No</Translatable></a>
</div>
<VoiceStateOverlay />
<TestStateOverlay />
<VoiceStateOverlay/>
<TestStateOverlay/>
</div>
<div className={cssStyle.footer}>
<TestToggle />
<Button color={"red"} type={"small"} onClick={() => events.fire("action_close")}><Translatable>Close</Translatable></Button>
<TestToggle/>
<Button color={"red"} type={"small"}
onClick={() => events.fire("action_close")}><Translatable>Close</Translatable></Button>
</div>
<TroubleshootingSoundOverlay />
<TroubleshootingSoundOverlay/>
</div>
);
};

Some files were not shown because too many files have changed in this diff Show More