Reset all js files and start from zero, this time more structured
This commit is contained in:
parent
5f0c1b303a
commit
447e84ed0f
111 changed files with 3946 additions and 4237 deletions
|
@ -1,8 +1,8 @@
|
|||
export interface Window {
|
||||
interface Window {
|
||||
BroadcastChannel: BroadcastChannel;
|
||||
}
|
||||
|
||||
export namespace bipc {
|
||||
namespace bipc {
|
||||
export interface BroadcastMessage {
|
||||
timestamp: number;
|
||||
receiver: string;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/// <reference path="log.ts" />
|
||||
/// <reference path="proto.ts" />
|
||||
/// <reference path="channel-tree/view.ts" />
|
||||
/// <reference path="ui/view.ts" />
|
||||
/// <reference path="settings.ts" />
|
||||
/// <reference path="FileManager.ts" />
|
||||
/// <reference path="permission/PermissionManager.ts" />
|
||||
|
@ -8,17 +8,7 @@
|
|||
/// <reference path="ui/frames/ControlBar.ts" />
|
||||
/// <reference path="connection/ConnectionBase.ts" />
|
||||
|
||||
import {ChannelTree} from "./channel-tree/view";
|
||||
import {LocalClientEntry} from "./channel-tree/client";
|
||||
import {ServerAddress} from "./channel-tree/server";
|
||||
import {ChannelEntry} from "./channel-tree/channel";
|
||||
import {AbstractServerConnection} from "./connection/ConnectionBase";
|
||||
import {PermissionManager} from "./permission/PermissionManager";
|
||||
import {GroupManager} from "./permission/GroupManager";
|
||||
import {ServerSettings} from "./settings";
|
||||
import {Hostbanner} from "./ui/frames/hostbanner";
|
||||
|
||||
export enum DisconnectReason {
|
||||
enum DisconnectReason {
|
||||
HANDLER_DESTROYED,
|
||||
REQUESTED,
|
||||
DNS_FAILED,
|
||||
|
@ -38,7 +28,7 @@ export enum DisconnectReason {
|
|||
UNKNOWN
|
||||
}
|
||||
|
||||
export enum ConnectionState {
|
||||
enum ConnectionState {
|
||||
UNCONNECTED,
|
||||
CONNECTING,
|
||||
INITIALISING,
|
||||
|
@ -46,7 +36,7 @@ export enum ConnectionState {
|
|||
DISCONNECTING
|
||||
}
|
||||
|
||||
export enum ViewReasonId {
|
||||
enum ViewReasonId {
|
||||
VREASON_USER_ACTION = 0,
|
||||
VREASON_MOVED = 1,
|
||||
VREASON_SYSTEM = 2,
|
||||
|
@ -61,7 +51,7 @@ export enum ViewReasonId {
|
|||
VREASON_SERVER_SHUTDOWN = 11
|
||||
}
|
||||
|
||||
export interface VoiceStatus {
|
||||
interface VoiceStatus {
|
||||
input_hardware: boolean;
|
||||
input_muted: boolean;
|
||||
output_muted: boolean;
|
||||
|
@ -78,7 +68,7 @@ export interface VoiceStatus {
|
|||
queries_visible: boolean;
|
||||
}
|
||||
|
||||
export interface ConnectParameters {
|
||||
interface ConnectParameters {
|
||||
nickname?: string;
|
||||
channel?: {
|
||||
target: string | number;
|
||||
|
@ -89,10 +79,10 @@ export interface ConnectParameters {
|
|||
auto_reconnect_attempt?: boolean;
|
||||
}
|
||||
|
||||
export class ConnectionHandler {
|
||||
class ConnectionHandler {
|
||||
channelTree: ChannelTree;
|
||||
|
||||
serverConnection: AbstractServerConnection;
|
||||
serverConnection: connection.AbstractServerConnection;
|
||||
|
||||
fileManager: FileManager;
|
||||
|
||||
|
|
|
@ -1,26 +1,21 @@
|
|||
import {ChannelEntry} from "./channel-tree/channel";
|
||||
import {AbstractCommandHandler, ServerCommand} from "./connection/ConnectionBase";
|
||||
import {ConnectionHandler} from "./ConnectionHandler";
|
||||
import {CommandResult} from "./connection/ServerConnectionDeclaration";
|
||||
import {log, LogCategory} from "./log";
|
||||
import {ClientEntry} from "./channel-tree/client";
|
||||
import {hex} from "./crypto/hex";
|
||||
/// <reference path="connection/CommandHandler.ts" />
|
||||
/// <reference path="connection/ConnectionBase.ts" />
|
||||
|
||||
export class FileEntry {
|
||||
class FileEntry {
|
||||
name: string;
|
||||
datetime: number;
|
||||
type: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export class FileListRequest {
|
||||
class FileListRequest {
|
||||
path: string;
|
||||
entries: FileEntry[];
|
||||
|
||||
callback: (entries: FileEntry[]) => void;
|
||||
}
|
||||
|
||||
export namespace transfer {
|
||||
namespace transfer {
|
||||
export interface TransferKey {
|
||||
client_transfer_id: number;
|
||||
server_transfer_id: number;
|
||||
|
@ -157,7 +152,7 @@ class RequestFileUpload implements transfer.UploadTransfer {
|
|||
}
|
||||
}
|
||||
|
||||
class FileManager extends AbstractCommandHandler {
|
||||
class FileManager extends connection.AbstractCommandHandler {
|
||||
handle: ConnectionHandler;
|
||||
icons: IconManager;
|
||||
avatars: AvatarManager;
|
||||
|
@ -196,7 +191,7 @@ class FileManager extends AbstractCommandHandler {
|
|||
this.avatars = undefined;
|
||||
}
|
||||
|
||||
handle_command(command: ServerCommand): boolean {
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
switch (command.command) {
|
||||
case "notifyfilelist":
|
||||
this.notifyFileList(command.arguments);
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {Settings, settings} from "./settings";
|
||||
import {contextmenu} from "./ui/elements/context_menu";
|
||||
import {image_preview} from "./ui/frames/image_preview";
|
||||
import {guid} from "./crypto/uid";
|
||||
|
||||
declare const xbbcode;
|
||||
export namespace messages.formatter {
|
||||
namespace messages.formatter {
|
||||
export namespace bbcode {
|
||||
const sanitizer_escaped = (key: string) => "[-- sescaped: " + key + " --]";
|
||||
const sanitizer_escaped_regex = /\[-- sescaped: ([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}) --]/;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export enum KeyCode {
|
||||
enum KeyCode {
|
||||
KEY_CANCEL = 3,
|
||||
KEY_HELP = 6,
|
||||
KEY_BACK_SPACE = 8,
|
||||
|
@ -118,7 +118,7 @@ export enum KeyCode {
|
|||
KEY_META = 224
|
||||
}
|
||||
|
||||
export namespace ppt {
|
||||
namespace ppt {
|
||||
export enum EventType {
|
||||
KEY_PRESS,
|
||||
KEY_RELEASE,
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
import {profiles} from "./profiles/ConnectionProfile";
|
||||
namespace bookmarks {
|
||||
function guid() {
|
||||
function s4() {
|
||||
return Math
|
||||
.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
}
|
||||
|
||||
export namespace bookmarks {
|
||||
export const boorkmak_connect = (mark: Bookmark, new_tab?: boolean) => {
|
||||
const profile = profiles.find_profile(mark.connect_profile) || profiles.default_profile();
|
||||
if(profile.valid()) {
|
||||
|
|
|
@ -1,37 +1,16 @@
|
|||
import {ConnectionHandler, DisconnectReason, ViewReasonId} from "../ConnectionHandler";
|
||||
import {
|
||||
AbstractCommandHandler,
|
||||
AbstractCommandHandlerBoss,
|
||||
AbstractServerConnection,
|
||||
CommandOptions, ServerCommand
|
||||
} from "./ConnectionBase";
|
||||
import {CommandResult, ErrorID} from "./ServerConnectionDeclaration";
|
||||
import {Sound} from "../sound/Sounds";
|
||||
import {log, LogCategory} from "../log";
|
||||
import {MessageHelper} from "../ui/frames/chat";
|
||||
import {
|
||||
ClientConnectionInfo,
|
||||
ClientEntry,
|
||||
ClientType,
|
||||
LocalClientEntry,
|
||||
MusicClientEntry, SongInfo
|
||||
} from "../channel-tree/client";
|
||||
import {ChannelEntry} from "../channel-tree/channel";
|
||||
import {chat as pchat} from "../ui/frames/side/private_conversations";
|
||||
import {Modals} from "../ui/modal/ModalPoke";
|
||||
import {chat} from "../ui/frames/side/conversations";
|
||||
import Conversation = chat.channel.Conversation;
|
||||
import {createErrorModal, createInfoModal, createInputModal, createModal} from "../ui/elements/modal";
|
||||
import {server_connections} from "../ui/frames/connection_handlers";
|
||||
import {server} from "../ui/frames/server_log";
|
||||
/// <reference path="ConnectionBase.ts" />
|
||||
|
||||
export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss {
|
||||
namespace connection {
|
||||
import Conversation = chat.channel.Conversation;
|
||||
import MusicInfo = chat.MusicInfo;
|
||||
|
||||
export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss {
|
||||
constructor(connection: AbstractServerConnection) {
|
||||
super(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ConnectionCommandHandler extends AbstractCommandHandler {
|
||||
export class ConnectionCommandHandler extends AbstractCommandHandler {
|
||||
readonly connection: AbstractServerConnection;
|
||||
readonly connection_handler: ConnectionHandler;
|
||||
|
||||
|
@ -86,7 +65,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
this["notifyplaylistsongloaded"] = this.handleNotifyPlaylistSongLoaded;
|
||||
}
|
||||
|
||||
private loggable_invoker(unique_id, client_id, name) : server.base.Client | undefined {
|
||||
private loggable_invoker(unique_id, client_id, name) : log.server.base.Client | undefined {
|
||||
const id = parseInt(client_id);
|
||||
if(typeof(client_id) === "undefined" || Number.isNaN(id))
|
||||
return undefined;
|
||||
|
@ -105,7 +84,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
};
|
||||
}
|
||||
|
||||
proxy_command_promise(promise: Promise<CommandResult>, options: CommandOptions) {
|
||||
proxy_command_promise(promise: Promise<CommandResult>, options: connection.CommandOptions) {
|
||||
if(!options.process_result)
|
||||
return promise;
|
||||
|
||||
|
@ -117,18 +96,18 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
if(res.id == ErrorID.PERMISSION_ERROR) { //Permission error
|
||||
const permission = this.connection_handler.permissions.resolveInfo(res.json["failed_permid"] as number);
|
||||
res.message = tr("Insufficient client permissions. Failed on permission ") + (permission ? permission.name : "unknown");
|
||||
this.connection_handler.log.log(server.Type.ERROR_PERMISSION, {
|
||||
this.connection_handler.log.log(log.server.Type.ERROR_PERMISSION, {
|
||||
permission: this.connection_handler.permissions.resolveInfo(res.json["failed_permid"] as number)
|
||||
});
|
||||
this.connection_handler.sound.play(Sound.ERROR_INSUFFICIENT_PERMISSIONS);
|
||||
} else if(res.id != ErrorID.EMPTY_RESULT) {
|
||||
this.connection_handler.log.log(server.Type.ERROR_CUSTOM, {
|
||||
this.connection_handler.log.log(log.server.Type.ERROR_CUSTOM, {
|
||||
message: res.extra_message.length == 0 ? res.message : res.extra_message
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if(typeof(ex) === "string") {
|
||||
this.connection_handler.log.log(server.Type.CONNECTION_COMMAND_ERROR, {error: ex});
|
||||
this.connection_handler.log.log(log.server.Type.CONNECTION_COMMAND_ERROR, {error: ex});
|
||||
} else {
|
||||
log.error(LogCategory.NETWORKING, tr("Invalid promise result type: %s. Result: %o"), typeof (ex), ex);
|
||||
}
|
||||
|
@ -211,7 +190,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
if(properties.virtualserver_hostmessage_mode > 0) {
|
||||
if(properties.virtualserver_hostmessage_mode == 1) {
|
||||
/* show in log */
|
||||
this.connection_handler.log.log(server.Type.SERVER_HOST_MESSAGE, {
|
||||
this.connection_handler.log.log(log.server.Type.SERVER_HOST_MESSAGE, {
|
||||
message: properties.virtualserver_hostmessage
|
||||
});
|
||||
} else {
|
||||
|
@ -225,7 +204,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
if(properties.virtualserver_hostmessage_mode == 3) {
|
||||
/* first let the client initialize his stuff */
|
||||
setTimeout(() => {
|
||||
this.connection_handler.log.log(server.Type.SERVER_HOST_MESSAGE_DISCONNECT, {
|
||||
this.connection_handler.log.log(log.server.Type.SERVER_HOST_MESSAGE_DISCONNECT, {
|
||||
message: properties.virtualserver_welcomemessage
|
||||
});
|
||||
|
||||
|
@ -239,7 +218,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
|
||||
/* welcome message */
|
||||
if(properties.virtualserver_welcomemessage) {
|
||||
this.connection_handler.log.log(server.Type.SERVER_WELCOME_MESSAGE, {
|
||||
this.connection_handler.log.log(log.server.Type.SERVER_WELCOME_MESSAGE, {
|
||||
message: properties.virtualserver_welcomemessage
|
||||
});
|
||||
}
|
||||
|
@ -261,7 +240,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
}, { field_placeholder: 'Enter Privilege Key' }).open();
|
||||
}
|
||||
|
||||
this.connection_handler.log.log(server.Type.CONNECTION_CONNECTED, {
|
||||
this.connection_handler.log.log(log.server.Type.CONNECTION_CONNECTED, {
|
||||
own_client: this.connection_handler.getClient().log_data()
|
||||
});
|
||||
this.connection_handler.sound.play(Sound.CONNECTION_CONNECTED);
|
||||
|
@ -435,7 +414,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
|
||||
if(this.connection_handler.client_status.queries_visible || client.properties.client_type != ClientType.CLIENT_QUERY) {
|
||||
const own_channel = this.connection.client.getClient().currentChannel();
|
||||
this.connection_handler.log.log(server.Type.CLIENT_VIEW_ENTER, {
|
||||
this.connection_handler.log.log(log.server.Type.CLIENT_VIEW_ENTER, {
|
||||
channel_from: old_channel ? old_channel.log_data() : undefined,
|
||||
channel_to: channel ? channel.log_data() : undefined,
|
||||
client: client.log_data(),
|
||||
|
@ -542,7 +521,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
let channel_to = tree.findChannel(entry["ctid"]);
|
||||
|
||||
const is_own_channel = channel_from == own_channel;
|
||||
this.connection_handler.log.log(server.Type.CLIENT_VIEW_LEAVE, {
|
||||
this.connection_handler.log.log(log.server.Type.CLIENT_VIEW_LEAVE, {
|
||||
channel_from: channel_from ? channel_from.log_data() : undefined,
|
||||
channel_to: channel_to ? channel_to.log_data() : undefined,
|
||||
client: client.log_data(),
|
||||
|
@ -585,7 +564,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
attach: false
|
||||
});
|
||||
if(conversation) {
|
||||
conversation.set_state(pchat.PrivateConversationState.DISCONNECTED);
|
||||
conversation.set_state(chat.PrivateConversationState.DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -656,7 +635,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
}
|
||||
|
||||
const own_channel = this.connection.client.getClient().currentChannel();
|
||||
this.connection_handler.log.log(server.Type.CLIENT_VIEW_MOVE, {
|
||||
this.connection_handler.log.log(log.server.Type.CLIENT_VIEW_MOVE, {
|
||||
channel_from: channel_from ? {
|
||||
channel_id: channel_from.channelId,
|
||||
channel_name: channel_from.channelName()
|
||||
|
@ -771,7 +750,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
const target_own = target_client_id === this.connection.client.getClientId();
|
||||
|
||||
if(target_own && target_client_id === json["invokerid"]) {
|
||||
log.error(LogCategory.NETWORKING, tr("Received conversation message from invalid client id. Data: %o"), json);
|
||||
log.error(LogCategory.NETWORKING, tr("Received conversation message from invalid client id. Data: %o", json));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -829,7 +808,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
if(conversation.is_unread() && channel)
|
||||
channel.flag_text_unread = true;
|
||||
} else if(mode == 3) {
|
||||
this.connection_handler.log.log(server.Type.GLOBAL_MESSAGE, {
|
||||
this.connection_handler.log.log(log.server.Type.GLOBAL_MESSAGE, {
|
||||
message: json["msg"],
|
||||
sender: {
|
||||
client_unique_id: json["invokeruid"],
|
||||
|
@ -892,7 +871,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
log.warn(LogCategory.GENERAL, tr("Received chat close for client, but we haven't a chat open."));
|
||||
return;
|
||||
}
|
||||
conversation.set_state(pchat.PrivateConversationState.CLOSED);
|
||||
conversation.set_state(chat.PrivateConversationState.CLOSED);
|
||||
}
|
||||
|
||||
handleNotifyClientUpdated(json) {
|
||||
|
@ -1177,4 +1156,5 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
metadata: json["song_metadata"]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +1,5 @@
|
|||
import {
|
||||
ClientNameInfo,
|
||||
CommandResult,
|
||||
ErrorID,
|
||||
Playlist, PlaylistInfo, PlaylistSong,
|
||||
QueryList,
|
||||
QueryListEntry, ServerGroupClient
|
||||
} from "./ServerConnectionDeclaration";
|
||||
import {ChannelEntry} from "../channel-tree/channel";
|
||||
import {ChatType} from "../ui/frames/chat";
|
||||
import {ClientEntry} from "../channel-tree/client";
|
||||
import {AbstractCommandHandler, ServerCommand, SingleCommandHandler} from "./ConnectionBase";
|
||||
import {log, LogCategory} from "../log";
|
||||
|
||||
export class CommandHelper extends AbstractCommandHandler {
|
||||
namespace connection {
|
||||
export class CommandHelper extends AbstractCommandHandler {
|
||||
private _who_am_i: any;
|
||||
private _awaiters_unique_ids: {[unique_id: string]:((resolved: ClientNameInfo) => any)[]} = {};
|
||||
private _awaiters_unique_dbid: {[database_id: number]:((resolved: ClientNameInfo) => any)[]} = {};
|
||||
|
@ -36,7 +23,7 @@ export class CommandHelper extends AbstractCommandHandler {
|
|||
this._awaiters_unique_ids = undefined;
|
||||
}
|
||||
|
||||
handle_command(command: ServerCommand): boolean {
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
if(command.command == "notifyclientnamefromuid")
|
||||
this.handle_notifyclientnamefromuid(command.arguments);
|
||||
if(command.command == "notifyclientgetnamefromdbid")
|
||||
|
@ -457,4 +444,5 @@ export class CommandHelper extends AbstractCommandHandler {
|
|||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,18 @@
|
|||
import {ConnectionHandler, ConnectionState} from "../ConnectionHandler";
|
||||
import {ServerAddress} from "../channel-tree/server";
|
||||
import {CommandResult} from "./ServerConnectionDeclaration";
|
||||
import {RecorderProfile} from "../voice/RecorderProfile";
|
||||
import {CommandHelper} from "./CommandHelper";
|
||||
import {connection} from "./HandshakeHandler";
|
||||
import HandshakeHandler = connection.HandshakeHandler;
|
||||
|
||||
export interface CommandOptions {
|
||||
namespace connection {
|
||||
export interface CommandOptions {
|
||||
flagset?: string[]; /* default: [] */
|
||||
process_result?: boolean; /* default: true */
|
||||
|
||||
timeout?: number /* default: 1000 */;
|
||||
}
|
||||
export const CommandOptionDefaults: CommandOptions = {
|
||||
}
|
||||
export const CommandOptionDefaults: CommandOptions = {
|
||||
flagset: [],
|
||||
process_result: true,
|
||||
timeout: 1000
|
||||
};
|
||||
};
|
||||
|
||||
export type ConnectionStateListener = (old_state: ConnectionState, new_state: ConnectionState) => any;
|
||||
export abstract class AbstractServerConnection {
|
||||
export type ConnectionStateListener = (old_state: ConnectionState, new_state: ConnectionState) => any;
|
||||
export abstract class AbstractServerConnection {
|
||||
readonly client: ConnectionHandler;
|
||||
readonly command_helper: CommandHelper;
|
||||
|
||||
|
@ -51,9 +44,9 @@ export abstract class AbstractServerConnection {
|
|||
native: number,
|
||||
javascript?: number
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace voice {
|
||||
export namespace voice {
|
||||
export enum PlayerState {
|
||||
PREBUFFERING,
|
||||
PLAYING,
|
||||
|
@ -112,14 +105,14 @@ export namespace voice {
|
|||
abstract get_encoder_codec() : number;
|
||||
abstract set_encoder_codec(codec: number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ServerCommand {
|
||||
export class ServerCommand {
|
||||
command: string;
|
||||
arguments: any[];
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractCommandHandler {
|
||||
export abstract class AbstractCommandHandler {
|
||||
readonly connection: AbstractServerConnection;
|
||||
|
||||
handler_boss: AbstractCommandHandlerBoss | undefined;
|
||||
|
@ -135,18 +128,18 @@ export abstract class AbstractCommandHandler {
|
|||
* @return If the command should be consumed
|
||||
*/
|
||||
abstract handle_command(command: ServerCommand) : boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export interface SingleCommandHandler {
|
||||
export interface SingleCommandHandler {
|
||||
name?: string;
|
||||
command?: string;
|
||||
timeout?: number;
|
||||
|
||||
/* if the return is true then the command handler will be removed */
|
||||
function: (command: ServerCommand) => boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractCommandHandlerBoss {
|
||||
export abstract class AbstractCommandHandlerBoss {
|
||||
readonly connection: AbstractServerConnection;
|
||||
protected command_handlers: AbstractCommandHandler[] = [];
|
||||
/* TODO: Timeout */
|
||||
|
@ -219,4 +212,5 @@ export abstract class AbstractCommandHandlerBoss {
|
|||
|
||||
return flag_consumed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,4 @@
|
|||
import {AbstractServerConnection} from "./ConnectionBase";
|
||||
import {ConnectParameters, DisconnectReason} from "../ConnectionHandler";
|
||||
import {profiles} from "../profiles/ConnectionProfile";
|
||||
import {profiles as iprofiles} from "../profiles/Identity";
|
||||
import {profiles as tiprofiles} from "../profiles/identities/TeamSpeakIdentity";
|
||||
import {native_client} from "../main";
|
||||
import {settings} from "../settings";
|
||||
import {CommandResult} from "./ServerConnectionDeclaration";
|
||||
|
||||
export namespace connection {
|
||||
import identities = iprofiles.identities;
|
||||
|
||||
namespace connection {
|
||||
export interface HandshakeIdentityHandler {
|
||||
connection: AbstractServerConnection;
|
||||
|
||||
|
@ -59,7 +48,7 @@ export namespace connection {
|
|||
|
||||
on_teamspeak() {
|
||||
const type = this.profile.selected_type();
|
||||
if(type == identities.IdentitifyType.TEAMSPEAK)
|
||||
if(type == profiles.identities.IdentitifyType.TEAMSPEAK)
|
||||
this.handshake_finished();
|
||||
else {
|
||||
|
||||
|
@ -133,8 +122,8 @@ export namespace connection {
|
|||
}
|
||||
|
||||
/* required to keep compatibility */
|
||||
if(this.profile.selected_type() === identities.IdentitifyType.TEAMSPEAK) {
|
||||
data["client_key_offset"] = (this.profile.selected_identity() as tiprofiles.identities.TeaSpeakIdentity).hash_number;
|
||||
if(this.profile.selected_type() === profiles.identities.IdentitifyType.TEAMSPEAK) {
|
||||
data["client_key_offset"] = (this.profile.selected_identity() as profiles.identities.TeaSpeakIdentity).hash_number;
|
||||
}
|
||||
|
||||
this.connection.send_command("clientinit", data).catch(error => {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import {LaterPromise} from "../utils/helpers";
|
||||
|
||||
export enum ErrorID {
|
||||
enum ErrorID {
|
||||
NOT_IMPLEMENTED = 0x2,
|
||||
COMMAND_NOT_FOUND = 0x100,
|
||||
|
||||
|
@ -17,7 +15,7 @@ export enum ErrorID {
|
|||
CONVERSATION_IS_PRIVATE = 0x2202
|
||||
}
|
||||
|
||||
export class CommandResult {
|
||||
class CommandResult {
|
||||
success: boolean;
|
||||
id: number;
|
||||
message: string;
|
||||
|
@ -37,39 +35,39 @@ export class CommandResult {
|
|||
}
|
||||
}
|
||||
|
||||
export interface ClientNameInfo {
|
||||
interface ClientNameInfo {
|
||||
//cluid=tYzKUryn\/\/Y8VBMf8PHUT6B1eiE= name=Exp clname=Exp cldbid=9
|
||||
client_unique_id: string;
|
||||
client_nickname: string;
|
||||
client_database_id: number;
|
||||
}
|
||||
|
||||
export interface ClientNameFromUid {
|
||||
interface ClientNameFromUid {
|
||||
promise: LaterPromise<ClientNameInfo[]>,
|
||||
keys: string[],
|
||||
response: ClientNameInfo[]
|
||||
}
|
||||
|
||||
export interface ServerGroupClient {
|
||||
interface ServerGroupClient {
|
||||
client_nickname: string;
|
||||
client_unique_identifier: string;
|
||||
client_database_id: number;
|
||||
}
|
||||
|
||||
export interface QueryListEntry {
|
||||
interface QueryListEntry {
|
||||
username: string;
|
||||
unique_id: string;
|
||||
bounded_server: number;
|
||||
}
|
||||
|
||||
export interface QueryList {
|
||||
interface QueryList {
|
||||
flag_own: boolean;
|
||||
flag_all: boolean;
|
||||
|
||||
queries: QueryListEntry[];
|
||||
}
|
||||
|
||||
export interface Playlist {
|
||||
interface Playlist {
|
||||
playlist_id: number;
|
||||
playlist_bot_id: number;
|
||||
playlist_title: string;
|
||||
|
@ -85,7 +83,7 @@ export interface Playlist {
|
|||
needed_power_song_remove: number;
|
||||
}
|
||||
|
||||
export interface PlaylistInfo {
|
||||
interface PlaylistInfo {
|
||||
playlist_id: number,
|
||||
playlist_title: string,
|
||||
playlist_description: string,
|
||||
|
@ -102,7 +100,7 @@ export interface PlaylistInfo {
|
|||
playlist_max_songs: number
|
||||
}
|
||||
|
||||
export interface PlaylistSong {
|
||||
interface PlaylistSong {
|
||||
song_id: number;
|
||||
song_previous_song_id: number;
|
||||
song_invoker: string;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
export namespace asn1 {
|
||||
namespace asn1 {
|
||||
declare class Int10 {
|
||||
constructor(value?: any);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export class Crc32 {
|
||||
class Crc32 {
|
||||
private static readonly lookup = [
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace hex {
|
||||
namespace hex {
|
||||
export function encode(buffer) {
|
||||
let hexCodes = [];
|
||||
let view = new DataView(buffer);
|
||||
|
|
|
@ -10,7 +10,7 @@ interface Window {
|
|||
}
|
||||
*/
|
||||
|
||||
export namespace sha {
|
||||
namespace sha {
|
||||
/*
|
||||
* [js-sha1]{@link https://github.com/emn178/js-sha1}
|
||||
*
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
export function guid() {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export namespace dns {
|
||||
namespace dns {
|
||||
export interface AddressTarget {
|
||||
target_ip: string;
|
||||
target_port?: number;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import {guid} from "./crypto/uid";
|
||||
import {PlaylistSong} from "./connection/ServerConnectionDeclaration";
|
||||
import {MusicClientEntry, SongInfo} from "./channel-tree/client";
|
||||
|
||||
export namespace events {
|
||||
namespace events {
|
||||
export interface EventConvert<All> {
|
||||
as<T extends keyof All>() : All[T];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export namespace i18n {
|
||||
|
||||
namespace i18n {
|
||||
interface CountryInfo {
|
||||
name: string;
|
||||
alpha_2: string;
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import {guid} from "../crypto/uid";
|
||||
import {log, LogCategory} from "../log";
|
||||
import {MessageHelper} from "../ui/frames/chat";
|
||||
import {StaticSettings} from "../settings";
|
||||
import {createErrorModal} from "../ui/elements/modal";
|
||||
function guid() {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
}
|
||||
|
||||
export namespace i18n {
|
||||
namespace i18n {
|
||||
export interface TranslationKey {
|
||||
message: string;
|
||||
line?: number;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
//Used by CertAccept popup
|
||||
|
||||
import {settings} from "./settings";
|
||||
|
||||
export enum LogCategory {
|
||||
enum LogCategory {
|
||||
CHANNEL,
|
||||
CHANNEL_PROPERTIES, /* separating channel and channel properties because on channel init logging is a big bottleneck */
|
||||
CLIENT,
|
||||
|
@ -21,7 +19,7 @@ export enum LogCategory {
|
|||
DNS
|
||||
}
|
||||
|
||||
export namespace log {
|
||||
namespace log {
|
||||
export enum LogType {
|
||||
TRACE,
|
||||
DEBUG,
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
/// <reference path="ui/frames/chat.ts" />
|
||||
/// <reference path="ui/modal/ModalConnect.ts" />
|
||||
/// <reference path="ui/modal/ModalCreateChannel.ts" />
|
||||
/// <reference path="ui/modal/ModalBanClient.ts" />
|
||||
/// <reference path="ui/modal/ModalYesNo.ts" />
|
||||
/// <reference path="ui/modal/ModalBanList.ts" />
|
||||
/// <reference path="settings.ts" />
|
||||
/// <reference path="log.ts" />
|
||||
/// <reference path="PPTListener.ts" />
|
||||
|
||||
import spawnYesNo = Modals.spawnYesNo;
|
||||
import {ConnectionHandler} from "./ConnectionHandler";
|
||||
import {bipc} from "./BrowserIPC";
|
||||
import {log, LogCategory} from "./log";
|
||||
import {profiles} from "./profiles/ConnectionProfile";
|
||||
import {Modals} from "./ui/modal/ModalConnect";
|
||||
import {settings, Settings} from "./settings";
|
||||
import {i18n} from "./i18n/localize";
|
||||
import {createInfoModal} from "./ui/elements/modal";
|
||||
import {MessageHelper} from "./ui/frames/chat";
|
||||
|
||||
export const js_render = window.jsrender || $;
|
||||
export const native_client = window.require !== undefined;
|
||||
const js_render = window.jsrender || $;
|
||||
const native_client = window.require !== undefined;
|
||||
|
||||
export function getUserMediaFunctionPromise() : (constraints: MediaStreamConstraints) => Promise<MediaStream> {
|
||||
function getUserMediaFunctionPromise() : (constraints: MediaStreamConstraints) => Promise<MediaStream> {
|
||||
if('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices)
|
||||
return constraints => navigator.mediaDevices.getUserMedia(constraints);
|
||||
|
||||
|
@ -23,12 +24,11 @@ export function getUserMediaFunctionPromise() : (constraints: MediaStreamConstra
|
|||
return constraints => new Promise<MediaStream>((resolve, reject) => _callbacked_function(constraints, resolve, reject));
|
||||
}
|
||||
|
||||
export interface Window {
|
||||
interface Window {
|
||||
open_connected_question: () => Promise<boolean>;
|
||||
}
|
||||
|
||||
export declare const nodeRequire: typeof require;
|
||||
export function setup_close() {
|
||||
function setup_close() {
|
||||
window.onbeforeunload = event => {
|
||||
if(profiles.requires_save())
|
||||
profiles.save();
|
||||
|
@ -50,7 +50,7 @@ export function setup_close() {
|
|||
}));
|
||||
|
||||
const exit = () => {
|
||||
const {remote} = nodeRequire('electron');
|
||||
const {remote} = require('electron');
|
||||
remote.getCurrentWindow().close();
|
||||
};
|
||||
|
||||
|
@ -80,8 +80,8 @@ export function setup_close() {
|
|||
};
|
||||
}
|
||||
|
||||
export declare function moment(...arguments) : any;
|
||||
export function setup_jsrender() : boolean {
|
||||
declare function moment(...arguments) : any;
|
||||
function setup_jsrender() : boolean {
|
||||
if(!js_render) {
|
||||
loader.critical_error("Missing jsrender extension!");
|
||||
return false;
|
||||
|
@ -115,7 +115,7 @@ export function setup_jsrender() : boolean {
|
|||
return true;
|
||||
}
|
||||
|
||||
export async function initialize() {
|
||||
async function initialize() {
|
||||
Settings.initialize();
|
||||
|
||||
try {
|
||||
|
@ -129,7 +129,7 @@ export async function initialize() {
|
|||
bipc.setup();
|
||||
}
|
||||
|
||||
export async function initialize_app() {
|
||||
async function initialize_app() {
|
||||
try { //Initialize main template
|
||||
const main = $("#tmpl_main").renderTag({
|
||||
multi_session: !settings.static_global(Settings.KEY_DISABLE_MULTI_SESSION),
|
||||
|
@ -180,7 +180,7 @@ export async function initialize_app() {
|
|||
setup_close();
|
||||
}
|
||||
|
||||
export function str2ab8(str) {
|
||||
function str2ab8(str) {
|
||||
const buf = new ArrayBuffer(str.length);
|
||||
const bufView = new Uint8Array(buf);
|
||||
for (let i = 0, strLen = str.length; i < strLen; i++) {
|
||||
|
@ -190,7 +190,7 @@ export function str2ab8(str) {
|
|||
}
|
||||
|
||||
/* FIXME Dont use atob, because it sucks for non UTF-8 tings */
|
||||
export function arrayBufferBase64(base64: string) {
|
||||
function arrayBufferBase64(base64: string) {
|
||||
base64 = atob(base64);
|
||||
const buf = new ArrayBuffer(base64.length);
|
||||
const bufView = new Uint8Array(buf);
|
||||
|
@ -200,7 +200,7 @@ export function arrayBufferBase64(base64: string) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
export function base64_encode_ab(source: ArrayBufferLike) {
|
||||
function base64_encode_ab(source: ArrayBufferLike) {
|
||||
const encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
let base64 = "";
|
||||
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
/// <reference path="../connection/ConnectionBase.ts" />
|
||||
|
||||
import {LaterPromise} from "../utils/helpers";
|
||||
import {PermissionManager, PermissionValue} from "./PermissionManager";
|
||||
import {AbstractCommandHandler, ServerCommand} from "../connection/ConnectionBase";
|
||||
import {ConnectionHandler} from "../ConnectionHandler";
|
||||
import {log, LogCategory} from "../log";
|
||||
import {CommandResult} from "../connection/ServerConnectionDeclaration";
|
||||
|
||||
export enum GroupType {
|
||||
enum GroupType {
|
||||
QUERY,
|
||||
TEMPLATE,
|
||||
NORMAL
|
||||
}
|
||||
|
||||
export enum GroupTarget {
|
||||
enum GroupTarget {
|
||||
SERVER,
|
||||
CHANNEL
|
||||
}
|
||||
|
||||
export class GroupProperties {
|
||||
class GroupProperties {
|
||||
iconid: number = 0;
|
||||
|
||||
sortid: number = 0;
|
||||
|
@ -26,12 +19,12 @@ export class GroupProperties {
|
|||
namemode: number = 0;
|
||||
}
|
||||
|
||||
export class GroupPermissionRequest {
|
||||
class GroupPermissionRequest {
|
||||
group_id: number;
|
||||
promise: LaterPromise<PermissionValue[]>;
|
||||
}
|
||||
|
||||
export class Group {
|
||||
class Group {
|
||||
properties: GroupProperties = new GroupProperties();
|
||||
|
||||
readonly handle: GroupManager;
|
||||
|
@ -70,7 +63,7 @@ export class Group {
|
|||
}
|
||||
}
|
||||
|
||||
export class GroupManager extends AbstractCommandHandler {
|
||||
class GroupManager extends connection.AbstractCommandHandler {
|
||||
readonly handle: ConnectionHandler;
|
||||
|
||||
serverGroups: Group[] = [];
|
||||
|
@ -90,7 +83,7 @@ export class GroupManager extends AbstractCommandHandler {
|
|||
this.channelGroups = undefined;
|
||||
}
|
||||
|
||||
handle_command(command: ServerCommand): boolean {
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
switch (command.command) {
|
||||
case "notifyservergrouplist":
|
||||
case "notifychannelgrouplist":
|
||||
|
|
|
@ -2,14 +2,7 @@
|
|||
/// <reference path="../connection/ConnectionBase.ts" />
|
||||
/// <reference path="../i18n/localize.ts" />
|
||||
|
||||
import {ConnectionHandler} from "../ConnectionHandler";
|
||||
import {log, LogCategory} from "../log";
|
||||
import {LaterPromise} from "../utils/helpers";
|
||||
import {AbstractCommandHandler, ServerCommand} from "../connection/ConnectionBase";
|
||||
import LogType = log.LogType;
|
||||
import {CommandResult, ErrorID} from "../connection/ServerConnectionDeclaration";
|
||||
|
||||
export enum PermissionType {
|
||||
enum PermissionType {
|
||||
B_SERVERINSTANCE_HELP_VIEW = "b_serverinstance_help_view",
|
||||
B_SERVERINSTANCE_VERSION_VIEW = "b_serverinstance_version_view",
|
||||
B_SERVERINSTANCE_INFO_VIEW = "b_serverinstance_info_view",
|
||||
|
@ -359,7 +352,7 @@ export enum PermissionType {
|
|||
I_FT_QUOTA_MB_UPLOAD_PER_CLIENT = "i_ft_quota_mb_upload_per_client"
|
||||
}
|
||||
|
||||
export class PermissionInfo {
|
||||
class PermissionInfo {
|
||||
name: string;
|
||||
id: number;
|
||||
description: string;
|
||||
|
@ -370,21 +363,21 @@ export class PermissionInfo {
|
|||
}
|
||||
}
|
||||
|
||||
export class PermissionGroup {
|
||||
class PermissionGroup {
|
||||
begin: number;
|
||||
end: number;
|
||||
deep: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class GroupedPermissions {
|
||||
class GroupedPermissions {
|
||||
group: PermissionGroup;
|
||||
permissions: PermissionInfo[];
|
||||
children: GroupedPermissions[];
|
||||
parent: GroupedPermissions;
|
||||
}
|
||||
|
||||
export class PermissionValue {
|
||||
class PermissionValue {
|
||||
readonly type: PermissionInfo;
|
||||
value: number;
|
||||
flag_skip: boolean;
|
||||
|
@ -418,13 +411,13 @@ export class PermissionValue {
|
|||
}
|
||||
}
|
||||
|
||||
export class NeededPermissionValue extends PermissionValue {
|
||||
class NeededPermissionValue extends PermissionValue {
|
||||
constructor(type, value) {
|
||||
super(type, value);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace permissions {
|
||||
namespace permissions {
|
||||
export type PermissionRequestKeys = {
|
||||
client_id?: number;
|
||||
channel_id?: number;
|
||||
|
@ -480,13 +473,13 @@ export namespace permissions {
|
|||
}
|
||||
}
|
||||
|
||||
export type RequestLists =
|
||||
type RequestLists =
|
||||
"requests_channel_permissions" |
|
||||
"requests_client_permissions" |
|
||||
"requests_client_channel_permissions" |
|
||||
"requests_playlist_permissions" |
|
||||
"requests_playlist_client_permissions";
|
||||
export class PermissionManager extends AbstractCommandHandler {
|
||||
class PermissionManager extends connection.AbstractCommandHandler {
|
||||
readonly handle: ConnectionHandler;
|
||||
|
||||
permissionList: PermissionInfo[] = [];
|
||||
|
@ -610,7 +603,7 @@ export class PermissionManager extends AbstractCommandHandler {
|
|||
this._cacheNeededPermissions = undefined;
|
||||
}
|
||||
|
||||
handle_command(command: ServerCommand): boolean {
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
switch (command.command) {
|
||||
case "notifyclientneededpermissions":
|
||||
this.onNeededPermissions(command.arguments);
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
import {MessageHelper} from "../ui/frames/chat";
|
||||
import {createErrorModal} from "../ui/elements/modal";
|
||||
import {guid} from "../crypto/uid";
|
||||
import {decode_identity, IdentitifyType, Identity} from "./Identity";
|
||||
import {static_forum_identity} from "./identities/TeaForumIdentity";
|
||||
import {TeaSpeakIdentity} from "./identities/TeamSpeakIdentity";
|
||||
import {AbstractServerConnection} from "../connection/ConnectionBase";
|
||||
import {connection} from "../connection/HandshakeHandler";
|
||||
|
||||
import HandshakeIdentityHandler = connection.HandshakeIdentityHandler;
|
||||
|
||||
export class ConnectionProfile {
|
||||
namespace profiles {
|
||||
export class ConnectionProfile {
|
||||
id: string;
|
||||
|
||||
profile_name: string;
|
||||
|
@ -17,7 +7,7 @@ export class ConnectionProfile {
|
|||
default_password: string;
|
||||
|
||||
selected_identity_type: string = "unset";
|
||||
identities: { [key: string]: Identity } = {};
|
||||
identities: { [key: string]: identities.Identity } = {};
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
|
@ -32,31 +22,31 @@ export class ConnectionProfile {
|
|||
return name || "Another TeaSpeak user";
|
||||
}
|
||||
|
||||
selected_identity(current_type?: IdentitifyType): Identity {
|
||||
selected_identity(current_type?: identities.IdentitifyType): identities.Identity {
|
||||
if (!current_type)
|
||||
current_type = this.selected_type();
|
||||
|
||||
if (current_type === undefined)
|
||||
return undefined;
|
||||
|
||||
if (current_type == IdentitifyType.TEAFORO) {
|
||||
return static_forum_identity();
|
||||
} else if (current_type == IdentitifyType.TEAMSPEAK || current_type == IdentitifyType.NICKNAME) {
|
||||
return this.identities[IdentitifyType[current_type].toLowerCase()];
|
||||
if (current_type == identities.IdentitifyType.TEAFORO) {
|
||||
return identities.static_forum_identity();
|
||||
} else if (current_type == identities.IdentitifyType.TEAMSPEAK || current_type == identities.IdentitifyType.NICKNAME) {
|
||||
return this.identities[identities.IdentitifyType[current_type].toLowerCase()];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
selected_type?(): IdentitifyType {
|
||||
return this.selected_identity_type ? IdentitifyType[this.selected_identity_type.toUpperCase()] : undefined;
|
||||
selected_type?(): identities.IdentitifyType {
|
||||
return this.selected_identity_type ? identities.IdentitifyType[this.selected_identity_type.toUpperCase()] : undefined;
|
||||
}
|
||||
|
||||
set_identity(type: IdentitifyType, identity: Identity) {
|
||||
this.identities[IdentitifyType[type].toLowerCase()] = identity;
|
||||
set_identity(type: identities.IdentitifyType, identity: identities.Identity) {
|
||||
this.identities[identities.IdentitifyType[type].toLowerCase()] = identity;
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler?(connection: AbstractServerConnection): HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler?(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler {
|
||||
const identity = this.selected_identity();
|
||||
if (!identity)
|
||||
return undefined;
|
||||
|
@ -86,9 +76,9 @@ export class ConnectionProfile {
|
|||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function decode_profile(data): Promise<ConnectionProfile | string> {
|
||||
async function decode_profile(data): Promise<ConnectionProfile | string> {
|
||||
data = JSON.parse(data);
|
||||
if (data.version !== 1)
|
||||
return "invalid version";
|
||||
|
@ -101,11 +91,11 @@ async function decode_profile(data): Promise<ConnectionProfile | string> {
|
|||
|
||||
if (data.identity_data) {
|
||||
for (const key in data.identity_data) {
|
||||
const type = IdentitifyType[key.toUpperCase() as string];
|
||||
const type = identities.IdentitifyType[key.toUpperCase() as string];
|
||||
const _data = data.identity_data[key];
|
||||
if (type == undefined) continue;
|
||||
|
||||
const identity = await decode_identity(type, _data);
|
||||
const identity = await identities.decode_identity(type, _data);
|
||||
if (identity == undefined) continue;
|
||||
|
||||
result.identities[key.toLowerCase()] = identity;
|
||||
|
@ -113,16 +103,16 @@ async function decode_profile(data): Promise<ConnectionProfile | string> {
|
|||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
interface ProfilesData {
|
||||
interface ProfilesData {
|
||||
version: number;
|
||||
profiles: string[];
|
||||
}
|
||||
}
|
||||
|
||||
let available_profiles: ConnectionProfile[] = [];
|
||||
let available_profiles: ConnectionProfile[] = [];
|
||||
|
||||
export async function load() {
|
||||
export async function load() {
|
||||
available_profiles = [];
|
||||
|
||||
const profiles_json = localStorage.getItem("profiles");
|
||||
|
@ -163,14 +153,14 @@ export async function load() {
|
|||
|
||||
/* generate default identity */
|
||||
try {
|
||||
const identity = await TeaSpeakIdentity.generate_new();
|
||||
const identity = await identities.TeaSpeakIdentity.generate_new();
|
||||
let active = true;
|
||||
setTimeout(() => {
|
||||
active = false;
|
||||
}, 1000);
|
||||
await identity.improve_level(8, 1, () => active);
|
||||
profile.set_identity(IdentitifyType.TEAMSPEAK, identity);
|
||||
profile.selected_identity_type = IdentitifyType[IdentitifyType.TEAMSPEAK];
|
||||
profile.set_identity(identities.IdentitifyType.TEAMSPEAK, identity);
|
||||
profile.selected_identity_type = identities.IdentitifyType[identities.IdentitifyType.TEAMSPEAK];
|
||||
} catch (error) {
|
||||
createErrorModal(tr("Failed to generate default identity"), tr("Failed to generate default identity!<br>Please manually generate the identity within your settings => profiles")).open();
|
||||
}
|
||||
|
@ -182,25 +172,25 @@ export async function load() {
|
|||
profile.default_username = "";
|
||||
profile.profile_name = "TeaSpeak Forum profile";
|
||||
|
||||
profile.set_identity(IdentitifyType.TEAFORO, static_forum_identity());
|
||||
profile.selected_identity_type = IdentitifyType[IdentitifyType.TEAFORO];
|
||||
profile.set_identity(identities.IdentitifyType.TEAFORO, identities.static_forum_identity());
|
||||
profile.selected_identity_type = identities.IdentitifyType[identities.IdentitifyType.TEAFORO];
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function create_new_profile(name: string, id?: string): ConnectionProfile {
|
||||
export function create_new_profile(name: string, id?: string): ConnectionProfile {
|
||||
const profile = new ConnectionProfile(id || guid());
|
||||
profile.profile_name = name;
|
||||
profile.default_username = "";
|
||||
available_profiles.push(profile);
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
let _requires_save = false;
|
||||
let _requires_save = false;
|
||||
|
||||
export function save() {
|
||||
export function save() {
|
||||
const profiles: string[] = [];
|
||||
for (const profile of available_profiles)
|
||||
profiles.push(profile.encode());
|
||||
|
@ -210,51 +200,52 @@ export function save() {
|
|||
profiles: profiles
|
||||
});
|
||||
localStorage.setItem("profiles", data);
|
||||
}
|
||||
}
|
||||
|
||||
export function mark_need_save() {
|
||||
export function mark_need_save() {
|
||||
_requires_save = true;
|
||||
}
|
||||
}
|
||||
|
||||
export function requires_save(): boolean {
|
||||
export function requires_save(): boolean {
|
||||
return _requires_save;
|
||||
}
|
||||
}
|
||||
|
||||
export function profiles(): ConnectionProfile[] {
|
||||
export function profiles(): ConnectionProfile[] {
|
||||
return available_profiles;
|
||||
}
|
||||
}
|
||||
|
||||
export function find_profile(id: string): ConnectionProfile | undefined {
|
||||
export function find_profile(id: string): ConnectionProfile | undefined {
|
||||
for (const profile of profiles())
|
||||
if (profile.id == id)
|
||||
return profile;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function find_profile_by_name(name: string): ConnectionProfile | undefined {
|
||||
export function find_profile_by_name(name: string): ConnectionProfile | undefined {
|
||||
name = name.toLowerCase();
|
||||
for (const profile of profiles())
|
||||
if ((profile.profile_name || "").toLowerCase() == name)
|
||||
return profile;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function default_profile(): ConnectionProfile {
|
||||
export function default_profile(): ConnectionProfile {
|
||||
return find_profile("default");
|
||||
}
|
||||
}
|
||||
|
||||
export function set_default_profile(profile: ConnectionProfile) {
|
||||
export function set_default_profile(profile: ConnectionProfile) {
|
||||
const old_default = default_profile();
|
||||
if (old_default && old_default != profile) {
|
||||
old_default.id = guid();
|
||||
}
|
||||
profile.id = "default";
|
||||
return old_default;
|
||||
}
|
||||
}
|
||||
|
||||
export function delete_profile(profile: ConnectionProfile) {
|
||||
export function delete_profile(profile: ConnectionProfile) {
|
||||
available_profiles.remove(profile);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,11 @@
|
|||
import {AbstractCommandHandler, AbstractServerConnection, ServerCommand} from "../connection/ConnectionBase";
|
||||
import {connection} from "../connection/HandshakeHandler";
|
||||
|
||||
import HandshakeIdentityHandler = connection.HandshakeIdentityHandler;
|
||||
import {NameIdentity} from "./identities/NameIdentity";
|
||||
import {TeaForumIdentity} from "./identities/TeaForumIdentity";
|
||||
import {TeaSpeakIdentity} from "./identities/TeamSpeakIdentity";
|
||||
|
||||
export enum IdentitifyType {
|
||||
namespace profiles.identities {
|
||||
export enum IdentitifyType {
|
||||
TEAFORO,
|
||||
TEAMSPEAK,
|
||||
NICKNAME
|
||||
}
|
||||
}
|
||||
|
||||
export interface Identity {
|
||||
export interface Identity {
|
||||
fallback_name(): string | undefined ;
|
||||
uid() : string;
|
||||
type() : IdentitifyType;
|
||||
|
@ -22,10 +15,10 @@ export interface Identity {
|
|||
encode?() : string;
|
||||
decode(data: string) : Promise<void>;
|
||||
|
||||
spawn_identity_handshake_handler(connection: AbstractServerConnection) : HandshakeIdentityHandler;
|
||||
}
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler;
|
||||
}
|
||||
|
||||
export async function decode_identity(type: IdentitifyType, data: string) : Promise<Identity> {
|
||||
export async function decode_identity(type: IdentitifyType, data: string) : Promise<Identity> {
|
||||
let identity: Identity;
|
||||
switch (type) {
|
||||
case IdentitifyType.NICKNAME:
|
||||
|
@ -50,9 +43,9 @@ export async function decode_identity(type: IdentitifyType, data: string) : Prom
|
|||
}
|
||||
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
|
||||
export function create_identity(type: IdentitifyType) {
|
||||
export function create_identity(type: IdentitifyType) {
|
||||
let identity: Identity;
|
||||
switch (type) {
|
||||
case IdentitifyType.NICKNAME:
|
||||
|
@ -66,18 +59,18 @@ export function create_identity(type: IdentitifyType) {
|
|||
break;
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
|
||||
export class HandshakeCommandHandler<T extends AbstractHandshakeIdentityHandler> extends AbstractCommandHandler {
|
||||
export class HandshakeCommandHandler<T extends AbstractHandshakeIdentityHandler> extends connection.AbstractCommandHandler {
|
||||
readonly handle: T;
|
||||
|
||||
constructor(connection: AbstractServerConnection, handle: T) {
|
||||
constructor(connection: connection.AbstractServerConnection, handle: T) {
|
||||
super(connection);
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
|
||||
handle_command(command: ServerCommand): boolean {
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
if($.isFunction(this[command.command]))
|
||||
this[command.command](command.arguments);
|
||||
else if(command.command == "error") {
|
||||
|
@ -87,14 +80,14 @@ export class HandshakeCommandHandler<T extends AbstractHandshakeIdentityHandler>
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractHandshakeIdentityHandler implements connection.HandshakeIdentityHandler {
|
||||
connection: AbstractServerConnection;
|
||||
export abstract class AbstractHandshakeIdentityHandler implements connection.HandshakeIdentityHandler {
|
||||
connection: connection.AbstractServerConnection;
|
||||
|
||||
protected callbacks: ((success: boolean, message?: string) => any)[] = [];
|
||||
|
||||
protected constructor(connection: AbstractServerConnection) {
|
||||
protected constructor(connection: connection.AbstractServerConnection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -113,4 +106,5 @@ export abstract class AbstractHandshakeIdentityHandler implements connection.Han
|
|||
for(const callback of this.callbacks)
|
||||
callback(false, message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,11 @@
|
|||
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
|
||||
import {log, LogCategory} from "../../log";
|
||||
import {AbstractServerConnection} from "../../connection/ConnectionBase";
|
||||
import {connection} from "../../connection/HandshakeHandler";
|
||||
/// <reference path="../Identity.ts" />
|
||||
|
||||
import HandshakeIdentityHandler = connection.HandshakeIdentityHandler;
|
||||
import {AbstractHandshakeIdentityHandler, HandshakeCommandHandler, IdentitifyType, Identity} from "../Identity";
|
||||
|
||||
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
namespace profiles.identities {
|
||||
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
readonly identity: NameIdentity;
|
||||
handler: HandshakeCommandHandler<NameHandshakeHandler>;
|
||||
|
||||
constructor(connection: AbstractServerConnection, identity: NameIdentity) {
|
||||
constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.NameIdentity) {
|
||||
super(connection);
|
||||
this.identity = identity;
|
||||
|
||||
|
@ -41,9 +36,9 @@ class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
|||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class NameIdentity implements Identity {
|
||||
export class NameIdentity implements Identity {
|
||||
private _name: string;
|
||||
|
||||
constructor(name?: string) {
|
||||
|
@ -86,7 +81,8 @@ export class NameIdentity implements Identity {
|
|||
});
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler(connection: AbstractServerConnection) : HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler {
|
||||
return new NameHandshakeHandler(connection, this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,11 @@
|
|||
import {AbstractServerConnection} from "../../connection/ConnectionBase";
|
||||
import {log, LogCategory} from "../../log";
|
||||
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
|
||||
import {forum} from "./teaspeak-forum";
|
||||
import {connection} from "../../connection/HandshakeHandler";
|
||||
import HandshakeIdentityHandler = connection.HandshakeIdentityHandler;
|
||||
import {AbstractHandshakeIdentityHandler, HandshakeCommandHandler, IdentitifyType, Identity} from "../Identity";
|
||||
/// <reference path="../Identity.ts" />
|
||||
|
||||
class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
namespace profiles.identities {
|
||||
class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
readonly identity: TeaForumIdentity;
|
||||
handler: HandshakeCommandHandler<TeaForumHandshakeHandler>;
|
||||
|
||||
constructor(connection: AbstractServerConnection, identity: TeaForumIdentity) {
|
||||
constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.TeaForumIdentity) {
|
||||
super(connection);
|
||||
this.identity = identity;
|
||||
this.handler = new HandshakeCommandHandler(connection, this);
|
||||
|
@ -54,9 +49,9 @@ class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
|||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TeaForumIdentity implements Identity {
|
||||
export class TeaForumIdentity implements Identity {
|
||||
private readonly identity_data: forum.Data;
|
||||
|
||||
valid() : boolean {
|
||||
|
@ -85,7 +80,7 @@ export class TeaForumIdentity implements Identity {
|
|||
});
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler(connection: AbstractServerConnection) : HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler {
|
||||
return new TeaForumHandshakeHandler(connection, this);
|
||||
}
|
||||
|
||||
|
@ -93,7 +88,7 @@ export class TeaForumIdentity implements Identity {
|
|||
return this.identity_data ? this.identity_data.name() : undefined;
|
||||
}
|
||||
|
||||
type(): IdentitifyType {
|
||||
type(): profiles.identities.IdentitifyType {
|
||||
return IdentitifyType.TEAFORO;
|
||||
}
|
||||
|
||||
|
@ -101,26 +96,27 @@ export class TeaForumIdentity implements Identity {
|
|||
//FIXME: Real UID!
|
||||
return "TeaForo#" + ((this.identity_data ? this.identity_data.name() : "Another TeaSpeak user"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let static_identity: TeaForumIdentity;
|
||||
let static_identity: TeaForumIdentity;
|
||||
|
||||
export function set_static_identity(identity: TeaForumIdentity) {
|
||||
export function set_static_identity(identity: TeaForumIdentity) {
|
||||
static_identity = identity;
|
||||
}
|
||||
}
|
||||
|
||||
export function update_forum() {
|
||||
export function update_forum() {
|
||||
if(forum.logged_in() && (!static_identity || static_identity.data() !== forum.data())) {
|
||||
static_identity = new TeaForumIdentity(forum.data());
|
||||
} else {
|
||||
static_identity = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function valid_static_forum_identity() : boolean {
|
||||
export function valid_static_forum_identity() : boolean {
|
||||
return static_identity && static_identity.valid();
|
||||
}
|
||||
}
|
||||
|
||||
export function static_forum_identity() : TeaForumIdentity | undefined {
|
||||
export function static_forum_identity() : TeaForumIdentity | undefined {
|
||||
return static_identity;
|
||||
}
|
||||
}
|
|
@ -1,15 +1,7 @@
|
|||
import {arrayBufferBase64, base64_encode_ab, str2ab8} from "../../main";
|
||||
import {sha} from "../../crypto/sha";
|
||||
import {asn1} from "../../crypto/asn1";
|
||||
import {AbstractServerConnection} from "../../connection/ConnectionBase";
|
||||
import {log, LogCategory} from "../../log";
|
||||
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
|
||||
import {settings} from "../../settings";
|
||||
import {connection} from "../../connection/HandshakeHandler";
|
||||
import HandshakeIdentityHandler = connection.HandshakeIdentityHandler;
|
||||
import {AbstractHandshakeIdentityHandler, HandshakeCommandHandler, IdentitifyType, Identity} from "../Identity";
|
||||
/// <reference path="../Identity.ts" />
|
||||
|
||||
export namespace CryptoHelper {
|
||||
namespace profiles.identities {
|
||||
export namespace CryptoHelper {
|
||||
export function base64_url_encode(str){
|
||||
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');
|
||||
}
|
||||
|
@ -216,13 +208,13 @@ export namespace CryptoHelper {
|
|||
kty:"EC",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
identity: TeaSpeakIdentity;
|
||||
handler: HandshakeCommandHandler<TeaSpeakHandshakeHandler>;
|
||||
|
||||
constructor(connection: AbstractServerConnection, identity: TeaSpeakIdentity) {
|
||||
constructor(connection: connection.AbstractServerConnection, identity: TeaSpeakIdentity) {
|
||||
super(connection);
|
||||
this.identity = identity;
|
||||
this.handler = new HandshakeCommandHandler(connection, this);
|
||||
|
@ -272,9 +264,9 @@ class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
|||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IdentityPOWWorker {
|
||||
class IdentityPOWWorker {
|
||||
private _worker: Worker;
|
||||
private _current_hash: string;
|
||||
private _best_level: number;
|
||||
|
@ -426,9 +418,9 @@ class IdentityPOWWorker {
|
|||
private handle_message(message: any) {
|
||||
log.info(LogCategory.IDENTITIES, tr("Received message: %o"), message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TeaSpeakIdentity implements Identity {
|
||||
export class TeaSpeakIdentity implements Identity {
|
||||
static async generate_new() : Promise<TeaSpeakIdentity> {
|
||||
let key: CryptoKeyPair;
|
||||
try {
|
||||
|
@ -872,7 +864,8 @@ export class TeaSpeakIdentity implements Identity {
|
|||
return base64_encode_ab(buffer.subarray(0, index));
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler(connection: AbstractServerConnection): HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler {
|
||||
return new TeaSpeakHandshakeHandler(connection, this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
import {Settings, settings} from "../../settings";
|
||||
import {update_forum} from "./TeaForumIdentity";
|
||||
|
||||
declare interface Window {
|
||||
interface Window {
|
||||
grecaptcha: GReCaptcha;
|
||||
}
|
||||
|
||||
export interface GReCaptcha {
|
||||
interface GReCaptcha {
|
||||
render(container: string | HTMLElement, parameters: {
|
||||
sitekey: string;
|
||||
theme?: "dark" | "light";
|
||||
|
@ -21,10 +18,10 @@ export interface GReCaptcha {
|
|||
reset(widget_id?: string);
|
||||
}
|
||||
|
||||
export namespace forum {
|
||||
namespace forum {
|
||||
export namespace gcaptcha {
|
||||
export async function initialize() {
|
||||
if(typeof((window as any).grecaptcha) === "undefined") {
|
||||
if(typeof(window.grecaptcha) === "undefined") {
|
||||
let script = document.createElement("script");
|
||||
script.async = true;
|
||||
|
||||
|
@ -53,7 +50,7 @@ export namespace forum {
|
|||
}
|
||||
}
|
||||
|
||||
if(typeof((window as any).grecaptcha) === "undefined")
|
||||
if(typeof(window.grecaptcha) === "undefined")
|
||||
throw tr("failed to load recaptcha");
|
||||
}
|
||||
|
||||
|
@ -65,9 +62,9 @@ export namespace forum {
|
|||
throw tr("initialisation failed");
|
||||
}
|
||||
if(container.attr("captcha-uuid"))
|
||||
(window as any).grecaptcha.reset(container.attr("captcha-uuid"));
|
||||
window.grecaptcha.reset(container.attr("captcha-uuid"));
|
||||
else {
|
||||
container.attr("captcha-uuid", (window as any).grecaptcha.render(container[0], {
|
||||
container.attr("captcha-uuid", window.grecaptcha.render(container[0], {
|
||||
"sitekey": key,
|
||||
callback: callback_data
|
||||
}));
|
||||
|
@ -209,7 +206,7 @@ export namespace forum {
|
|||
localStorage.setItem("teaspeak-forum-data", response["data"]);
|
||||
localStorage.setItem("teaspeak-forum-sign", response["sign"]);
|
||||
localStorage.setItem("teaspeak-forum-auth", response["auth-key"]);
|
||||
update_forum();
|
||||
profiles.identities.update_forum();
|
||||
} catch(error) {
|
||||
console.error(tr("Failed to parse forum given data: %o"), error);
|
||||
return {
|
||||
|
@ -269,7 +266,7 @@ export namespace forum {
|
|||
_data = new Data(_data.auth_key, response["data"], response["sign"]);
|
||||
localStorage.setItem("teaspeak-forum-data", response["data"]);
|
||||
localStorage.setItem("teaspeak-forum-sign", response["sign"]);
|
||||
update_forum();
|
||||
profiles.identities.update_forum();
|
||||
} catch(error) {
|
||||
console.error(tr("Failed to parse forum given data: %o"), error);
|
||||
throw tr("failed to parse data");
|
||||
|
@ -323,7 +320,7 @@ export namespace forum {
|
|||
localStorage.removeItem("teaspeak-forum-data");
|
||||
localStorage.removeItem("teaspeak-forum-sign");
|
||||
localStorage.removeItem("teaspeak-forum-auth");
|
||||
update_forum();
|
||||
profiles.identities.update_forum();
|
||||
}
|
||||
|
||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//Used by CertAccept popup
|
||||
|
||||
interface Array<T> {
|
||||
remove(elem?: T): boolean;
|
||||
last?(): T;
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/// <reference path="ui/elements/modal.ts" />
|
||||
//Used by CertAccept popup
|
||||
|
||||
import {log, LogCategory} from "./log";
|
||||
import {createErrorModal} from "./ui/elements/modal";
|
||||
|
||||
if(typeof(customElements) !== "undefined") {
|
||||
try {
|
||||
class X_Properties extends HTMLElement {}
|
||||
|
@ -17,7 +14,7 @@ if(typeof(customElements) !== "undefined") {
|
|||
}
|
||||
|
||||
/* T = value type */
|
||||
export interface SettingsKey<T> {
|
||||
interface SettingsKey<T> {
|
||||
key: string;
|
||||
|
||||
fallback_keys?: string | string[];
|
||||
|
@ -28,7 +25,7 @@ export interface SettingsKey<T> {
|
|||
require_restart?: boolean;
|
||||
}
|
||||
|
||||
export class SettingsBase {
|
||||
class SettingsBase {
|
||||
protected static readonly UPDATE_DIRECT: boolean = true;
|
||||
|
||||
protected static transformStO?<T>(input?: string, _default?: T, default_type?: string) : T {
|
||||
|
@ -80,7 +77,7 @@ export class SettingsBase {
|
|||
}
|
||||
}
|
||||
|
||||
export class StaticSettings extends SettingsBase {
|
||||
class StaticSettings extends SettingsBase {
|
||||
private static _instance: StaticSettings;
|
||||
static get instance() : StaticSettings {
|
||||
if(!this._instance)
|
||||
|
@ -142,7 +139,7 @@ export class StaticSettings extends SettingsBase {
|
|||
}
|
||||
}
|
||||
|
||||
export class Settings extends StaticSettings {
|
||||
class Settings extends StaticSettings {
|
||||
static readonly KEY_USER_IS_NEW: SettingsKey<boolean> = {
|
||||
key: 'user_is_new_user',
|
||||
default_value: true
|
||||
|
@ -436,7 +433,7 @@ export class Settings extends StaticSettings {
|
|||
}
|
||||
}
|
||||
|
||||
export class ServerSettings extends SettingsBase {
|
||||
class ServerSettings extends SettingsBase {
|
||||
private cacheServer = {};
|
||||
private _server_unique_id: string;
|
||||
private _server_save_worker: NodeJS.Timer;
|
||||
|
@ -514,4 +511,4 @@ export class ServerSettings extends SettingsBase {
|
|||
}
|
||||
}
|
||||
|
||||
export let settings: Settings;
|
||||
let settings: Settings;
|
|
@ -1,8 +1,4 @@
|
|||
import {settings} from "../settings";
|
||||
import {log, LogCategory} from "../log";
|
||||
import {ConnectionHandler} from "../ConnectionHandler";
|
||||
|
||||
export enum Sound {
|
||||
enum Sound {
|
||||
SOUND_TEST = "sound.test",
|
||||
SOUND_EGG = "sound.egg",
|
||||
|
||||
|
@ -65,7 +61,7 @@ export enum Sound {
|
|||
GROUP_CHANNEL_CHANGED_SELF = "group.channel.changed.self"
|
||||
}
|
||||
|
||||
export namespace sound {
|
||||
namespace sound {
|
||||
export interface SoundHandle {
|
||||
key: string;
|
||||
filename: string;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import {log, LogCategory} from "./log";
|
||||
|
||||
export namespace stats {
|
||||
namespace stats {
|
||||
const LOG_PREFIX = "[Statistics] ";
|
||||
|
||||
export enum CloseCodes {
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
.channel-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.channel-container .container-channel {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
width: 100%;
|
||||
min-height: 16px;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.channel-container .container-channel .channel-type {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.channel-container .container-channel .container-channel-name {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
justify-content: left;
|
||||
max-width: 100%;
|
||||
/* important for the repetitive channel name! */
|
||||
overflow-x: hidden;
|
||||
height: 16px;
|
||||
}
|
||||
.channel-container .container-channel .container-channel-name.align-right {
|
||||
justify-content: right;
|
||||
}
|
||||
.channel-container .container-channel .container-channel-name.align-center, .channel-container .container-channel .container-channel-name.align-repetitive {
|
||||
justify-content: center;
|
||||
}
|
||||
.channel-container .container-channel .container-channel-name .channel-name {
|
||||
align-self: center;
|
||||
color: #828282;
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.channel-container .container-channel .container-channel-name.align-repetitive .channel-name {
|
||||
text-overflow: clip;
|
||||
}
|
||||
.channel-container .container-channel .icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.channel-container .container-channel.move-selected {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
.channel-container .container-channel .show-channel-normal-only {
|
||||
display: none;
|
||||
}
|
||||
.channel-container .container-channel .show-channel-normal-only.channel-normal {
|
||||
display: block;
|
||||
}
|
||||
.channel-container .container-channel .icon_no_sound {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
.channel-container .container-channel .icon_no_sound .background {
|
||||
width: 10px;
|
||||
height: 14px;
|
||||
background: red;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 3px;
|
||||
z-index: -1;
|
||||
}
|
||||
.channel-container .container-clients {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=channel.css.map */
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"sourceRoot":"","sources":["channel.scss","colors.scss"],"names":[],"mappings":"AAEA;EACI;EACA;;AAEA;EACI;EAEA;EACA;EACA;EAEA;EACA;EAEA;EACA;;AAEA;EACI;EACA;EAEA;;AAGJ;EACI;EACA;EAEA;EACA;EAEA;EAEA;AAAiB;EACjB;EACA;;AAEA;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA,OC/CW;EDiDX;EACA;EACA;EACA;;AAIA;EACI;;AAKZ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAEA;EACI;;AAIR;EACI;EACA;;AAEA;EACI;EACA;EAEA;EACA;EACA;EACA;EACA;;AAKZ;EACI;EACA","file":"channel.css"}
|
|
@ -1,106 +0,0 @@
|
|||
@import "colors";
|
||||
|
||||
.channel-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.container-channel {
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
width: 100%;
|
||||
min-height: 16px;
|
||||
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.channel-type {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.container-channel-name {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
justify-content: left;
|
||||
|
||||
max-width: 100%; /* important for the repetitive channel name! */
|
||||
overflow-x: hidden;
|
||||
height: 16px;
|
||||
|
||||
&.align-right {
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
&.align-center, &.align-repetitive {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.channel-name {
|
||||
align-self: center;
|
||||
color: $channel-tree-entry-color;
|
||||
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&.align-repetitive {
|
||||
.channel-name {
|
||||
text-overflow: clip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.move-selected {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
.show-channel-normal-only {
|
||||
display: none;
|
||||
|
||||
&.channel-normal {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.icon_no_sound {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
.background {
|
||||
width: 10px;
|
||||
height: 14px;
|
||||
|
||||
background: red;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 3px;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-clients {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
import * as React from "react";
|
||||
import {ChannelEntry} from "../../channel-tree/channel";
|
||||
|
||||
const cssChannel = require("./channel.scss");
|
||||
const cssTree = require("./tree.scss");
|
||||
|
||||
class ChannelIcon extends React.Component<{ channel: ChannelEntry }, {}> {
|
||||
channel_icon_classes() {
|
||||
const class_list = [];
|
||||
const channel = this.props.channel;
|
||||
|
||||
if(channel.formattedChannelName() !== channel.channelName())
|
||||
return "channel-spacer";
|
||||
|
||||
let icon_color;
|
||||
if(channel.properties.channel_flag_password && !channel.cached_password())
|
||||
icon_color = "yellow";
|
||||
else if(channel.properties.channel_flag_maxclients_unlimited && channel.clients().length >= channel.properties.channel_maxclients)
|
||||
icon_color = "red";
|
||||
else if(channel.properties.channel_flag_maxfamilyclients_unlimited && channel.clients(true).length >= channel.properties.channel_maxfamilyclients)
|
||||
icon_color = "red";
|
||||
else
|
||||
icon_color = "green";
|
||||
|
||||
|
||||
return "channel-normal client-channel_" + icon_color + (channel.flag_subscribed ? "_subscribed" : "");
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.channel_icon_classes()} />;
|
||||
}
|
||||
}
|
||||
|
||||
class ChannelIcons extends React.Component<{channel: ChannelEntry}, {}> {
|
||||
render_icon(target: HTMLDivElement) {
|
||||
const props = this.props.channel.properties;
|
||||
if(!props.channel_icon_id) return;
|
||||
|
||||
const tag = this.props.channel.channelTree.client.fileManager.icons.generateTag(props.channel_icon_id);
|
||||
tag.appendTo($(target));
|
||||
}
|
||||
|
||||
render() {
|
||||
const icons = [];
|
||||
|
||||
const props = this.props.channel.properties;
|
||||
if(props.channel_flag_default) {
|
||||
icons.push(<div className={"show-channel-normal-only icon_entry icon_default icon client-channel_default"} title={tr("Default channel")} />);
|
||||
}
|
||||
if(props.channel_flag_password) {
|
||||
icons.push(<div className={"show-channel-normal-only icon_entry icon_password icon client-register"} title={tr("The channel is password protected")} />);
|
||||
}
|
||||
if(props.channel_codec_quality > 4) {
|
||||
icons.push(<div className={"show-channel-normal-only icon_entry icon_moderated icon client-moderated"} title={tr("Music quality")} />);
|
||||
}
|
||||
if(props.channel_needed_talk_power > 0) {
|
||||
icons.push(<div className={"show-channel-normal-only icon_entry icon_moderated icon client-moderated"} title={tr("Channel is moderated")} />);
|
||||
}
|
||||
if(props.channel_icon_id != 0) {
|
||||
icons.push(<div className={"show-channel-normal-only icon_entry channel_icon"} title={tr("Channel icon")} ref={e => this.render_icon(e) }/>)
|
||||
}
|
||||
if(!audio.codec.supported(props.channel_codec)) {
|
||||
icons.push(<div className={cssChannel.icon_no_sound}>
|
||||
<div className={cssChannel.background} />
|
||||
<div className={"icon_entry icon client-conflict-icon"} title={tr("You don't support the channel codec")} />
|
||||
</div>)
|
||||
}
|
||||
|
||||
return (<div className={cssChannel.icons}>{icons}</div>);
|
||||
}
|
||||
}
|
||||
|
||||
class ChannelLine extends React.Component<{ channel: ChannelEntry }, {}> {
|
||||
|
||||
render() {
|
||||
let depth = 1;
|
||||
let parent = this.props.channel;
|
||||
while((parent = parent.parent))
|
||||
depth++;
|
||||
|
||||
//TODO: On handle spacer alignments in channel name!
|
||||
return (
|
||||
<div className={cssChannel.containerChannel}>
|
||||
<div className={cssTree.markerTextUnread} />
|
||||
<div className={cssTree.depthFiller} style={{ width: depth + "em" }} />
|
||||
<ChannelIcon channel={this.props.channel} />
|
||||
<div className={cssChannel.containerChannelName}>
|
||||
<a className={cssChannel.channelName}>{this.props.channel.formattedChannelName()}</a>
|
||||
</div>
|
||||
<ChannelIcons channel={this.props.channel} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChannelClientsView extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
class SubChannelView extends React.Component<{ channels: ChannelEntry[] }, {}> {
|
||||
|
||||
render() {
|
||||
return this.props.channels.map(e => <ChannelLine channel={e} />);
|
||||
}
|
||||
}
|
||||
|
||||
export class Channel extends React.Component<{ channel: ChannelEntry }, {}> {
|
||||
children: ChannelEntry[];
|
||||
|
||||
channel_entry() : ChannelEntry { return this.props.channel; }
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={[cssTree.entry, cssChannel.channelContainer].join(" ")}>
|
||||
<ChannelLine channel={this.props.channel} />
|
||||
<ChannelClientsView />
|
||||
<SubChannelView channels={[]} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
|
||||
/*# sourceMappingURL=colors.css.map */
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"sourceRoot":"","sources":[],"names":[],"mappings":"","file":"colors.css"}
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
$channel-tree-new-message-color: #a814147F;
|
||||
$channel-tree-entry-color: #828282;
|
|
@ -1,38 +0,0 @@
|
|||
/* Some general browser helpers */
|
||||
.tree-container .tree .entry .depth-filler {
|
||||
font-size: 16px;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
.tree-container .marker-text-unread {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
background-color: #a814147F;
|
||||
opacity: 1;
|
||||
-moz-transition: opacity 0.25s;
|
||||
-o-transition: opacity 0.25s;
|
||||
-webkit-transition: opacity 0.25s;
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
.tree-container .marker-text-unread:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 24px;
|
||||
background: -moz-linear-gradient(left, rgba(168, 20, 20, 0.18) 0%, rgba(168, 20, 20, 0) 100%);
|
||||
/* FF3.6-15 */
|
||||
background: -webkit-linear-gradient(left, rgba(168, 20, 20, 0.18) 0%, rgba(168, 20, 20, 0) 100%);
|
||||
/* Chrome10-25,Safari5.1-6 */
|
||||
background: linear-gradient(to right, rgba(168, 20, 20, 0.18) 0%, rgba(168, 20, 20, 0) 100%);
|
||||
/* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
||||
}
|
||||
.tree-container .marker-text-unread.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=tree.css.map */
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"sourceRoot":"","sources":["../../../css/static/mixin.scss","tree.scss"],"names":[],"mappings":"AAAA;ACQY;EACI;EAEA;EACA;;AAKZ;EACI;EACA;EACA;EACA;EAEA;EACA;EAEA;EDvBP,iBC4CO;ED3CP,eC2CO;ED1CP,oBC0CO;EDzCP,YCyCO;;AAnBA;EACI;EACA;EAEA;EACA;EACA;EAEA;EAEA;AAAyF;EACzF;AAA2F;EAC3F;AAAuF;;AAG3F;EACI","file":"tree.css"}
|
|
@ -1,50 +0,0 @@
|
|||
@import "../../../css/static/mixin";
|
||||
@import "../../../css/static/properties";
|
||||
|
||||
.tree-container {
|
||||
.tree {
|
||||
|
||||
.entry {
|
||||
|
||||
.depth-filler {
|
||||
font-size: 16px;
|
||||
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.marker-text-unread {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 1px;
|
||||
background-color: #a814147F;
|
||||
|
||||
opacity: 1;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 24px;
|
||||
|
||||
background: -moz-linear-gradient(left, rgba(168,20,20,.18) 0%, rgba(168,20,20,0) 100%); /* FF3.6-15 */
|
||||
background: -webkit-linear-gradient(left, rgba(168,20,20,.18) 0%,rgba(168,20,20,0) 100%); /* Chrome10-25,Safari5.1-6 */
|
||||
background: linear-gradient(to right, rgba(168,20,20,.18) 0%,rgba(168,20,20,0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@include transition(opacity $button_hover_animation_time);
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import * as React from "react";
|
||||
|
||||
export class TreeView {
|
||||
|
||||
}
|
|
@ -1,15 +1,12 @@
|
|||
/// <reference path="view.ts" />
|
||||
/// <reference path="../utils/helpers.ts" />
|
||||
|
||||
import {ChannelTree} from "./view";
|
||||
import {ClientEntry} from "./client";
|
||||
|
||||
export enum ChannelType {
|
||||
enum ChannelType {
|
||||
PERMANENT,
|
||||
SEMI_PERMANENT,
|
||||
TEMPORARY
|
||||
}
|
||||
export namespace ChannelType {
|
||||
namespace ChannelType {
|
||||
export function normalize(mode: ChannelType) {
|
||||
let value: string = ChannelType[mode];
|
||||
value = value.toLowerCase();
|
||||
|
@ -17,13 +14,13 @@ export namespace ChannelType {
|
|||
}
|
||||
}
|
||||
|
||||
export enum ChannelSubscribeMode {
|
||||
enum ChannelSubscribeMode {
|
||||
SUBSCRIBED,
|
||||
UNSUBSCRIBED,
|
||||
INHERITED
|
||||
}
|
||||
|
||||
export class ChannelProperties {
|
||||
class ChannelProperties {
|
||||
channel_order: number = 0;
|
||||
channel_name: string = "";
|
||||
channel_name_phonetic: string = "";
|
||||
|
@ -58,7 +55,7 @@ export class ChannelProperties {
|
|||
channel_conversation_history_length: number = -1;
|
||||
}
|
||||
|
||||
export class ChannelEntry {
|
||||
class ChannelEntry {
|
||||
channelTree: ChannelTree;
|
||||
channelId: number;
|
||||
parent?: ChannelEntry;
|
|
@ -1,11 +1,8 @@
|
|||
/// <reference path="channel.ts" />
|
||||
/// <reference path="../ui/modal/ModalChangeVolume.ts" />
|
||||
/// <reference path="../ui/client_move.ts" />
|
||||
/// <reference path="modal/ModalChangeVolume.ts" />
|
||||
/// <reference path="client_move.ts" />
|
||||
|
||||
import {ChannelEntry} from "./channel";
|
||||
import {ChannelTree} from "./view";
|
||||
|
||||
export enum ClientType {
|
||||
enum ClientType {
|
||||
CLIENT_VOICE,
|
||||
CLIENT_QUERY,
|
||||
CLIENT_INTERNAL,
|
||||
|
@ -14,7 +11,7 @@ export enum ClientType {
|
|||
CLIENT_UNDEFINED
|
||||
}
|
||||
|
||||
export class ClientProperties {
|
||||
class ClientProperties {
|
||||
client_type: ClientType = ClientType.CLIENT_VOICE; //TeamSpeaks type
|
||||
client_type_exact: ClientType = ClientType.CLIENT_VOICE;
|
||||
|
||||
|
@ -60,7 +57,7 @@ export class ClientProperties {
|
|||
client_is_priority_speaker: boolean = false;
|
||||
}
|
||||
|
||||
export class ClientConnectionInfo {
|
||||
class ClientConnectionInfo {
|
||||
connection_bandwidth_received_last_minute_control: number = -1;
|
||||
connection_bandwidth_received_last_minute_keepalive: number = -1;
|
||||
connection_bandwidth_received_last_minute_speech: number = -1;
|
||||
|
@ -112,7 +109,7 @@ export class ClientConnectionInfo {
|
|||
connection_client_port: number = -1;
|
||||
}
|
||||
|
||||
export class ClientEntry {
|
||||
class ClientEntry {
|
||||
readonly events: events.Registry<events.channel_tree.client>;
|
||||
|
||||
protected _clientId: number;
|
||||
|
@ -1126,7 +1123,7 @@ export class ClientEntry {
|
|||
}
|
||||
}
|
||||
|
||||
export class LocalClientEntry extends ClientEntry {
|
||||
class LocalClientEntry extends ClientEntry {
|
||||
handle: ConnectionHandler;
|
||||
|
||||
private renaming: boolean;
|
||||
|
@ -1235,7 +1232,7 @@ export class LocalClientEntry extends ClientEntry {
|
|||
}
|
||||
}
|
||||
|
||||
export class MusicClientProperties extends ClientProperties {
|
||||
class MusicClientProperties extends ClientProperties {
|
||||
player_state: number = 0;
|
||||
player_volume: number = 0;
|
||||
|
||||
|
@ -1267,7 +1264,7 @@ export class MusicClientProperties extends ClientProperties {
|
|||
}
|
||||
*/
|
||||
|
||||
export class SongInfo {
|
||||
class SongInfo {
|
||||
song_id: number = 0;
|
||||
song_url: string = "";
|
||||
song_invoker: number = 0;
|
||||
|
@ -1280,7 +1277,7 @@ export class SongInfo {
|
|||
song_length: number = 0;
|
||||
}
|
||||
|
||||
export class MusicClientPlayerInfo extends SongInfo {
|
||||
class MusicClientPlayerInfo extends SongInfo {
|
||||
bot_id: number = 0;
|
||||
player_state: number = 0;
|
||||
|
||||
|
@ -1293,7 +1290,7 @@ export class MusicClientPlayerInfo extends SongInfo {
|
|||
player_description: string = "";
|
||||
}
|
||||
|
||||
export class MusicClientEntry extends ClientEntry {
|
||||
class MusicClientEntry extends ClientEntry {
|
||||
private _info_promise: Promise<MusicClientPlayerInfo>;
|
||||
private _info_promise_age: number = 0;
|
||||
private _info_promise_resolve: any;
|
|
@ -1,4 +1,6 @@
|
|||
export class ClientMover {
|
||||
/// <reference path="client.ts" />
|
||||
|
||||
class ClientMover {
|
||||
static readonly listener_root = $(document);
|
||||
static readonly move_element = $("#mouse-move");
|
||||
readonly channel_tree: ChannelTree;
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import {settings} from "../../settings";
|
||||
import {log, LogCategory} from "../../log";
|
||||
|
||||
declare const $: any;
|
||||
interface JQuery<TElement = HTMLElement> {
|
||||
dividerfy() : this;
|
||||
}
|
||||
|
||||
if(!$.fn.dividerfy) {
|
||||
$.fn.dividerfy = function<T extends HTMLElement>(this: JQuery<T>) : JQuery<T> {
|
||||
(this as any).find(".container-seperator").each(function (this: T) {
|
||||
this.find(".container-seperator").each(function (this: T) {
|
||||
if(!this.previousElementSibling) return;
|
||||
if(!this.nextElementSibling) return;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace contextmenu {
|
||||
namespace contextmenu {
|
||||
export interface MenuEntry {
|
||||
callback?: () => void;
|
||||
type: MenuEntryType;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import {KeyCode} from "../../PPTListener";
|
||||
/// <reference path="../../PPTListener.ts" />
|
||||
|
||||
export enum ElementType {
|
||||
enum ElementType {
|
||||
HEADER,
|
||||
BODY,
|
||||
FOOTER
|
||||
}
|
||||
|
||||
export type BodyCreator = (() => JQuery | JQuery[] | string) | string | JQuery | JQuery[];
|
||||
export const ModalFunctions = {
|
||||
type BodyCreator = (() => JQuery | JQuery[] | string) | string | JQuery | JQuery[];
|
||||
const ModalFunctions = {
|
||||
divify: function (val: JQuery) {
|
||||
if(val.length > 1)
|
||||
return $.spawn("div").append(val);
|
||||
|
@ -54,7 +54,7 @@ export const ModalFunctions = {
|
|||
}
|
||||
};
|
||||
|
||||
export class ModalProperties {
|
||||
class ModalProperties {
|
||||
template?: string;
|
||||
header: BodyCreator = () => "HEADER";
|
||||
body: BodyCreator = () => "BODY";
|
||||
|
@ -89,7 +89,7 @@ export class ModalProperties {
|
|||
full_size?: boolean = false;
|
||||
}
|
||||
|
||||
export namespace modal {
|
||||
namespace modal {
|
||||
export function initialize_modals() {
|
||||
register_global_events();
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ let _global_modal_count = 0;
|
|||
let _global_modal_last: HTMLElement;
|
||||
let _global_modal_last_time: number;
|
||||
|
||||
export class Modal {
|
||||
class Modal {
|
||||
private _htmlTag: JQuery;
|
||||
properties: ModalProperties;
|
||||
shown: boolean;
|
||||
|
@ -296,11 +296,11 @@ export class Modal {
|
|||
}
|
||||
}
|
||||
|
||||
export function createModal(data: ModalProperties | any) : Modal {
|
||||
function createModal(data: ModalProperties | any) : Modal {
|
||||
return new Modal(ModalFunctions.warpProperties(data));
|
||||
}
|
||||
|
||||
export class InputModalProperties extends ModalProperties {
|
||||
class InputModalProperties extends ModalProperties {
|
||||
maxLength?: number;
|
||||
|
||||
field_title?: string;
|
||||
|
@ -310,7 +310,7 @@ export class InputModalProperties extends ModalProperties {
|
|||
error_message?: string;
|
||||
}
|
||||
|
||||
export function createInputModal(headMessage: BodyCreator, question: BodyCreator, validator: (input: string) => boolean, callback: (flag: boolean | string) => void, props: InputModalProperties | any = {}) : Modal {
|
||||
function createInputModal(headMessage: BodyCreator, question: BodyCreator, validator: (input: string) => boolean, callback: (flag: boolean | string) => void, props: InputModalProperties | any = {}) : Modal {
|
||||
props = ModalFunctions.warpProperties(props);
|
||||
props.template_properties || (props.template_properties = {});
|
||||
props.template_properties.field_title = props.field_title;
|
||||
|
@ -370,7 +370,7 @@ export function createInputModal(headMessage: BodyCreator, question: BodyCreator
|
|||
return modal;
|
||||
}
|
||||
|
||||
export function createErrorModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: undefined }) {
|
||||
function createErrorModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: undefined }) {
|
||||
props = ModalFunctions.warpProperties(props);
|
||||
(props.template_properties || (props.template_properties = {})).header_class = "modal-header-error";
|
||||
|
||||
|
@ -382,7 +382,7 @@ export function createErrorModal(header: BodyCreator, message: BodyCreator, prop
|
|||
return modal;
|
||||
}
|
||||
|
||||
export function createInfoModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: undefined }) {
|
||||
function createInfoModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: undefined }) {
|
||||
props = ModalFunctions.warpProperties(props);
|
||||
(props.template_properties || (props.template_properties = {})).header_class = "modal-header-info";
|
||||
|
||||
|
@ -393,3 +393,73 @@ export function createInfoModal(header: BodyCreator, message: BodyCreator, props
|
|||
modal.htmlTag.find(".modal-body").addClass("modal-info");
|
||||
return modal;
|
||||
}
|
||||
|
||||
/* extend jquery */
|
||||
|
||||
interface ModalElements {
|
||||
header?: BodyCreator;
|
||||
body?: BodyCreator;
|
||||
footer?: BodyCreator;
|
||||
}
|
||||
|
||||
interface JQuery<TElement = HTMLElement> {
|
||||
modalize(entry_callback?: (header: JQuery, body: JQuery, footer: JQuery) => ModalElements | void, properties?: ModalProperties | any) : Modal;
|
||||
}
|
||||
|
||||
$.fn.modalize = function (this: JQuery, entry_callback?: (header: JQuery, body: JQuery, footer: JQuery) => ModalElements | void, properties?: ModalProperties | any) : Modal {
|
||||
properties = properties || {} as ModalProperties;
|
||||
entry_callback = entry_callback || ((a,b,c) => undefined);
|
||||
|
||||
let tag_modal = this[0].tagName.toLowerCase() == "modal" ? this : undefined; /* TODO may throw exception? */
|
||||
|
||||
let tag_head = tag_modal ? tag_modal.find("modal-header") : ModalFunctions.jqueriefy(properties.header);
|
||||
let tag_body = tag_modal ? tag_modal.find("modal-body") : this;
|
||||
let tag_footer = tag_modal ? tag_modal.find("modal-footer") : ModalFunctions.jqueriefy(properties.footer);
|
||||
|
||||
const result = entry_callback(tag_head as any, tag_body, tag_footer as any) || {};
|
||||
properties.header = result.header || tag_head;
|
||||
properties.body = result.body || tag_body;
|
||||
properties.footer = result.footer || tag_footer;
|
||||
return createModal(properties);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace net.graph {
|
||||
namespace net.graph {
|
||||
export type Entry = {
|
||||
timestamp: number;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface SliderOptions {
|
||||
interface SliderOptions {
|
||||
min_value?: number;
|
||||
max_value?: number;
|
||||
initial_value?: number;
|
||||
|
@ -8,11 +8,11 @@ export interface SliderOptions {
|
|||
value_field?: JQuery | JQuery[];
|
||||
}
|
||||
|
||||
export interface Slider {
|
||||
interface Slider {
|
||||
value(value?: number) : number;
|
||||
}
|
||||
|
||||
export function sliderfy(slider: JQuery, options?: SliderOptions) : Slider {
|
||||
function sliderfy(slider: JQuery, options?: SliderOptions) : Slider {
|
||||
options = Object.assign( {
|
||||
initial_value: 0,
|
||||
min_value: 0,
|
||||
|
|
161
shared/js/ui/elements/tab.ts
Normal file
161
shared/js/ui/elements/tab.ts
Normal file
|
@ -0,0 +1,161 @@
|
|||
/// <reference path="../../i18n/localize.ts" />
|
||||
|
||||
interface JQuery<TElement = HTMLElement> {
|
||||
asTabWidget(copy?: boolean) : JQuery<TElement>;
|
||||
tabify(copy?: boolean) : this;
|
||||
|
||||
changeElementType(type: string) : JQuery<TElement>;
|
||||
}
|
||||
|
||||
|
||||
if(typeof (customElements) !== "undefined") {
|
||||
try {
|
||||
class X_Tab extends HTMLElement {}
|
||||
class X_Entry extends HTMLElement {}
|
||||
class X_Tag extends HTMLElement {}
|
||||
class X_Content extends HTMLElement {}
|
||||
|
||||
customElements.define('x-tab', X_Tab, { extends: 'div' });
|
||||
customElements.define('x-entry', X_Entry, { extends: 'div' });
|
||||
customElements.define('x-tag', X_Tag, { extends: 'div' });
|
||||
customElements.define('x-content', X_Content, { extends: 'div' });
|
||||
} catch(error) {
|
||||
console.warn("failed to define costum elements");
|
||||
}
|
||||
} else {
|
||||
console.warn(tr("Could not defied tab customElements!"));
|
||||
}
|
||||
|
||||
var TabFunctions = {
|
||||
tabify(template: JQuery, copy: boolean = true) : JQuery {
|
||||
console.log("Tabify: copy=" + copy);
|
||||
console.log(template);
|
||||
|
||||
let tag = $.spawn("div");
|
||||
tag.addClass("tab");
|
||||
|
||||
let header = $.spawn("div");
|
||||
header.addClass("tab-header");
|
||||
|
||||
let content = $.spawn("div");
|
||||
content.addClass("tab-content");
|
||||
|
||||
content.append($.spawn("div").addClass("height-watcher"));
|
||||
|
||||
let silentContent = $.spawn("div");
|
||||
silentContent.addClass("tab-content-invisible");
|
||||
|
||||
/* add some kind of min height */
|
||||
const update_height = () => {
|
||||
const height_watcher = tag.find("> .tab-content .height-watcher");
|
||||
const entries: JQuery = tag.find("> .tab-content-invisible x-content, > .tab-content x-content");
|
||||
console.error(entries);
|
||||
let max_height = 0;
|
||||
|
||||
entries.each((_, _e) => {
|
||||
const entry = $(_e);
|
||||
const height = entry.visible_height();
|
||||
if(height > max_height)
|
||||
max_height = height;
|
||||
});
|
||||
|
||||
height_watcher.css('min-height', max_height + "px");
|
||||
tag.find(".window-resize-listener").trigger('resize');
|
||||
};
|
||||
|
||||
template.find("x-entry").each( (_, _entry) => {
|
||||
const entry = $(_entry);
|
||||
|
||||
const tag_header = $.spawn("div").addClass("entry");
|
||||
const tag_content = copy ? entry.find("x-content").clone(true, true) : entry.find("x-content");
|
||||
|
||||
{
|
||||
const header_tag = entry.find("x-tag");
|
||||
const header_data = copy ? header_tag.contents().clone(true, true) : header_tag.contents();
|
||||
|
||||
if(header_tag.attr("x-entry-class"))
|
||||
tag_header.addClass(header_tag.attr("x-entry-class"));
|
||||
if(header_tag.attr("x-entry-id"))
|
||||
tag_header.attr("x-id", header_tag.attr("x-entry-id"));
|
||||
|
||||
tag_header.append(header_data);
|
||||
|
||||
/* listener if the tab might got removed */
|
||||
tag_header.addClass("window-resize-listener");
|
||||
tag_header.on('resize', event => {
|
||||
if(!tag_header.is(':visible') && tag_header.hasClass('selected')) {
|
||||
let element = tag_header.next('.entry:visible');
|
||||
if(element.length == 0)
|
||||
element = tag_header.prev('.entry:visible');
|
||||
if(element.length == 0) {
|
||||
tag_header.removeClass("selected");
|
||||
tag_content.hide();
|
||||
} else {
|
||||
element.first().trigger('click');
|
||||
}
|
||||
console.log("Next: %o", tag_header.next('.entry:visible'));
|
||||
console.log("prev: %o", tag_header.prev('.entry:visible'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
content.append(tag_content.hide());
|
||||
|
||||
tag_header.on("click", () => {
|
||||
if(tag_header.hasClass("selected")) return;
|
||||
|
||||
tag.find(".tab-header .selected").removeClass("selected");
|
||||
tag_header.addClass("selected");
|
||||
|
||||
content.find("> x-content").hide();
|
||||
/* don't show many nodes at once */
|
||||
let entries = tag_content.find(".tab-show-partitional");
|
||||
entries.hide();
|
||||
const show_next = index => {
|
||||
console.log("Show " + index);
|
||||
if(index >= entries.length) return;
|
||||
entries.eq(index).show();
|
||||
|
||||
setTimeout(show_next.bind(undefined, index + 1), 0);
|
||||
};
|
||||
show_next(0);
|
||||
|
||||
tag_content.trigger('show');
|
||||
tag_content.show();
|
||||
});
|
||||
|
||||
console.log(this);
|
||||
header.append(tag_header);
|
||||
});
|
||||
|
||||
setTimeout(() => header.find(".entry").first().trigger("click"), 0);
|
||||
|
||||
tag.append(header);
|
||||
tag.append(content);
|
||||
tag.append(silentContent);
|
||||
|
||||
tag.on('tab.resize', update_height);
|
||||
return tag;
|
||||
}
|
||||
};
|
||||
|
||||
if(!$.fn.asTabWidget) {
|
||||
$.fn.asTabWidget = function (copy?: boolean) : JQuery {
|
||||
if($(this).prop("tagName") == "X-TAB")
|
||||
return TabFunctions.tabify($(this), typeof(copy) === "boolean" ? copy : true);
|
||||
else {
|
||||
throw "Invalid tag! " + $(this).prop("tagName");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$.fn.tabify) {
|
||||
$.fn.tabify = function (this: JQuery, copy?: boolean) {
|
||||
const wrapped_tag = $.spawn("div").append(this);
|
||||
wrapped_tag.find("x-tab").each((_, _element) => {
|
||||
const element = $(_element);
|
||||
element.replaceWith(element.asTabWidget(copy));
|
||||
});
|
||||
return wrapped_tag.children();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
export function tooltip(entry: JQuery) {
|
||||
function tooltip(entry: JQuery) {
|
||||
return tooltip.initialize(entry);
|
||||
}
|
||||
|
||||
export namespace tooltip {
|
||||
namespace tooltip {
|
||||
let _global_tooltip: JQuery;
|
||||
export type Handle = {
|
||||
show();
|
||||
|
|
|
@ -13,27 +13,12 @@
|
|||
client_away_message Value: ''
|
||||
*/
|
||||
|
||||
import {ConnectionHandler, DisconnectReason} from "../../ConnectionHandler";
|
||||
import {top_menu} from "./MenuBar";
|
||||
import {Settings, settings} from "../../settings";
|
||||
import {createErrorModal, createInfoModal, createInputModal} from "../elements/modal";
|
||||
import {default_recorder} from "../../voice/RecorderProfile";
|
||||
import {sound, Sound} from "../../sound/Sounds";
|
||||
import {Modals} from "../modal/ModalConnect";
|
||||
import {Modal as ModalsS} from "../modal/ModalSettings";
|
||||
import {log} from "./server_log";
|
||||
import {MessageHelper} from "./chat";
|
||||
import {CommandResult} from "../../connection/ServerConnectionDeclaration";
|
||||
import {PermissionType} from "../../permission/PermissionManager";
|
||||
import {bookmarks} from "../../bookmarks";
|
||||
import {contextmenu} from "../elements/context_menu";
|
||||
let control_bar: ControlBar; /* global variable to access the control bar */
|
||||
|
||||
export let control_bar: ControlBar; /* global variable to access the control bar */
|
||||
|
||||
export type MicrophoneState = "disabled" | "muted" | "enabled";
|
||||
export type HeadphoneState = "muted" | "enabled";
|
||||
export type AwayState = "away-global" | "away" | "online";
|
||||
export class ControlBar {
|
||||
type MicrophoneState = "disabled" | "muted" | "enabled";
|
||||
type HeadphoneState = "muted" | "enabled";
|
||||
type AwayState = "away-global" | "away" | "online";
|
||||
class ControlBar {
|
||||
private _button_away_active: AwayState;
|
||||
private _button_microphone: MicrophoneState;
|
||||
private _button_speakers: HeadphoneState;
|
||||
|
@ -436,7 +421,7 @@ export class ControlBar {
|
|||
}
|
||||
|
||||
private on_open_settings() {
|
||||
ModalsS.spawnSettingsModal();
|
||||
Modals.spawnSettingsModal();
|
||||
}
|
||||
|
||||
private on_open_connect() {
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
import {bookmarks} from "../../bookmarks";
|
||||
import {Modals} from "../modal/ModalBookmarks";
|
||||
import {DisconnectReason} from "../../ConnectionHandler";
|
||||
import {control_bar} from "./ControlBar";
|
||||
import {createErrorModal} from "../elements/modal";
|
||||
import {PermissionType} from "../../permission/PermissionManager";
|
||||
import {Sound} from "../../sound/Sounds";
|
||||
|
||||
export namespace top_menu {
|
||||
namespace top_menu {
|
||||
export interface HRItem { }
|
||||
|
||||
export interface MenuItem {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import {log, LogCategory} from "../../log";
|
||||
|
||||
export enum ChatType {
|
||||
enum ChatType {
|
||||
GENERAL,
|
||||
SERVER,
|
||||
CHANNEL,
|
||||
|
@ -8,7 +6,7 @@ export enum ChatType {
|
|||
}
|
||||
|
||||
declare const xbbcode: any;
|
||||
export namespace MessageHelper {
|
||||
namespace MessageHelper {
|
||||
export function htmlEscape(message: string) : string[] {
|
||||
const div = document.createElement('div');
|
||||
div.innerText = message;
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
/* the bar on the right with the chats (Channel & Client) */
|
||||
import {ChannelEntry} from "../../channel-tree/channel";
|
||||
import {Modals} from "../modal/ModalMusicManage";
|
||||
import {MessageHelper} from "./chat";
|
||||
import {ServerEntry} from "../../channel-tree/server";
|
||||
import {ConnectionHandler} from "../../ConnectionHandler";
|
||||
|
||||
export namespace chat {
|
||||
namespace chat {
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import {ConnectionHandler, DisconnectReason} from "../../ConnectionHandler";
|
||||
import {Settings, settings} from "../../settings";
|
||||
import {control_bar} from "./ControlBar";
|
||||
import {top_menu} from "./MenuBar";
|
||||
|
||||
export let server_connections: ServerConnectionManager;
|
||||
let server_connections: ServerConnectionManager;
|
||||
|
||||
export class ServerConnectionManager {
|
||||
class ServerConnectionManager {
|
||||
private connection_handlers: ConnectionHandler[] = [];
|
||||
private active_handler: ConnectionHandler | undefined;
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import {ConnectionHandler} from "../../ConnectionHandler";
|
||||
import {Settings, settings} from "../../settings";
|
||||
import {log, LogCategory} from "../../log";
|
||||
|
||||
export class Hostbanner {
|
||||
class Hostbanner {
|
||||
readonly html_tag: JQuery<HTMLElement>;
|
||||
readonly client: ConnectionHandler;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace image_preview {
|
||||
namespace image_preview {
|
||||
let preview_overlay: JQuery<HTMLDivElement>;
|
||||
let container_image: JQuery<HTMLDivElement>;
|
||||
let button_open_in_browser: JQuery;
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
import {ConnectionHandler, ViewReasonId} from "../../ConnectionHandler";
|
||||
import {PermissionInfo} from "../../permission/PermissionManager";
|
||||
import {htmltags} from "../htmltags";
|
||||
import {MessageHelper} from "./chat";
|
||||
import {i18n} from "../../i18n/localize";
|
||||
|
||||
export namespace server {
|
||||
namespace log {
|
||||
export namespace server {
|
||||
export enum Type {
|
||||
CONNECTION_BEGIN = "connection_begin",
|
||||
CONNECTION_HOSTNAME_RESOLVE = "connection_hostname_resolve",
|
||||
|
@ -265,9 +260,9 @@ export namespace server {
|
|||
return [$.spawn("div").addClass("log-error").text(data.message)]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ServerLog {
|
||||
export class ServerLog {
|
||||
private readonly handle: ConnectionHandler;
|
||||
private history_length: number = 100;
|
||||
|
||||
|
@ -369,14 +364,13 @@ export class ServerLog {
|
|||
}, 5) as any;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* impl of the parsers */
|
||||
export namespace server {
|
||||
namespace log {
|
||||
export namespace server {
|
||||
namespace impl {
|
||||
import MessageBuilders = server.MessageBuilders;
|
||||
import base = server.base;
|
||||
import tra = i18n.tra;
|
||||
const client_tag = (client: base.Client, braces?: boolean) => htmltags.generate_client_object({
|
||||
client_unique_id: client.client_unique_id,
|
||||
client_id: client.client_id,
|
||||
|
@ -390,7 +384,7 @@ export namespace server {
|
|||
add_braces: braces
|
||||
});
|
||||
|
||||
MessageBuilders["connection_begin"] = (data: server.event.ConnectBegin, options) => {
|
||||
MessageBuilders["connection_begin"] = (data: event.ConnectBegin, options) => {
|
||||
return MessageHelper.formatMessage(tr("Connecting to {0}{1}"), data.address.server_hostname, data.address.server_port == 9987 ? "" : (":" + data.address.server_port));
|
||||
};
|
||||
|
||||
|
@ -568,4 +562,5 @@ export namespace server {
|
|||
return result.map(e => e.addClass("log-error"));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export namespace chat {
|
||||
namespace chat {
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace chat {
|
||||
namespace chat {
|
||||
export namespace helpers {
|
||||
//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;
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
import {ClientEntry, LocalClientEntry} from "../../../channel-tree/client";
|
||||
import {Modals} from "../../modal/ModalClientInfo";
|
||||
import {htmltags} from "../../htmltags";
|
||||
import {image_preview} from "../image_preview";
|
||||
import {i18n} from "../../../i18n/country";
|
||||
import {GroupManager} from "../../../permission/GroupManager";
|
||||
|
||||
export namespace chat {
|
||||
namespace chat {
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {htmltags} from "../../htmltags";
|
||||
import {MessageHelper} from "../chat";
|
||||
import {CommandResult, ErrorID} from "../../../connection/ServerConnectionDeclaration";
|
||||
import {log, LogCategory} from "../../../log";
|
||||
import {createErrorModal} from "../../elements/modal";
|
||||
|
||||
export namespace chat {
|
||||
namespace chat {
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {MusicClientEntry} from "../../../channel-tree/client";
|
||||
import {image_preview} from "../image_preview";
|
||||
namespace chat {
|
||||
import PlayerState = connection.voice.PlayerState;
|
||||
|
||||
export namespace chat {
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* the bar on the right with the chats (Channel & Client) */
|
||||
import {log, LogCategory} from "../../../log";
|
||||
import {htmltags} from "../../htmltags";
|
||||
import {MessageHelper} from "../chat";
|
||||
|
||||
export namespace chat {
|
||||
namespace chat {
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace htmltags {
|
||||
namespace htmltags {
|
||||
let mouse_coordinates: {x: number, y: number} = {x: 0, y: 0};
|
||||
|
||||
function initialize() {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
function format_date(date: number) {
|
||||
const d = new Date(date);
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
//TODO: Test if we could render this image and not only the browser by knowing the type.
|
||||
export function spawnAvatarUpload(callback_data: (data: ArrayBuffer | undefined | null) => any) {
|
||||
const modal = createModal({
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
const avatar_to_uid = (id: string) => {
|
||||
const buffer = new Uint8Array(id.length / 2);
|
||||
for(let index = 0; index < id.length; index += 2) {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export type BanEntry = {
|
||||
name?: string;
|
||||
unique_id: string;
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../i18n/localize.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function openBanList(client: ConnectionHandler) {
|
||||
let modal: Modal;
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function spawnBookmarkModal() {
|
||||
let modal: Modal;
|
||||
modal = createModal({
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
let modal: Modal;
|
||||
export function spawnChangeLatency(client: ClientEntry, current: connection.voice.LatencySettings, reset: () => connection.voice.LatencySettings, apply: (settings: connection.voice.LatencySettings) => any, callback_flush?: () => any) {
|
||||
if(modal) modal.close();
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
//TODO: Use the max limit!
|
||||
|
||||
let modal: Modal;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function openChannelInfo(channel: ChannelEntry) {
|
||||
let modal: Modal;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
type InfoUpdateCallback = (info: ClientConnectionInfo) => any;
|
||||
export function openClientInfo(client: ClientEntry) {
|
||||
let modal: Modal;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
|
||||
//FIXME: Move this shit out of this file!
|
||||
export namespace connection_log {
|
||||
namespace connection_log {
|
||||
//TODO: Save password data
|
||||
export type ConnectionData = {
|
||||
name: string;
|
||||
|
@ -89,7 +91,7 @@ export namespace connection_log {
|
|||
});
|
||||
}
|
||||
|
||||
export namespace Modals {
|
||||
namespace Modals {
|
||||
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: profiles.ConnectionProfile, enforce: boolean}) {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
|
||||
namespace Modals {
|
||||
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
|
||||
const modal = createModal({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
let current_modal: Modal;
|
||||
export function createServerGroupAssignmentModal(client: ClientEntry, callback: (groups: number[], flag: boolean) => Promise<boolean>) {
|
||||
if(current_modal)
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: number) => any, selected_icon?: number) {
|
||||
selected_icon = selected_icon || 0;
|
||||
let allow_manage = client.permissions.neededPermission(PermissionType.B_ICON_MANAGE).granted(1);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function spawnTeamSpeakIdentityImprove(identity: profiles.identities.TeaSpeakIdentity, name: string): Modal {
|
||||
let modal: Modal;
|
||||
let elapsed_timer: NodeJS.Timer;
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
type URLGeneratorSettings = {
|
||||
flag_direct: boolean,
|
||||
flag_resolved: boolean
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function spawnKeySelect(callback: (key?: ppt.KeyEvent) => void) {
|
||||
let modal = createModal({
|
||||
header: tr("Select a key"),
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function openMusicManage(client: ConnectionHandler, bot: MusicClientEntry) {
|
||||
const ev_registry = new events.Registry<events.modal.music_manage>();
|
||||
ev_registry.enable_debug("music-manage");
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
const next_step: {[key: string]:string} = {
|
||||
"welcome": "microphone",
|
||||
//"microphone": app.is_web() ? "identity" : "speaker", /* speaker setup only for the native client! */
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function spawnPlaylistSongInfo(song: PlaylistSong) {
|
||||
let modal: Modal;
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../i18n/localize.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function spawnPlaylistManage(client: ConnectionHandler) {
|
||||
{
|
||||
createErrorModal(tr("Not implemented"), tr("Playlist management hasn't yet been implemented")).open();
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
let global_modal: PokeModal;
|
||||
|
||||
interface ServerEntry {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function spawnQueryCreate(connection: ConnectionHandler, callback_created?: (user, pass) => any) {
|
||||
let modal;
|
||||
modal = createModal({
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
export namespace Modals {
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
/*
|
||||
export function spawnQueryManage(client: ConnectionHandler) {
|
||||
let modal: Modal;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => Promise<void>) {
|
||||
const properties = Object.assign({}, server.properties);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function openServerInfo(server: ServerEntry) {
|
||||
let modal: Modal;
|
||||
let update_callbacks: ServerBandwidthInfoUpdateCallback[] = [];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export enum RequestInfoStatus {
|
||||
SUCCESS,
|
||||
UNKNOWN,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function spawnSettingsModal(default_page?: string) : Modal {
|
||||
let modal: Modal;
|
||||
modal = createModal({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {BodyCreator, ModalFunctions} from "../elements/modal";
|
||||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
|
||||
export namespace Modals {
|
||||
namespace Modals {
|
||||
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: {
|
||||
text_yes?: string,
|
||||
text_no?: string,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/// <reference path="./ModalPermissionEdit.ts" /> /* first needs the AbstractPermissionEdit */
|
||||
|
||||
/* Canvas Permission Editor */
|
||||
export namespace pe {
|
||||
namespace pe {
|
||||
namespace ui {
|
||||
export namespace scheme {
|
||||
export interface CheckBox {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue