canary
WolverinDEV 2018-04-16 20:38:35 +02:00
parent e357cf5aa6
commit bbb229b921
84 changed files with 2981 additions and 1432 deletions

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,16 @@
cursor: not-allowed;
}
.align_row {
display: flex;
flex-direction: row;
}
.align_column {
display: flex;
flex-direction: column;
}
.icon_loading {
border: 2px solid #f3f3f3; /* Light grey */
border-top: 2px solid #3498db; /* Blue */
@ -67,6 +77,16 @@
height: 14px!important;
}
.avatar_loading {
border: 2px solid #f3f3f3; /* Light grey */
border-top: 2px solid #3498db; /* Blue */
border-radius: 50%;
animation: spin 2s linear infinite;
width: 14px!important;
height: 14px!important;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
@ -177,6 +197,10 @@
width: 120px;
}
.channel_general_properties .value {
width: 100%;
}
.main_container {
padding: 4px;
border: lightgray solid;

21
css/modals.css Normal file
View File

@ -0,0 +1,21 @@
.channel_general_properties .value {
width: 100%;
}
.channel_general_properties .key {
width: 150px;
}
.channel_general_properties .property_entry {
margin: 2px;
}
.channel_perm_tbl .value {
width: 60px;
}
.input_error {
border-radius: 1px;
border-style: solid;
border-color: red;
}

View File

@ -90,6 +90,7 @@
display: flex;
height: auto;
position: relative;
flex-shrink: 0;
}
#chat .input .input_box {

View File

@ -7,18 +7,42 @@
-ms-user-select: none;
user-select: none;
vertical-align: center;
outline: none;
}
.channelTree * {
font-family: Arial;
font-size: 12px;
white-space: pre;
line-height: 1;
}
.channelTree div {
max-width: 100%;
height: 16px;
position: relative;
}
.channelTree .channel_type {
margin-right: 4px;
}
.channelTree .icon_client_state {
margin-right: 4px;
}
.channelTree .server_type {
margin-right: 4px;
}
.channelTree .icons .icon_entry {
margin-left: 2px;
}
.channelTree *{ font-family: Arial; font-size: 12px; white-space: pre; line-height: 1; }
.channelTree div{ max-width: 100%;height: 16px;position: relative;margin-right:4px;}
.channelTree img.loading {width: 50px;height: 50px;-webkit-animation:spin 2s linear infinite;-moz-animation:spin 2s linear infinite;animation:spin 2s linear infinite;}
@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
.channelTree div.l{text-align: left;}
.channelTree div.c{text-align: center;}
.channelTree div.r{text-align: right;}
.channelTree div.l {justify-content: flex-start; }
.channelTree div.c {justify-content: center;}
.channelTree div.r {justify-content: flex-end;}
.channelTree div.solidline{ background: url('../images/viewer/spacer_solidline.gif') repeat-x left center;margin: 0px; }
.channelTree div.dashline{ background: url('../images/viewer/spacer_dashline.gif') repeat-x left center;margin: 0px; }
@ -29,8 +53,26 @@
.channelTree div * {vertical-align: middle;display:inline-block;height: 16px;padding: 0px;}
.channelTree div img {border: 0;}
.channelTree div span {position: absolute; right: 0;}
.channelTree .name {vertical-align: middle; margin-top: 1px; height: 14px;}
.channelTree .own_name {font-weight: bold;}
.channelTree .name {
vertical-align: middle;
margin-top: 1px;
height: 14px;
display: inline;
}
.channelTree .own_name {
font-weight: bold;
display: inline;
}
.channelTree .channel_name {
display: flex;
align-items: center;
}
.channelTree .channel_name_container {
display: inline-flex;
width: 100%;
overflow-x: hidden;
}
.channelTree .country {width:16px;height:11px;}
@ -40,6 +82,7 @@
margin-bottom: -2px;
display: grid;
width: 100%;
left: 16px;
}
.channelTree .channel {
@ -53,6 +96,7 @@
margin-bottom: -2px;
display: grid;
width: 100%;
left: 16px;
}
.channelTree .client {
@ -70,6 +114,10 @@
.channelTree .channelLine {
position: absolute;
width: calc(100% - 16px);
display: flex;
flex-direction: row;
top: 0px;
left: 16px;
}

View File

@ -42,6 +42,10 @@ x-tab { display:none }
margin-bottom: -1px;
display: flex;
user-select: none;
flex-direction: row;
justify-content: stretch;
width: 100%;
}
.tab .tab-header .entry {
@ -56,6 +60,7 @@ x-tab { display:none }
padding-left: 5px;
padding-right: 5px;
cursor: pointer;
flex-grow: 1;
}
.tab .tab-content-invisible {

BIN
img/script.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

66
img/script.svg Normal file
View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
<g>
<path d="M6.5,41v15c0,1.009,1.22,2,2.463,2h40.074c1.243,0,2.463-0.991,2.463-2V41H6.5z M27.021,51.566
c0,0.474-0.087,0.873-0.26,1.196c-0.174,0.323-0.406,0.583-0.697,0.779c-0.292,0.196-0.627,0.333-1.005,0.41
s-0.769,0.116-1.169,0.116c-0.201,0-0.436-0.021-0.704-0.062s-0.547-0.104-0.834-0.191s-0.563-0.185-0.827-0.294
c-0.265-0.109-0.488-0.232-0.67-0.369l0.697-1.107c0.091,0.063,0.221,0.13,0.39,0.198s0.353,0.132,0.554,0.191
c0.2,0.06,0.41,0.111,0.629,0.157s0.424,0.068,0.615,0.068c0.482,0,0.868-0.094,1.155-0.28s0.439-0.504,0.458-0.95v-7.711h1.668
V51.566z M34.958,52.298c-0.15,0.342-0.362,0.643-0.636,0.902s-0.611,0.467-1.012,0.622c-0.401,0.155-0.857,0.232-1.367,0.232
c-0.219,0-0.444-0.012-0.677-0.034s-0.468-0.062-0.704-0.116c-0.237-0.055-0.463-0.13-0.677-0.226s-0.399-0.212-0.554-0.349
l0.287-1.176c0.127,0.073,0.289,0.144,0.485,0.212s0.398,0.132,0.608,0.191c0.209,0.06,0.419,0.107,0.629,0.144
c0.209,0.036,0.405,0.055,0.588,0.055c0.556,0,0.982-0.13,1.278-0.39s0.444-0.645,0.444-1.155c0-0.31-0.105-0.574-0.314-0.793
c-0.21-0.219-0.472-0.417-0.786-0.595s-0.654-0.355-1.019-0.533c-0.365-0.178-0.707-0.388-1.025-0.629
c-0.319-0.241-0.584-0.526-0.793-0.854c-0.21-0.328-0.314-0.738-0.314-1.23c0-0.446,0.082-0.843,0.246-1.189
s0.385-0.641,0.663-0.882s0.602-0.426,0.971-0.554s0.759-0.191,1.169-0.191c0.419,0,0.843,0.039,1.271,0.116
c0.428,0.077,0.774,0.203,1.039,0.376c-0.055,0.118-0.119,0.248-0.191,0.39c-0.073,0.142-0.142,0.273-0.205,0.396
c-0.064,0.123-0.119,0.226-0.164,0.308c-0.046,0.082-0.073,0.128-0.082,0.137c-0.055-0.027-0.116-0.063-0.185-0.109
s-0.167-0.091-0.294-0.137c-0.128-0.046-0.297-0.077-0.506-0.096c-0.21-0.019-0.479-0.014-0.807,0.014
c-0.183,0.019-0.355,0.07-0.52,0.157s-0.311,0.193-0.438,0.321c-0.128,0.128-0.229,0.271-0.301,0.431
c-0.073,0.159-0.109,0.313-0.109,0.458c0,0.364,0.104,0.658,0.314,0.882c0.209,0.224,0.469,0.419,0.779,0.588
c0.31,0.169,0.646,0.333,1.012,0.492c0.364,0.159,0.704,0.354,1.019,0.581s0.576,0.513,0.786,0.854
c0.209,0.342,0.314,0.781,0.314,1.319C35.184,51.603,35.108,51.956,34.958,52.298z"/>
<path d="M51.5,39V13.978c0-0.766-0.092-1.333-0.55-1.792L39.313,0.55C38.964,0.201,38.48,0,37.985,0H8.963
C7.777,0,6.5,0.916,6.5,2.926V39H51.5z M29.5,32c0,0.552-0.447,1-1,1s-1-0.448-1-1v-3c0-0.552,0.447-1,1-1s1,0.448,1,1V32z
M37.5,3.391c0-0.458,0.553-0.687,0.877-0.363l10.095,10.095C48.796,13.447,48.567,14,48.109,14H37.5V3.391z M36.5,23v-4
c0-0.551-0.448-1-1-1c-0.553,0-1-0.448-1-1s0.447-1,1-1c1.654,0,3,1.346,3,3v4c0,1.103,0.897,2,2,2c0.553,0,1,0.448,1,1
s-0.447,1-1,1c-1.103,0-2,0.897-2,2v4c0,1.654-1.346,3-3,3c-0.553,0-1-0.448-1-1s0.447-1,1-1c0.552,0,1-0.449,1-1v-4
c0-1.2,0.542-2.266,1.382-3C37.042,25.266,36.5,24.2,36.5,23z M28.5,21c0.828,0,1.5,0.672,1.5,1.5S29.328,24,28.5,24
S27,23.328,27,22.5S27.672,21,28.5,21z M16.5,25c1.103,0,2-0.897,2-2v-4c0-1.654,1.346-3,3-3c0.553,0,1,0.448,1,1s-0.447,1-1,1
c-0.552,0-1,0.449-1,1v4c0,1.2-0.542,2.266-1.382,3c0.84,0.734,1.382,1.8,1.382,3v4c0,0.551,0.448,1,1,1c0.553,0,1,0.448,1,1
s-0.447,1-1,1c-1.654,0-3-1.346-3-3v-4c0-1.103-0.897-2-2-2c-0.553,0-1-0.448-1-1S15.947,25,16.5,25z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,5 +1,5 @@
<?php
$testXF = true;
$testXF = false;
if(file_exists('auth.php'))
@ -23,13 +23,14 @@
<link rel="stylesheet" href="css/ts/client.css" type="text/css">
<link rel="stylesheet" href="css/ts/icons.css" type="text/css">
<link rel="stylesheet" href="css/general.css" type="text/css">
<link rel="stylesheet" href="css/modals.css" type="text/css">
<!-- PHP generated properies -->
<x-properties id="properties">
<!-- <x-property key="" value=""/> -->
<?php
function spawnProperty($name, $value) {
echo '<x-property key="' . $name . '" value="' . urlencode($value) . '"/>';
echo '<x-property key="' . $name . '" value="' . urlencode($value) . '"></x-property>';
}
spawnProperty('connect_default_host', $localhost ? "localhost" : "ts.TeaSpeak.de");
@ -44,7 +45,6 @@
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-113151733-4');
</script>
</head>

View File

@ -41,8 +41,7 @@ class DownloadFileTransfer {
let fileReader = new FileReader();
fileReader.onload = (event) => {
this.onBinaryData(new Uint8Array(event.target.result));
if (this._socket.readyState !== WebSocket.OPEN && !this._succeed)
this.on_fail("unexpected close");
//if(this._socket.readyState != WebSocket.OPEN && !this._succeed) this.on_fail("unexpected close");
this._parseActive = false;
};
fileReader.readAsArrayBuffer(data.data);
@ -66,7 +65,7 @@ class DownloadFileTransfer {
if (!this._active)
return;
if (!this._parseActive)
this.on_fail("unexpected close");
this.on_fail("unexpected close (remote closed)");
this.disconnect();
}
disconnect() {
@ -81,6 +80,7 @@ class FileManager {
this.downloadCounter = 0;
this.handle = client;
this.icons = new IconManager(this);
this.avatars = new AvatarManager(this);
this.handle.serverConnection.commandHandler["notifyfilelist"] = this.notifyFileList.bind(this);
this.handle.serverConnection.commandHandler["notifyfilelistfinished"] = this.notifyFileListFinished.bind(this);
this.handle.serverConnection.commandHandler["notifystartdownload"] = this.notifyStartDownload.bind(this);
@ -209,6 +209,7 @@ class IconManager {
let array = new Uint8Array(0);
ft.on_fail = reason => {
console.error("Could not download icon " + id + " -> " + reason);
chat.serverChat().appendError("Fail to download icon {0}. ({1})", id, JSON.stringify(reason));
reject(reason);
};
ft.on_start = () => { };
@ -227,6 +228,7 @@ class IconManager {
ft.startTransfer();
}).catch(reason => {
console.error("Error while downloading icon! (" + JSON.stringify(reason) + ")");
chat.serverChat().appendError("Failed to request download for icon {0}. ({1})", id, JSON.stringify(reason));
reject(reason);
});
});
@ -237,7 +239,7 @@ class IconManager {
return $("<div class='icon_empty'></div>");
else if (id < 1000)
return $("<div class='icon client-group_" + id + "'></div>");
let tag = $("<div></div>");
let tag = $.spawn("div");
tag.addClass("icon_empty");
let img = $.spawn("img");
img.attr("width", 16).attr("height", 16).attr("alt", "");
@ -248,7 +250,7 @@ class IconManager {
}
else {
img.attr("src", "file://null");
let loader = $("<div></div>");
let loader = $.spawn("div");
loader.addClass("icon_loading");
tag.append(loader);
this.loadIcon(id).then(icon => {
@ -262,6 +264,94 @@ class IconManager {
});
}).catch(reason => {
console.error("Could not load icon " + id + ". Reason: " + reason);
loader.removeClass("icon_loading").addClass("icon client-warning").attr("tag", "Could not load icon " + id);
});
}
return tag;
}
}
class Avatar {
}
class AvatarManager {
constructor(handle) {
this.handle = handle;
}
downloadAvatar(client) {
return this.handle.requestFileDownload("", "/avatar_" + client.avatarId());
}
resolveCached(client) {
let avatar = localStorage.getItem("avatar_" + client.properties.client_unique_identifier);
if (avatar) {
let i = JSON.parse(avatar);
if (i.base64.length > 0 && i.avatarId == client.properties.client_flag_avatar) {
return i;
}
}
return undefined;
}
loadAvatar(client) {
const _this = this;
return new Promise((resolve, reject) => {
let avatar = this.resolveCached(client);
if (avatar) {
resolve(avatar);
return;
}
_this.downloadAvatar(client).then(ft => {
let array = new Uint8Array(0);
ft.on_fail = reason => {
console.error("Could not download avatar " + client.properties.client_flag_avatar + " -> " + reason);
chat.serverChat().appendError("Fail to download avatar for {0}. ({1})", client.clientNickName(), JSON.stringify(reason));
reject(reason);
};
ft.on_start = () => { };
ft.on_data = (data) => {
array = concatenate(Uint8Array, array, data);
};
ft.on_complete = () => {
let base64 = btoa(String.fromCharCode.apply(null, array));
let avatar = new Avatar();
avatar.base64 = base64;
avatar.clientUid = client.clientUid();
avatar.avatarId = client.properties.client_flag_avatar;
localStorage.setItem("avatar_" + client.properties.client_unique_identifier, JSON.stringify(avatar));
resolve(avatar);
};
ft.startTransfer();
}).catch(reason => {
console.error("Error while downloading avatar! (" + JSON.stringify(reason) + ")");
chat.serverChat().appendError("Failed to request avatar download for {0}. ({1})", client.clientNickName(), JSON.stringify(reason));
reject(reason);
});
});
}
generateTag(client) {
let tag = $.spawn("div");
let img = $.spawn("img");
img.attr("alt", "");
let avatar = this.resolveCached(client);
if (avatar) {
img.attr("src", "data:image/png;base64," + avatar.base64);
tag.append(img);
}
else {
img.attr("src", "file://null");
let loader = $.spawn("div");
loader.addClass("avatar_loading");
tag.append(loader);
this.loadAvatar(client).then(avatar => {
img.attr("src", "data:image/png;base64," + avatar.base64);
console.debug("Avatar " + client.clientNickName() + " loaded :)");
img.css("opacity", 0);
tag.append(img);
loader.animate({ opacity: 0 }, 50, function () {
$(this).detach();
img.animate({ opacity: 1 }, 150);
});
}).catch(reason => {
console.error("Could not load avatar for " + client.clientNickName() + ". Reason: " + reason);
//TODO Broken image
loader.removeClass("avatar_loading").addClass("icon client-warning").attr("tag", "Could not load avatar " + client.clientNickName());
});
}
return tag;

File diff suppressed because one or more lines are too long

View File

@ -74,7 +74,7 @@ class DownloadFileTransfer {
let fileReader = new FileReader();
fileReader.onload = (event: any) => {
this.onBinaryData(new Uint8Array(event.target.result));
if(this._socket.readyState !== WebSocket.OPEN && !this._succeed) this.on_fail("unexpected close");
//if(this._socket.readyState != WebSocket.OPEN && !this._succeed) this.on_fail("unexpected close");
this._parseActive = false;
};
fileReader.readAsArrayBuffer(data.data);
@ -99,7 +99,7 @@ class DownloadFileTransfer {
private onClose() {
if(!this._active) return;
if(!this._parseActive) this.on_fail("unexpected close");
if(!this._parseActive) this.on_fail("unexpected close (remote closed)");
this.disconnect();
}
@ -112,6 +112,7 @@ class DownloadFileTransfer {
class FileManager {
handle: TSClient;
icons: IconManager;
avatars: AvatarManager;
private listRequests: FileListRequest[] = [];
private pendingDownloadTransfers: DownloadFileTransfer[] = [];
@ -120,6 +121,7 @@ class FileManager {
constructor(client: TSClient) {
this.handle = client;
this.icons = new IconManager(this);
this.avatars = new AvatarManager(this);
this.handle.serverConnection.commandHandler["notifyfilelist"] = this.notifyFileList.bind(this);
this.handle.serverConnection.commandHandler["notifyfilelistfinished"] = this.notifyFileListFinished.bind(this);
@ -277,6 +279,7 @@ class IconManager {
let array = new Uint8Array(0);
ft.on_fail = reason => {
console.error("Could not download icon " + id + " -> " + reason);
chat.serverChat().appendError("Fail to download icon {0}. ({1})", id, JSON.stringify(reason));
reject(reason);
};
ft.on_start = () => {};
@ -297,6 +300,7 @@ class IconManager {
ft.startTransfer();
}).catch(reason => {
console.error("Error while downloading icon! (" + JSON.stringify(reason) + ")");
chat.serverChat().appendError("Failed to request download for icon {0}. ({1})", id, JSON.stringify(reason));
reject(reason);
});
});
@ -309,7 +313,7 @@ class IconManager {
else if(id < 1000)
return $("<div class='icon client-group_" + id + "'></div>");
let tag = $("<div></div>");
let tag = $.spawn("div");
tag.addClass("icon_empty");
let img = $.spawn("img");
@ -322,7 +326,7 @@ class IconManager {
} else {
img.attr("src", "file://null");
let loader = $("<div></div>");
let loader = $.spawn("div");
loader.addClass("icon_loading");
tag.append(loader);
@ -338,6 +342,113 @@ class IconManager {
});
}).catch(reason => {
console.error("Could not load icon " + id + ". Reason: " + reason);
loader.removeClass("icon_loading").addClass("icon client-warning").attr("tag", "Could not load icon " + id);
});
}
return tag;
}
}
class Avatar {
clientUid: string;
avatarId: string;
base64: string;
}
class AvatarManager {
handle: FileManager;
constructor(handle: FileManager) {
this.handle = handle;
}
downloadAvatar(client: ClientEntry) : Promise<DownloadFileTransfer> {
return this.handle.requestFileDownload("", "/avatar_" + client.avatarId());
}
resolveCached?(client: ClientEntry) : Avatar {
let avatar = localStorage.getItem("avatar_" + client.properties.client_unique_identifier);
if(avatar) {
let i = JSON.parse(avatar) as Avatar;
if(i.base64.length > 0 && i.avatarId == client.properties.client_flag_avatar) { //TODO timestamp?
return i;
}
}
return undefined;
}
loadAvatar(client: ClientEntry) : Promise<Avatar> {
const _this = this;
return new Promise<Avatar>((resolve, reject) => {
let avatar = this.resolveCached(client);
if(avatar){
resolve(avatar);
return;
}
_this.downloadAvatar(client).then(ft => {
let array = new Uint8Array(0);
ft.on_fail = reason => {
console.error("Could not download avatar " + client.properties.client_flag_avatar + " -> " + reason);
chat.serverChat().appendError("Fail to download avatar for {0}. ({1})", client.clientNickName(), JSON.stringify(reason));
reject(reason);
};
ft.on_start = () => {};
ft.on_data = (data: Uint8Array) => {
array = concatenate(Uint8Array, array, data);
};
ft.on_complete = () => {
let base64 = btoa(String.fromCharCode.apply(null, array));
let avatar = new Avatar();
avatar.base64 = base64;
avatar.clientUid = client.clientUid();
avatar.avatarId = client.properties.client_flag_avatar;
localStorage.setItem("avatar_" + client.properties.client_unique_identifier, JSON.stringify(avatar));
resolve(avatar);
};
ft.startTransfer();
}).catch(reason => {
console.error("Error while downloading avatar! (" + JSON.stringify(reason) + ")");
chat.serverChat().appendError("Failed to request avatar download for {0}. ({1})", client.clientNickName(), JSON.stringify(reason));
reject(reason);
});
});
}
generateTag(client: ClientEntry) {
let tag = $.spawn("div");
let img = $.spawn("img");
img.attr("alt", "");
let avatar = this.resolveCached(client);
if(avatar) {
img.attr("src", "data:image/png;base64," + avatar.base64);
tag.append(img);
} else {
img.attr("src", "file://null");
let loader = $.spawn("div");
loader.addClass("avatar_loading");
tag.append(loader);
this.loadAvatar(client).then(avatar => {
img.attr("src", "data:image/png;base64," + avatar.base64);
console.debug("Avatar " + client.clientNickName() + " loaded :)");
img.css("opacity", 0);
tag.append(img);
loader.animate({opacity: 0}, 50, function () {
$(this).detach();
img.animate({opacity: 1}, 150);
});
}).catch(reason => {
console.error("Could not load avatar for " + client.clientNickName() + ". Reason: " + reason);
//TODO Broken image
loader.removeClass("avatar_loading").addClass("icon client-warning").attr("tag", "Could not load avatar " + client.clientNickName());
});
}

View File

@ -168,7 +168,8 @@ class InfoBar {
}
this._htmlTag.append(channelGroup);
}
const _this = this;
if (this._currentSelected.properties.client_flag_avatar.length > 0)
this.handle.fileManager.avatars.generateTag(this._currentSelected).appendTo(this._htmlTag);
this.intervals.push(setInterval(this.updateClientTimings.bind(this), 1000));
}
}

File diff suppressed because one or more lines are too long

View File

@ -196,8 +196,8 @@ class InfoBar {
this._htmlTag.append(channelGroup);
}
const _this = this;
if(this._currentSelected.properties.client_flag_avatar.length > 0)
this.handle.fileManager.avatars.generateTag(this._currentSelected).appendTo(this._htmlTag);
this.intervals.push(setInterval(this.updateClientTimings.bind(this),1000));
}
}

View File

@ -56,8 +56,6 @@ class ChatEntry {
this.history = [];
this.onClose = function () { return true; };
}
static tagify(message, ...args) {
}
appendError(message, ...args) {
this.appendMessage("<a style='color: red'>{0}</a>".format(ChatMessage.formatMessage(message).format(...args)), false);
}
@ -215,23 +213,19 @@ class ChatEntry {
class ChatBox {
constructor(htmlTag) {
this.htmlTag = htmlTag;
const _this = this;
$(this.htmlTag).find(".input button").click(this.onSend.bind(this));
let chatBox = $(this.htmlTag).find(".input_box");
chatBox.keypress(function (e) {
if (e.keyCode == 13 /* Enter */ && !e.shiftKey) {
_this.onSend();
this.htmlTag.find(".input button").click(this.onSend.bind(this));
this.htmlTag.find(".input_box").keypress(event => {
if (event.keyCode == 13 /* Enter */ && !event.shiftKey) {
this.onSend();
return false;
}
});
chatBox.on('input', function (e) {
let text = $(this).val().toString();
if (_this.testMessage(text))
$(_this.htmlTag).find(".input button").removeAttr("disabled");
}).on('input', (event) => {
let text = $(event.target).val().toString();
if (this.testMessage(text))
this.htmlTag.find(".input button").removeAttr("disabled");
else
$(_this.htmlTag).find(".input button").attr("disabled", "true");
});
chatBox.trigger("input");
this.htmlTag.find(".input button").attr("disabled", "true");
}).trigger("input");
this.chats = [];
this._activeChat = undefined;
this.createChat("chat_server", ChatType.SERVER).onMessageSend = (text) => {
@ -248,11 +242,15 @@ class ChatBox {
}
globalClient.serverConnection.sendMessage(text, ChatType.CHANNEL, globalClient.getClient().currentChannel());
};
globalClient.permissions.initializedListener.push(flag => {
if (flag)
this.activeChat0(this._activeChat);
});
}
createChat(key, type = ChatType.CLIENT) {
let chat = new ChatEntry(this, type, key);
this.chats.push(chat);
$(this.htmlTag).find(".chats").append(chat.htmlTag);
this.htmlTag.find(".chats").append(chat.htmlTag);
if (!this._activeChat)
this.activeChat = chat;
return chat;
@ -288,13 +286,30 @@ class ChatBox {
return;
if (this._activeChat == chat)
return;
this.activeChat0(chat);
}
activeChat0(chat) {
this._activeChat = chat;
for (let e of this.chats)
e.htmlTag.removeClass("active");
let flagAllowSend = false;
if (this._activeChat) {
this._activeChat.htmlTag.addClass("active");
this._activeChat.displayHistory();
if (globalClient && globalClient.permissions && globalClient.permissions.initialized())
switch (this._activeChat.type) {
case ChatType.CLIENT:
flagAllowSend = true;
break;
case ChatType.SERVER:
flagAllowSend = globalClient.permissions.neededPermission(PermissionType.B_CLIENT_SERVER_TEXTMESSAGE_SEND).granted(1);
break;
case ChatType.CHANNEL:
flagAllowSend = globalClient.permissions.neededPermission(PermissionType.B_CLIENT_CHANNEL_TEXTMESSAGE_SEND).granted(1);
break;
}
}
this.htmlTag.find(".input_box").prop("disabled", !flagAllowSend);
}
get activeChat() { return this._activeChat; }
channelChat() {

File diff suppressed because one or more lines are too long

View File

@ -82,10 +82,6 @@ class ChatEntry {
this.onClose = function () { return true; }
}
static tagify(message: string, ...args) {
}
appendError(message: string, ...args) {
this.appendMessage("<a style='color: red'>{0}</a>".format(ChatMessage.formatMessage(message).format(...args)), false);
}
@ -248,30 +244,26 @@ class ChatEntry {
class ChatBox {
htmlTag: any;
htmlTag: JQuery;
chats: ChatEntry[];
private _activeChat: ChatEntry;
constructor(htmlTag) {
constructor(htmlTag: JQuery) {
this.htmlTag = htmlTag;
const _this = this;
$(this.htmlTag).find(".input button").click(this.onSend.bind(this));
let chatBox = $(this.htmlTag).find(".input_box");
chatBox.keypress(function (e) {
if(e.keyCode == Key.Enter && !e.shiftKey) {
_this.onSend();
this.htmlTag.find(".input button").click(this.onSend.bind(this));
this.htmlTag.find(".input_box").keypress(event => {
if(event.keyCode == Key.Enter && !event.shiftKey) {
this.onSend();
return false;
}
});
chatBox.on('input', function (e) {
let text = $(this).val().toString();
if(_this.testMessage(text))
$(_this.htmlTag).find(".input button").removeAttr("disabled");
}).on('input', (event) => {
let text = $(event.target).val().toString();
if(this.testMessage(text))
this.htmlTag.find(".input button").removeAttr("disabled");
else
$(_this.htmlTag).find(".input button").attr("disabled", "true");
});
chatBox.trigger("input");
this.htmlTag.find(".input button").attr("disabled", "true");
}).trigger("input");
this.chats = [];
this._activeChat = undefined;
@ -291,12 +283,16 @@ class ChatBox {
globalClient.serverConnection.sendMessage(text, ChatType.CHANNEL, globalClient.getClient().currentChannel());
};
globalClient.permissions.initializedListener.push(flag => {
if(flag) this.activeChat0(this._activeChat);
});
}
createChat(key, type : ChatType = ChatType.CLIENT) : ChatEntry {
let chat = new ChatEntry(this, type, key);
this.chats.push(chat);
$(this.htmlTag).find(".chats").append(chat.htmlTag);
this.htmlTag.find(".chats").append(chat.htmlTag);
if(!this._activeChat) this.activeChat = chat;
return chat;
}
@ -333,14 +329,33 @@ class ChatBox {
set activeChat(chat : ChatEntry) {
if(this.chats.indexOf(chat) === -1) return;
if(this._activeChat == chat) return;
this.activeChat0(chat);
}
private activeChat0(chat: ChatEntry) {
this._activeChat = chat;
for(let e of this.chats)
e.htmlTag.removeClass("active");
let flagAllowSend = false;
if(this._activeChat) {
this._activeChat.htmlTag.addClass("active");
this._activeChat.displayHistory();
if(globalClient && globalClient.permissions && globalClient.permissions.initialized())
switch (this._activeChat.type) {
case ChatType.CLIENT:
flagAllowSend = true;
break;
case ChatType.SERVER:
flagAllowSend = globalClient.permissions.neededPermission(PermissionType.B_CLIENT_SERVER_TEXTMESSAGE_SEND).granted(1);
break;
case ChatType.CHANNEL:
flagAllowSend = globalClient.permissions.neededPermission(PermissionType.B_CLIENT_CHANNEL_TEXTMESSAGE_SEND).granted(1);
break;
}
}
this.htmlTag.find(".input_box").prop("disabled", !flagAllowSend);
}
get activeChat(){ return this._activeChat; }

View File

@ -46,7 +46,6 @@ var ViewReasonId;
class TSClient {
constructor() {
this._clientId = 0;
this.settings = new Settings(this);
this.selectInfo = new InfoBar(this, $("#select_info"));
this.channelTree = new ChannelTree(this, $("#channelTree"));
this.serverConnection = new ServerConnection(this);
@ -73,7 +72,7 @@ class TSClient {
}
else {
host = addr;
port = 19974;
port = 9987;
}
console.log("Start connection to " + host + ":" + port);
this.channelTree.initialiseHead(addr);
@ -95,9 +94,9 @@ class TSClient {
onConnected() {
console.log("Client connected!");
this.channelTree.registerClient(this._ownEntry);
this.settings.loadServer();
this.serverConnection.sendCommand("channelsubscribeall");
settings.setServer(this.channelTree.server);
this.permissions.requestPermissionList();
this.serverConnection.sendCommand("channelsubscribeall");
if (this.groups.serverGroups.length == 0)
this.groups.requestGroups();
this.controlBar.updateProperties();

View File

@ -1 +1 @@
{"version":3,"file":"client.js","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"client.js","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"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"}

View File

@ -53,13 +53,11 @@ class TSClient {
permissions: PermissionManager;
groups: GroupManager;
controlBar: ControlBar;
settings: Settings;
private _clientId: number = 0;
private _ownEntry: LocalClientEntry;
constructor() {
this.settings = new Settings(this);
this.selectInfo = new InfoBar(this, $("#select_info"));
this.channelTree = new ChannelTree(this, $("#channelTree"));
this.serverConnection = new ServerConnection(this);
@ -89,7 +87,7 @@ class TSClient {
host = addr.substr(0, idx);
} else {
host = addr;
port = 19974;
port = 9987;
}
console.log("Start connection to " + host + ":" + port);
this.channelTree.initialiseHead(addr);
@ -118,9 +116,9 @@ class TSClient {
onConnected() {
console.log("Client connected!");
this.channelTree.registerClient(this._ownEntry);
this.settings.loadServer();
this.serverConnection.sendCommand("channelsubscribeall");
settings.setServer(this.channelTree.server);
this.permissions.requestPermissionList();
this.serverConnection.sendCommand("channelsubscribeall");
if(this.groups.serverGroups.length == 0)
this.groups.requestGroups();
this.controlBar.updateProperties();

1
js/codec/compile.sh Executable file
View File

@ -0,0 +1 @@
/usr/local/bin/tsc

View File

@ -128,17 +128,34 @@ class ServerConnection {
}
}
handleCommand(json) {
console.log("Handling command '" + json["command"] + "'");
let fn = this.commandHandler[json["command"]];
if (fn === undefined) {
console.log("Missing command '" + json["command"] + "'");
return;
let group = log.group(log.LogType.DEBUG, LogCategory.NETWORKING, "Handling command '%s'", json["command"]);
group.log("Handling command '" + json["command"] + "'");
group.group(log.LogType.TRACE, "Json:").collapsed(true).log("%o", json).end();
try {
let fn = this.commandHandler[json["command"]];
if (fn === undefined) {
group.log("Missing command '" + json["command"] + "'");
return;
}
fn.call(this.commandHandler, json["data"]);
}
finally {
group.end();
}
fn.call(this.commandHandler, json["data"]);
}
sendData(data) {
this._socket.send(data);
}
commandiefy(input) {
return JSON.stringify(input, (key, value) => {
switch (typeof value) {
case "boolean": return value == true ? "1" : "0";
case "function": return value();
default:
return value;
}
});
}
sendCommand(command, data = {}, logResult = true) {
const _this = this;
let result = new Promise((resolve, failed) => {
@ -154,7 +171,7 @@ class ServerConnection {
listener.reject("timeout");
}, 1500);
this._retListener.push(listener);
this._socket.send(JSON.stringify({
this._socket.send(this.commandiefy({
"type": "command",
"command": command,
"data": _data
@ -298,8 +315,8 @@ class ConnectionCommandHandler {
console.log("Setting up voice ");
this.connection._client.voiceConnection.createSession();
json = json[0]; //Only one bulk
this.connection._client.clientId = json["aclid"];
this.connection._client.getClient().updateVariable("client_nickname", json["acn"]);
this.connection._client.clientId = parseInt(json["aclid"]);
this.connection._client.getClient().updateVariables({ key: "client_nickname", value: json["acn"] });
for (let key in json) {
if (key === "aclid")
continue;
@ -313,7 +330,7 @@ class ConnectionCommandHandler {
}
createChannelFromJson(json, ignoreOrder = false) {
let tree = this.connection._client.channelTree;
let channel = new ChannelEntry(json["cid"], json["channel_name"], tree.findChannel(json["cpid"]));
let channel = new ChannelEntry(parseInt(json["cid"]), json["channel_name"], tree.findChannel(json["cpid"]));
tree.insertChannel(channel);
if (json["channel_order"] !== "0") {
let prev = tree.findChannel(json["channel_order"]);
@ -337,6 +354,7 @@ class ConnectionCommandHandler {
}
}
}
let updates = [];
for (let key in json) {
if (key === "cid")
continue;
@ -350,8 +368,9 @@ class ConnectionCommandHandler {
continue;
if (key === "reasonid")
continue;
channel.updateProperty(key, json[key]);
updates.push({ key: key, value: json[key] });
}
channel.updateVariables(...updates);
}
handleCommandChannelList(json) {
console.log("Got " + json.length + " new channels");
@ -381,7 +400,7 @@ class ConnectionCommandHandler {
let old_channel = tree.findChannel(json["cfid"]);
client = tree.findClient(json["clid"]);
if (!client) {
client = new ClientEntry(json["clid"], json["client_nickname"]);
client = new ClientEntry(parseInt(json["clid"]), json["client_nickname"]);
client = tree.insertClient(client, channel);
}
else {
@ -397,6 +416,7 @@ class ConnectionCommandHandler {
chat.serverChat().appendMessage("{0} connected to channel {1}", true, client.createChatTag(true), channel.createChatTag(true));
}
}
let updates = [];
for (let key in json) {
if (key == "cfid")
continue;
@ -410,8 +430,9 @@ class ConnectionCommandHandler {
continue;
if (key === "reasonid")
continue;
client.updateVariable(key, json[key]);
updates.push({ key: key, value: json[key] });
}
client.updateVariables(...updates);
}
handleCommandClientLeftView(json) {
json = json[0]; //Only one bulk
@ -517,6 +538,7 @@ class ConnectionCommandHandler {
console.error("Unknown channel edit (Channel)!");
return 0;
}
let updates = [];
for (let key in json) {
if (key === "cid")
continue;
@ -528,8 +550,9 @@ class ConnectionCommandHandler {
continue;
if (key === "reasonid")
continue;
channel.updateProperty(key, json[key]);
updates.push({ key: key, value: json[key] });
}
channel.updateVariables(...updates);
}
handleNotifyTextMessage(json) {
json = json[0]; //Only one bulk
@ -567,11 +590,13 @@ class ConnectionCommandHandler {
console.error("Tried to update an non existing client");
return;
}
let updates = [];
for (let key in json) {
if (key == "clid")
continue;
client.updateVariable(key, json[key]);
updates.push({ key: key, value: json[key] });
}
client.updateVariables(...updates);
if (this.connection._client.selectInfo.currentSelected == client)
this.connection._client.selectInfo.update();
}

File diff suppressed because one or more lines are too long

View File

@ -158,20 +158,37 @@ class ServerConnection {
}
handleCommand(json) {
console.log("Handling command '" + json["command"] + "'");
let group = log.group(log.LogType.DEBUG, LogCategory.NETWORKING, "Handling command '%s'", json["command"]);
group.log("Handling command '" + json["command"] + "'");
group.group(log.LogType.TRACE, "Json:").collapsed(true).log("%o", json).end();
let fn = this.commandHandler[json["command"]];
if(fn === undefined) {
console.log("Missing command '" + json["command"] + "'");
return;
try {
let fn = this.commandHandler[json["command"]];
if(fn === undefined) {
group.log("Missing command '" + json["command"] + "'");
return;
}
fn.call(this.commandHandler, json["data"]);
} finally {
group.end();
}
fn.call(this.commandHandler, json["data"]);
}
sendData(data: any) { //TODO check stuff?
this._socket.send(data);
}
private commandiefy(input: any) : string {
return JSON.stringify(input, (key, value) => {
switch (typeof value) {
case "boolean": return value == true ? "1" : "0";
case "function": return value();
default:
return value;
}
});
}
sendCommand(command: string, data: any = {}, logResult: boolean = true) : Promise<CommandResult> {
const _this = this;
let result = new Promise<CommandResult>((resolve, failed) => {
@ -189,7 +206,7 @@ class ServerConnection {
}, 1500);
this._retListener.push(listener);
this._socket.send(JSON.stringify({
this._socket.send(this.commandiefy({
"type": "command",
"command": command,
"data": _data
@ -352,8 +369,8 @@ class ConnectionCommandHandler {
json = json[0]; //Only one bulk
this.connection._client.clientId = json["aclid"];
this.connection._client.getClient().updateVariable("client_nickname", json["acn"]);
this.connection._client.clientId = parseInt(json["aclid"]);
this.connection._client.getClient().updateVariables({key: "client_nickname", value: json["acn"]});
for(let key in json) {
if(key === "aclid") continue;
@ -368,7 +385,7 @@ class ConnectionCommandHandler {
private createChannelFromJson(json, ignoreOrder: boolean = false) {
let tree = this.connection._client.channelTree;
let channel = new ChannelEntry(json["cid"], json["channel_name"], tree.findChannel(json["cpid"]));
let channel = new ChannelEntry(parseInt(json["cid"]), json["channel_name"], tree.findChannel(json["cpid"]));
tree.insertChannel(channel);
if(json["channel_order"] !== "0") {
let prev = tree.findChannel(json["channel_order"]);
@ -394,6 +411,10 @@ class ConnectionCommandHandler {
}
}
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key === "cid") continue;
if(key === "cpid") continue;
@ -402,8 +423,9 @@ class ConnectionCommandHandler {
if(key === "invokeruid") continue;
if(key === "reasonid") continue;
channel.updateProperty(key, json[key]);
updates.push({key: key, value: json[key]});
}
channel.updateVariables(...updates);
}
handleCommandChannelList(json) {
@ -441,7 +463,7 @@ class ConnectionCommandHandler {
client = tree.findClient(json["clid"]);
if(!client) {
client = new ClientEntry(json["clid"], json["client_nickname"]);
client = new ClientEntry(parseInt(json["clid"]), json["client_nickname"]);
client = tree.insertClient(client, channel);
} else {
if(client == this.connection._client.getClient())
@ -458,6 +480,11 @@ class ConnectionCommandHandler {
}
}
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key == "cfid") continue;
if(key == "ctid") continue;
@ -466,8 +493,10 @@ class ConnectionCommandHandler {
if(key === "invokeruid") continue;
if(key === "reasonid") continue;
client.updateVariable(key, json[key]);
updates.push({key: key, value: json[key]});
}
client.updateVariables(...updates);
}
handleCommandClientLeftView(json) {
@ -602,14 +631,20 @@ class ConnectionCommandHandler {
console.error("Unknown channel edit (Channel)!");
return 0;
}
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key === "cid") continue;
if(key === "invokerid") continue;
if(key === "invokername") continue;
if(key === "invokeruid") continue;
if(key === "reasonid") continue;
channel.updateProperty(key, json[key]);
updates.push({key: key, value: json[key]});
}
channel.updateVariables(...updates);
}
handleNotifyTextMessage(json) {
@ -648,10 +683,16 @@ class ConnectionCommandHandler {
console.error("Tried to update an non existing client");
return;
}
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key == "clid") continue;
client.updateVariable(key, json[key]);
updates.push({key: key, value: json[key]});
}
client.updateVariables(...updates);
if(this.connection._client.selectInfo.currentSelected == client)
this.connection._client.selectInfo.update();
}

View File

@ -73,7 +73,7 @@ function spawnMenu(x, y, ...entries) {
tag.append("<div class='" + icon + "'></div>");
tag.append("<div>" + ($.isFunction(entry.name) ? entry.name() : entry.name) + "</div>");
menu.append(tag);
if (entry.disabled)
if (entry.disabled || entry.invalidPermission)
tag.addClass("disabled");
else {
tag.click(function () {

View File

@ -1 +1 @@
{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["contextMenu.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["contextMenu.ts"],"names":[],"mappings":"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"}

View File

@ -57,6 +57,7 @@ function spawnMenu(x, y, ...entries: {
name: (() => string) | string;
icon: (() => string) | string;
disabled?: boolean;
invalidPermission?: boolean;
}[]) {
const menu = $("#contextMenu");
menu.empty();
@ -82,7 +83,7 @@ function spawnMenu(x, y, ...entries: {
menu.append(tag);
if(entry.disabled) tag.addClass("disabled");
if(entry.disabled || entry.invalidPermission) tag.addClass("disabled");
else {
tag.click(function () {
if($.isFunction(entry.callback)) entry.callback();

20
js/crypto/hex.ts Normal file
View File

@ -0,0 +1,20 @@
namespace hex {
export function encode(buffer) {
let hexCodes = [];
let view = new DataView(buffer);
for (let i = 0; i < view.byteLength % 4; i ++) {
let value = view.getUint32(i * 4);
let stringValue = value.toString(16);
let padding = '00000000';
let paddedValue = (padding + stringValue).slice(-padding.length);
hexCodes.push(paddedValue);
}
for (let i = (view.byteLength % 4) * 4; i < view.byteLength; i++) {
let value = view.getUint8(i).toString(16);
let padding = '00';
hexCodes.push((padding + value).slice(-padding.length));
}
return hexCodes.join("");
}
}

9
js/crypto/sha.ts Normal file
View File

@ -0,0 +1,9 @@
//Source: https://www.movable-type.co.uk/scripts/sha1.html
namespace sha {
export function sha1(message: string | ArrayBuffer) : PromiseLike<ArrayBuffer> {
let buffer = message instanceof ArrayBuffer ? message : new TextEncoder("utf-8").encode(message);
return crypto.subtle.digest("SHA-1", buffer);
}
}

View File

@ -69,8 +69,14 @@ function loadDebug() {
awaitLoad(loadScripts([
//Load general API's
"js/log.js",
"js/utils/modal.js",
"js/utils/tab.js",
"js/utils/helpers.js",
"js/crypto/sha.js",
"js/crypto/hex.js",
//Load UI
"js/ui/modal/ModalConnect.js",

121
js/log.ts Normal file
View File

@ -0,0 +1,121 @@
enum LogCategory {
CHANNEL,
CLIENT,
PERMISSIONS,
GENERAL,
NETWORKING
}
namespace log {
export enum LogType {
TRACE,
DEBUG,
INFO,
WARNING,
ERROR
}
let category_mapping = new Map<number, string>([
[LogCategory.CHANNEL, "Channel "],
[LogCategory.CLIENT, "Client "],
[LogCategory.PERMISSIONS, "Permission "],
[LogCategory.GENERAL, "General "],
[LogCategory.NETWORKING, "Network "]
]);
function logDirect(type: LogType, message: string, ...optionalParams: any[]) {
switch (type) {
case LogType.TRACE:
case LogType.DEBUG:
console.debug(message, ...optionalParams);
break;
case LogType.INFO:
console.log(message, ...optionalParams);
break;
case LogType.WARNING:
console.warn(message, ...optionalParams);
break;
case LogType.ERROR:
console.error(message, ...optionalParams);
break;
}
//console.log("This is %cMy stylish message", "color: yellow; font-style: italic; background-color: blue;padding: 2px");
}
export function log(type: LogType, category: LogCategory, message: string, ...optionalParams: any[]) {
optionalParams.unshift(category_mapping.get(category));
message = "[%s] " + message;
logDirect(type, message, ...optionalParams);
}
export function trace(category: LogCategory, message: string, ...optionalParams: any[]) {
log(LogType.TRACE, category, message, ...optionalParams);
}
export function debug(category: LogCategory, message: string, ...optionalParams: any[]) {
log(LogType.DEBUG, category, message, ...optionalParams);
}
export function info(category: LogCategory, message: string, ...optionalParams: any[]) {
log(LogType.INFO, category, message, ...optionalParams);
}
export function warn(category: LogCategory, message: string, ...optionalParams: any[]) {
log(LogType.WARNING, category, message, ...optionalParams);
}
export function error(category: LogCategory, message: string, ...optionalParams: any[]) {
log(LogType.ERROR, category, message, ...optionalParams);
}
export function group(level: LogType, category: LogCategory, name: string, ...optionalParams: any[]) : Group {
name = "[%s] " + name;
optionalParams.unshift(category_mapping.get(category));
return new Group(level, category, name, optionalParams);
}
export class Group {
readonly level: LogType;
readonly category: LogCategory;
owner: Group = undefined;
private readonly name: string;
private readonly optionalParams: any[][];
private _collapsed: boolean = true;
private initialized = false;
constructor(level: LogType, category: LogCategory, name: string, optionalParams: any[][], owner: Group = undefined) {
this.level = level;
this.category = category;
this.name = name;
this.optionalParams = optionalParams;
}
group(level: LogType, name: string, ...optionalParams: any[]) : Group {
return new Group(level, this.category, name, optionalParams, this);
}
collapsed(flag: boolean = true) : this {
this._collapsed = flag;
return this;
}
log(message: string, ...optionalParams: any[]) : this {
if(!this.initialized) {
if(this._collapsed && console.groupCollapsed)
console.groupCollapsed(this.name, ...this.optionalParams);
else
console.group(this.name, ...this.optionalParams);
this.initialized = true;
}
logDirect(this.level, message, ...optionalParams);
return this;
}
end() {
if(this.initialized)
console.groupEnd();
}
}
}

View File

@ -3,33 +3,46 @@
/// <reference path="Identity.ts" />
/// <reference path="utils/modal.ts" />
/// <reference path="ui/modal/ModalConnect.ts" />
/// <reference path="ui/modal/ModalCreateChannel.ts" />
/// <reference path="codec/CodecWrapper.ts" />
/// <reference path="settings.ts" />
/// <reference path="log.ts" />
let settings;
let globalClient;
let chat;
let forumIdentity;
function invokeMain() {
//localhost:63343/Web-Client/index.php?disableUnloadDialog=1&default_connect_type=forum&default_connect_url=localhost
AudioController.initializeAudioController();
if (!TSIdentityHelper.setup()) {
console.error("Could not setup the TeamSpeak identity parser!");
return;
}
settings = new Settings();
globalClient = new TSClient();
/** Setup the XF forum identity **/
if (globalClient.settings.static("forum_user_data")) {
forumIdentity = new TeaForumIdentity(globalClient.settings.static("forum_user_data"), globalClient.settings.static("forum_user_sign"));
if (settings.static("forum_user_data")) {
forumIdentity = new TeaForumIdentity(settings.static("forum_user_data"), settings.static("forum_user_sign"));
}
chat = new ChatBox($("#chat"));
globalClient.setup();
//globalClient.startConnection("localhost:19974"); //TODO remove only for testing
if (!settings.static(Settings.KEY_DISABLE_UNLOAD_DIALOG, false)) {
window.addEventListener("beforeunload", function (event) {
if (globalClient.serverConnection && globalClient.serverConnection.connected)
event.returnValue = "Are you really sure?<br>You're still connected!";
//event.preventDefault();
});
}
//Modals.spawnConnectModal();
//Modals.spawnSettingsModal();
window.addEventListener("beforeunload", function (event) {
if (globalClient.serverConnection && globalClient.serverConnection.connected)
event.returnValue = "Are you really sure?<br>You're still connected!";
//event.preventDefault();
});
//console.log("XF: " + globalClient.settings.static("forum_user_data"));
//console.log("XF: " + globalClient.settings.static("forum_user_sign"));
//Modals.createChannelModal(undefined);
if (settings.static("default_connect_url")) {
if (settings.static("default_connect_type", "forum")) {
globalClient.startConnection(settings.static("default_connect_url"), forumIdentity);
}
else
Modals.spawnConnectModal(settings.static("default_connect_url"));
}
}
//# sourceMappingURL=main.js.map

View File

@ -1 +1 @@
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,kCAAkC;AAClC,oCAAoC;AACpC,uCAAuC;AACvC,iDAAiD;AACjD,8CAA8C;AAC9C,oCAAoC;AAEpC,IAAI,YAAsB,CAAC;AAC3B,IAAI,IAAa,CAAC;AAElB,IAAI,aAA+B,CAAC;AAEpC;IACI,eAAe,CAAC,yBAAyB,EAAE,CAAC;IAC5C,EAAE,CAAA,CAAC,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAAC,MAAM,CAAC;IAAC,CAAC;IAE1G,YAAY,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC9B,mCAAmC;IACnC,EAAE,CAAA,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACjD,aAAa,GAAG,IAAI,gBAAgB,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC3I,CAAC;IAED,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAC;IACrB,iFAAiF;IAEjF,6BAA6B;IAC7B,8BAA8B;IAE9B,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,UAAU,KAAK;QACnD,EAAE,CAAA,CAAC,YAAY,CAAC,gBAAgB,IAAI,YAAY,CAAC,gBAAgB,CAAC,SAAS,CAAC;YACxE,KAAK,CAAC,WAAW,GAAG,iDAAiD,CAAC;QAC1E,yBAAyB;IAC7B,CAAC,CAAC,CAAC;IAGH,wEAAwE;IACxE,wEAAwE;AAC5E,CAAC"}
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,kCAAkC;AAClC,oCAAoC;AACpC,uCAAuC;AACvC,iDAAiD;AACjD,uDAAuD;AACvD,8CAA8C;AAC9C,oCAAoC;AACpC,+BAA+B;AAE/B,IAAI,QAAkB,CAAC;AACvB,IAAI,YAAsB,CAAC;AAC3B,IAAI,IAAa,CAAC;AAElB,IAAI,aAA+B,CAAC;AAGpC;IACI,qHAAqH;IACrH,eAAe,CAAC,yBAAyB,EAAE,CAAC;IAC5C,EAAE,CAAA,CAAC,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAAC,MAAM,CAAC;IAAC,CAAC;IAE1G,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC1B,YAAY,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC9B,mCAAmC;IACnC,EAAE,CAAA,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACpC,aAAa,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACjH,CAAC;IAED,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAC;IACrB,iFAAiF;IAGjF,EAAE,CAAA,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,UAAU,KAAK;YACnD,EAAE,CAAA,CAAC,YAAY,CAAC,gBAAgB,IAAI,YAAY,CAAC,gBAAgB,CAAC,SAAS,CAAC;gBACxE,KAAK,CAAC,WAAW,GAAG,iDAAiD,CAAC;YAC1E,yBAAyB;QAC7B,CAAC,CAAC,CAAC;IACP,CAAC;IACD,6BAA6B;IAC7B,8BAA8B;IAC9B,uCAAuC;IAEvC,EAAE,CAAA,CAAC,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxC,EAAE,CAAA,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;YAClD,YAAY,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,aAAa,CAAC,CAAC;QACxF,CAAC;QAAC,IAAI;YACF,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACzE,CAAC;AACL,CAAC"}

View File

@ -3,38 +3,50 @@
/// <reference path="Identity.ts" />
/// <reference path="utils/modal.ts" />
/// <reference path="ui/modal/ModalConnect.ts" />
/// <reference path="ui/modal/ModalCreateChannel.ts" />
/// <reference path="codec/CodecWrapper.ts" />
/// <reference path="settings.ts" />
/// <reference path="log.ts" />
let settings: Settings;
let globalClient: TSClient;
let chat: ChatBox;
let forumIdentity: TeaForumIdentity;
function invokeMain() {
//localhost:63343/Web-Client/index.php?disableUnloadDialog=1&default_connect_type=forum&default_connect_url=localhost
AudioController.initializeAudioController();
if(!TSIdentityHelper.setup()) { console.error("Could not setup the TeamSpeak identity parser!"); return; }
settings = new Settings();
globalClient = new TSClient();
/** Setup the XF forum identity **/
if(globalClient.settings.static("forum_user_data")) {
forumIdentity = new TeaForumIdentity(globalClient.settings.static("forum_user_data"), globalClient.settings.static("forum_user_sign"));
if(settings.static("forum_user_data")) {
forumIdentity = new TeaForumIdentity(settings.static("forum_user_data"), settings.static("forum_user_sign"));
}
chat = new ChatBox($("#chat"));
globalClient.setup();
//globalClient.startConnection("localhost:19974"); //TODO remove only for testing
if(!settings.static(Settings.KEY_DISABLE_UNLOAD_DIALOG, false)) {
window.addEventListener("beforeunload", function (event) {
if(globalClient.serverConnection && globalClient.serverConnection.connected)
event.returnValue = "Are you really sure?<br>You're still connected!";
//event.preventDefault();
});
}
//Modals.spawnConnectModal();
//Modals.spawnSettingsModal();
//Modals.createChannelModal(undefined);
window.addEventListener("beforeunload", function (event) {
if(globalClient.serverConnection && globalClient.serverConnection.connected)
event.returnValue = "Are you really sure?<br>You're still connected!";
//event.preventDefault();
});
//console.log("XF: " + globalClient.settings.static("forum_user_data"));
//console.log("XF: " + globalClient.settings.static("forum_user_sign"));
if(settings.static("default_connect_url")) {
if(settings.static("default_connect_type", "forum")) {
globalClient.startConnection(settings.static("default_connect_url"), forumIdentity);
} else
Modals.spawnConnectModal(settings.static("default_connect_url"));
}
}

View File

@ -294,9 +294,12 @@ class GrantedPermission {
this.value = value;
}
granted(requiredValue, required = true) {
let result = false;
if (this.value == -2)
return !required;
return this.value == -1 || this.value > requiredValue;
result = !required;
result = this.value == -1 || this.value >= requiredValue;
log.trace(LogCategory.PERMISSIONS, "Test needed required: %o | %i | %o => " + result, this, requiredValue, required);
return result;
}
hasValue() {
return this.value != -2;
@ -312,41 +315,78 @@ class PermissionManager {
constructor(client) {
this.permissionList = [];
this.neededPermissions = [];
this.initializedListener = [];
this.handle = client;
this.handle.serverConnection.commandHandler["notifyclientneededpermissions"] = this.onNeededPermissions.bind(this);
this.handle.serverConnection.commandHandler["notifypermissionlist"] = this.onPermissionList.bind(this);
}
initialized() {
return this.permissionList.length > 0;
}
requestPermissionList() {
this.handle.serverConnection.sendCommand("permissionlist");
}
onPermissionList(json) {
this.permissionList = [];
for (let e in json) {
let group = log.group(log.LogType.TRACE, LogCategory.PERMISSIONS, "Permission mapping");
for (let e of json) {
if (e["group_id_end"])
continue; //Skip all group ids (may use later?)
let perm = new PermissionInfo();
perm.name = e["permname"];
perm.id = e["permid"];
perm.id = parseInt(e["permid"]);
perm.description = e["permdesc"];
group.log("%i <> %s -> %s", perm.id, perm.name, perm.description);
this.permissionList.push(perm);
}
console.log("Got " + this.permissionList.length + " permissions");
group.end();
log.info(LogCategory.PERMISSIONS, "Got %i permissions", this.permissionList.length);
if (this._cacheNeededPermissions)
this.onNeededPermissions(this._cacheNeededPermissions);
for (let listener of this.initializedListener)
listener(true);
}
onNeededPermissions(json) {
let copy = this.neededPermissions;
console.debug("[Permissions] Got " + json.length + " needed permissions.");
for (let e in json) {
for (let p of copy)
if (p.type.id == e["permid"]) {
copy.remove(p);
p.value = e["permvalue"];
for (let listener of p.changeListener)
listener(p.value);
}
if (this.permissionList.length == 0) {
log.warn(LogCategory.PERMISSIONS, "Got needed permissions but don't have a permission list!");
this._cacheNeededPermissions = json;
return;
}
console.debug("[Permissions] Dropping " + copy.length + " needed permissions");
this._cacheNeededPermissions = undefined;
let copy = this.neededPermissions.slice();
let addcount = 0;
let group = log.group(log.LogType.TRACE, LogCategory.PERMISSIONS, "Got " + json.length + " needed permissions.");
for (let e of json) {
let entry = undefined;
for (let p of copy) {
if (p.type.id == e["permid"]) {
entry = p;
copy.remove(p);
break;
}
}
if (!entry) {
let info = this.resolveInfo(e["permid"]);
if (info) {
entry = new NeededGrantedPermission(info, -2);
this.neededPermissions.push(entry);
}
else {
log.warn(LogCategory.PERMISSIONS, "Could not resolve perm for id %s (%o|%o)", e["permid"], e, info);
continue;
}
addcount++;
}
if (entry.value == parseInt(e["permvalue"]))
continue;
entry.value = parseInt(e["permvalue"]);
group.log("Update needed permission " + entry.type.name + " to " + entry.value);
for (let listener of entry.changeListener)
listener(entry.value);
}
group.end();
log.debug(LogCategory.PERMISSIONS, "Dropping " + copy.length + " needed permissions and added " + addcount + " permissions.");
for (let e of copy) {
this.neededPermissions.remove(e);
e.value = -2;
for (let listener of e.changeListener)
listener(e.value);
@ -362,7 +402,15 @@ class PermissionManager {
for (let perm of this.neededPermissions)
if (perm.type.id == key || perm.type.name == key || perm.type == key)
return perm;
return new GrantedPermission(key instanceof PermissionInfo ? key : this.resolveInfo(key), -2);
log.debug(LogCategory.PERMISSIONS, "Could not resolve grant permission %o. Creating a new one.", key);
let info = key instanceof PermissionInfo ? key : this.resolveInfo(key);
if (!info) {
log.warn(LogCategory.PERMISSIONS, "Requested needed permission with invalid key! (%o)", key);
return undefined;
}
let result = new NeededGrantedPermission(info, -2);
this.neededPermissions.push(result);
return result;
}
}
//# sourceMappingURL=PermissionManager.js.map

File diff suppressed because one or more lines are too long

View File

@ -303,9 +303,12 @@ class GrantedPermission {
}
granted(requiredValue: number, required: boolean = true) : boolean {
let result = false;
if(this.value == -2)
return !required;
return this.value == -1 || this.value > requiredValue;
result = !required;
result = this.value == -1 || this.value >= requiredValue;
log.trace(LogCategory.PERMISSIONS, "Test needed required: %o | %i | %o => " + result , this, requiredValue, required);
return result;
}
hasValue() : boolean {
@ -327,6 +330,9 @@ class PermissionManager {
permissionList: PermissionInfo[] = [];
neededPermissions: NeededGrantedPermission[] = [];
initializedListener: ((initialized: boolean) => void)[] = [];
private _cacheNeededPermissions: any;
constructor(client: TSClient) {
this.handle = client;
@ -334,44 +340,81 @@ class PermissionManager {
this.handle.serverConnection.commandHandler["notifypermissionlist"] = this.onPermissionList.bind(this);
}
initialized() : boolean {
return this.permissionList.length > 0;
}
public requestPermissionList() {
this.handle.serverConnection.sendCommand("permissionlist");
}
private onPermissionList(json) {
this.permissionList = [];
for(let e in json) {
let group = log.group(log.LogType.TRACE, LogCategory.PERMISSIONS, "Permission mapping");
for(let e of json) {
if(e["group_id_end"]) continue; //Skip all group ids (may use later?)
let perm = new PermissionInfo();
perm.name = e["permname"];
perm.id = e["permid"];
perm.id = parseInt(e["permid"]);
perm.description = e["permdesc"];
group.log("%i <> %s -> %s", perm.id, perm.name, perm.description);
this.permissionList.push(perm);
}
group.end();
console.log("Got " + this.permissionList.length + " permissions");
log.info(LogCategory.PERMISSIONS, "Got %i permissions", this.permissionList.length);
if(this._cacheNeededPermissions)
this.onNeededPermissions(this._cacheNeededPermissions);
for(let listener of this.initializedListener)
listener(true);
}
private onNeededPermissions(json) {
let copy = this.neededPermissions;
console.debug("[Permissions] Got " + json.length + " needed permissions.");
for(let e in json) {
for(let p of copy)
if(p.type.id == e["permid"]) {
copy.remove(p);
p.value = e["permvalue"];
for(let listener of p.changeListener)
listener(p.value);
}
if(this.permissionList.length == 0) {
log.warn(LogCategory.PERMISSIONS, "Got needed permissions but don't have a permission list!");
this._cacheNeededPermissions = json;
return;
}
this._cacheNeededPermissions = undefined;
console.debug("[Permissions] Dropping " + copy.length + " needed permissions");
let copy = this.neededPermissions.slice();
let addcount = 0;
let group = log.group(log.LogType.TRACE, LogCategory.PERMISSIONS, "Got " + json.length + " needed permissions.");
for(let e of json) {
let entry: NeededGrantedPermission = undefined;
for(let p of copy) {
if(p.type.id == e["permid"]) {
entry = p;
copy.remove(p);
break;
}
}
if(!entry) {
let info = this.resolveInfo(e["permid"]);
if(info) {
entry = new NeededGrantedPermission(info, -2);
this.neededPermissions.push(entry);
} else {
log.warn(LogCategory.PERMISSIONS, "Could not resolve perm for id %s (%o|%o)", e["permid"], e, info);
continue;
}
addcount++;
}
if(entry.value == parseInt(e["permvalue"])) continue;
entry.value = parseInt(e["permvalue"]);
group.log("Update needed permission " + entry.type.name + " to " + entry.value);
for(let listener of entry.changeListener)
listener(entry.value);
}
group.end();
log.debug(LogCategory.PERMISSIONS, "Dropping " + copy.length + " needed permissions and added " + addcount + " permissions.");
for(let e of copy) {
this.neededPermissions.remove(e);
e.value = -2;
for(let listener of e.changeListener)
listener(e.value);
}
@ -388,6 +431,15 @@ class PermissionManager {
for(let perm of this.neededPermissions)
if(perm.type.id == key || perm.type.name == key || perm.type == key)
return perm;
return new GrantedPermission(key instanceof PermissionInfo ? key : this.resolveInfo(key), -2);
log.debug(LogCategory.PERMISSIONS, "Could not resolve grant permission %o. Creating a new one.", key);
let info = key instanceof PermissionInfo ? key : this.resolveInfo(key);
if(!info) {
log.warn(LogCategory.PERMISSIONS, "Requested needed permission with invalid key! (%o)", key);
return undefined;
}
let result = new NeededGrantedPermission(info, -2);
this.neededPermissions.push(result);
return result;
}
}

View File

@ -1 +1 @@
{"version":3,"file":"proto.js","sourceRoot":"","sources":["proto.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"proto.js","sourceRoot":"","sources":["proto.ts"],"names":[],"mappings":"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"}

View File

@ -13,8 +13,6 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
spawn<K extends keyof HTMLElementTagNameMap>(tagName: K): JQuery<HTMLElementTagNameMap[K]>;
}
interface String {
format(...fmt): string;
format(arguments: string[]): string;
@ -38,6 +36,7 @@ if (!Array.prototype.pop_front) {
}
}
if (!Array.prototype.last){
Array.prototype.last = function(){
if(this.length == 0) return undefined;

View File

@ -1,16 +1,17 @@
/// <reference path="client.ts" />
class X_Properties extends HTMLElement {
if (typeof (customElements) !== "undefined") {
class X_Properties extends HTMLElement {
}
class X_Property extends HTMLElement {
}
customElements.define('x-properties', X_Properties, { extends: 'div' });
customElements.define('x-property', X_Property, { extends: 'div' });
}
class X_Property extends HTMLElement {
}
customElements.define('x-properties', X_Properties, { extends: 'div' });
customElements.define('x-property', X_Property, { extends: 'div' });
class Settings {
constructor(handle) {
constructor() {
this.cacheGlobal = {};
this.cacheServer = {};
this.updated = false;
this.handle = handle;
this._staticPropsTag = $("#properties");
this.cacheGlobal = JSON.parse(localStorage.getItem("settings.global"));
if (!this.cacheGlobal)
@ -20,20 +21,56 @@ class Settings {
if (_this.updated)
_this.save();
}, 5 * 1000);
this.initializeStatic();
}
initializeStatic() {
location.search.substr(1).split("&").forEach(part => {
let item = part.split("=");
$.spawn("div")
.attr("key", item[0])
.attr("value", item[1])
.appendTo(this._staticPropsTag);
});
}
static transformStO(input, _default) {
if (typeof _default === "string")
return input;
else if (typeof _default === "number")
return parseInt(input);
else if (typeof _default === "boolean")
return (input == "1" || input == "true");
else if (typeof _default == "undefined")
return input;
return JSON.parse(input);
}
static transformOtS(input) {
if (typeof input === "string")
return input;
else if (typeof input === "number")
return input.toString();
else if (typeof input === "boolean")
return input ? "1" : "0";
else if (typeof input == "undefined")
return undefined;
return JSON.stringify(input);
}
global(key, _default) {
let result = this.cacheGlobal[key];
return result ? result : _default;
return Settings.transformStO(result, _default);
}
server(key, _default) {
let result = this.cacheServer[key];
return result ? result : _default;
return Settings.transformStO(result, _default);
}
static(key, _default) {
let result = this._staticPropsTag.find("[key='" + key + "']");
return Settings.transformStO(result.length > 0 ? decodeURIComponent(result.attr("value")) : undefined, _default);
}
changeGlobal(key, value) {
if (this.cacheGlobal[key] == value)
return;
this.updated = true;
this.cacheGlobal[key] = value;
this.cacheGlobal[key] = Settings.transformOtS(value);
if (Settings.UPDATE_DIRECT)
this.save();
}
@ -41,42 +78,41 @@ class Settings {
if (this.cacheServer[key] == value)
return;
this.updated = true;
this.cacheServer[key] = value;
this.cacheServer[key] = Settings.transformOtS(value);
if (Settings.UPDATE_DIRECT)
this.save();
}
loadServer() {
if (!this.handle.channelTree.server) {
setServer(server) {
if (this.currentServer) {
this.save();
this.cacheServer = {};
console.warn("[Settings] tried to load settings for unknown server");
return;
this.currentServer = undefined;
}
this.currentServer = server;
if (this.currentServer) {
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
if (!this.cacheServer)
this.cacheServer = {};
}
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
if (!this.cacheServer)
this.cacheServer = {};
}
save() {
this.updated = false;
if (this.handle.channelTree.server) {
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
if (this.currentServer) {
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
let server = JSON.stringify(this.cacheServer);
localStorage.setItem("settings.server_" + serverId, server);
}
let global = JSON.stringify(this.cacheGlobal);
localStorage.setItem("settings.global", global);
}
static(key, _default = undefined) {
let result = this._staticPropsTag.find("[key='" + key + "']");
if (result.length == 0)
return _default;
return decodeURIComponent(result.attr("value"));
}
deleteStatic(key) {
let result = this._staticPropsTag.find("[key='" + key + "']");
if (result.length != 0)
result.detach();
}
}
Settings.KEY_DISABLE_CONTEXT_MENU = "disableContextMenu";
Settings.KEY_DISABLE_UNLOAD_DIALOG = "disableUnloadDialog";
Settings.UPDATE_DIRECT = true;
//# sourceMappingURL=settings.js.map

View File

@ -1 +1 @@
{"version":3,"file":"settings.js","sourceRoot":"","sources":["settings.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC,kBAAmB,SAAQ,WAAW;CAAG;AACzC,gBAAiB,SAAQ,WAAW;CAAG;AAEvC,cAAc,CAAC,MAAM,CAAC,cAAc,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AACxE,cAAc,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AAEpE;IAUI,YAAY,MAAgB;QANpB,gBAAW,GAAG,EAAE,CAAC;QACjB,gBAAW,GAAG,EAAE,CAAC;QAEjB,YAAO,GAAY,KAAK,CAAC;QAI7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;QAExC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACvE,EAAE,CAAA,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;YAAC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YAC/B,EAAE,CAAA,CAAC,KAAK,CAAC,OAAO,CAAC;gBACb,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,CAAE,GAAW,EAAE,QAAiB;QAClC,IAAI,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,MAAM,CAAE,GAAW,EAAE,QAAiB;QAClC,IAAI,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,KAAc;QACpC,EAAE,CAAA,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC;YAAC,MAAM,CAAC;QAE1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAE9B,EAAE,CAAA,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtB,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,KAAc;QACpC,EAAE,CAAA,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC;YAAC,MAAM,CAAC;QAE1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAE9B,EAAE,CAAA,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtB,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,UAAU;QACN,EAAE,CAAA,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;YACrE,MAAM,CAAC;QACX,CAAC;QACD,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,+BAA+B,CAAC;QACzF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,kBAAkB,GAAG,QAAQ,CAAC,CAAC,CAAC;QACnF,EAAE,CAAA,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI;QACA,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QAErB,EAAE,CAAA,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;YAChC,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,+BAA+B,CAAC;YACzF,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9C,YAAY,CAAC,OAAO,CAAC,kBAAkB,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAE,GAAW,EAAE,WAAmB,SAAS;QAC7C,IAAI,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAC9D,EAAE,CAAA,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC;QACvC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,YAAY,CAAC,GAAW;QACpB,IAAI,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAC9D,EAAE,CAAA,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IAC3C,CAAC;;AApFuB,sBAAa,GAAY,IAAI,CAAC"}
{"version":3,"file":"settings.js","sourceRoot":"","sources":["settings.ts"],"names":[],"mappings":"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"}

View File

@ -1,23 +1,26 @@
/// <reference path="client.ts" />
class X_Properties extends HTMLElement {}
class X_Property extends HTMLElement {}
if(typeof(customElements) !== "undefined") {
class X_Properties extends HTMLElement {}
class X_Property extends HTMLElement {}
customElements.define('x-properties', X_Properties, { extends: 'div' });
customElements.define('x-property', X_Property, { extends: 'div' });
customElements.define('x-properties', X_Properties, { extends: 'div' });
customElements.define('x-property', X_Property, { extends: 'div' });
}
class Settings {
handle: TSClient;
static readonly KEY_DISABLE_CONTEXT_MENU = "disableContextMenu";
static readonly KEY_DISABLE_UNLOAD_DIALOG = "disableUnloadDialog";
private static readonly UPDATE_DIRECT: boolean = true;
private cacheGlobal = {};
private cacheServer = {};
private currentServer: ServerEntry;
private saveWorker: NodeJS.Timer;
private updated: boolean = false;
private _staticPropsTag: JQuery;
constructor(handle: TSClient) {
this.handle = handle;
constructor() {
this._staticPropsTag = $("#properties");
this.cacheGlobal = JSON.parse(localStorage.getItem("settings.global"));
@ -27,55 +30,93 @@ class Settings {
if(_this.updated)
_this.save();
}, 5 * 1000);
this.initializeStatic();
}
global?(key: string, _default?: string) : string {
private initializeStatic() {
location.search.substr(1).split("&").forEach(part => {
let item = part.split("=");
$.spawn("div")
.attr("key", item[0])
.attr("value", item[1])
.appendTo(this._staticPropsTag);
});
}
private static transformStO?<T>(input: string, _default?: T) : T {
if (typeof _default === "string") return input as any;
else if (typeof _default === "number") return parseInt(input) as any;
else if (typeof _default === "boolean") return (input == "1" || input == "true") as any;
else if (typeof _default == "undefined") return input as any;
return JSON.parse(input) as any;
}
private static transformOtS?<T>(input: T) : string {
if (typeof input === "string") return input as string;
else if (typeof input === "number") return input.toString();
else if (typeof input === "boolean") return input ? "1" : "0";
else if (typeof input == "undefined") return undefined;
return JSON.stringify(input);
}
global?<T>(key: string, _default?: T) : T {
let result = this.cacheGlobal[key];
return result ? result : _default;
return Settings.transformStO(result, _default);
}
server?(key: string, _default?: string) : string {
server?<T>(key: string, _default?: T) : T {
let result = this.cacheServer[key];
return result ? result : _default;
return Settings.transformStO(result, _default);
}
changeGlobal(key: string, value?: string){
static?<T>(key: string, _default?: T) : T {
let result = this._staticPropsTag.find("[key='" + key + "']");
return Settings.transformStO(result.length > 0 ? decodeURIComponent(result.attr("value")) : undefined, _default);
}
changeGlobal<T>(key: string, value?: T){
if(this.cacheGlobal[key] == value) return;
this.updated = true;
this.cacheGlobal[key] = value;
this.cacheGlobal[key] = Settings.transformOtS(value);
if(Settings.UPDATE_DIRECT)
this.save();
}
changeServer(key: string, value?: string) {
changeServer<T>(key: string, value?: T) {
if(this.cacheServer[key] == value) return;
this.updated = true;
this.cacheServer[key] = value;
this.cacheServer[key] = Settings.transformOtS(value);
if(Settings.UPDATE_DIRECT)
this.save();
}
loadServer() {
if(!this.handle.channelTree.server) {
setServer(server: ServerEntry) {
if(this.currentServer) {
this.save();
this.cacheServer = {};
console.warn("[Settings] tried to load settings for unknown server");
return;
this.currentServer = undefined;
}
this.currentServer = server;
if(this.currentServer) {
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
if(!this.cacheServer)
this.cacheServer = {};
}
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
if(!this.cacheServer)
this.cacheServer = {};
}
save() {
this.updated = false;
if(this.handle.channelTree.server) {
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
if(this.currentServer) {
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
let server = JSON.stringify(this.cacheServer);
localStorage.setItem("settings.server_" + serverId, server);
}
@ -84,12 +125,6 @@ class Settings {
localStorage.setItem("settings.global", global);
}
static?(key: string, _default: string = undefined) : string {
let result = this._staticPropsTag.find("[key='" + key + "']");
if(result.length == 0) return _default;
return decodeURIComponent(result.attr("value"));
}
deleteStatic(key: string) {
let result = this._staticPropsTag.find("[key='" + key + "']");
if(result.length != 0) result.detach();

View File

@ -23,8 +23,8 @@ class ControlBar {
this.htmlTag.find(".btn_mute_output").click(this.onOutputMute.bind(this));
this.htmlTag.find(".btn_open_settings").click(this.onOpenSettings.bind(this));
//Need an initialise
this.muteInput = this.handle.settings.global("mute_input") == "1";
this.muteOutput = this.handle.settings.global("mute_output") == "1";
this.muteInput = settings.global("mute_input") == "1";
this.muteOutput = settings.global("mute_output") == "1";
}
onAway() {
this.away = !this._away;
@ -52,9 +52,9 @@ class ControlBar {
}
if (this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_input_muted: this._muteInput ? 1 : 0
client_input_muted: this._muteInput
});
this.handle.settings.changeGlobal("mute_input", this._muteInput ? "1" : "0");
settings.changeGlobal("mute_input", this._muteInput);
this.updateMicrophoneRecordState();
}
get muteOutput() { return this._muteOutput; }
@ -75,9 +75,9 @@ class ControlBar {
}
if (this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_output_muted: this._muteOutput ? 1 : 0
client_output_muted: this._muteOutput
});
this.handle.settings.changeGlobal("mute_output", this._muteOutput ? "1" : "0");
settings.changeGlobal("mute_output", this._muteOutput);
this.updateMicrophoneRecordState();
}
set away(value) {
@ -102,7 +102,7 @@ class ControlBar {
}
if (this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_away: this._away ? 1 : 0,
client_away: this._away,
client_away_message: this._awayMessage
});
this.updateMicrophoneRecordState();
@ -114,9 +114,9 @@ class ControlBar {
updateProperties() {
if (this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_input_muted: this._muteInput ? 1 : 0,
client_output_muted: this._muteOutput ? 1 : 0,
client_away: this._away ? 1 : 0,
client_input_muted: this._muteInput,
client_output_muted: this._muteOutput,
client_away: this._away,
client_away_message: this._awayMessage,
});
}
@ -124,7 +124,7 @@ class ControlBar {
Modals.spawnSettingsModal();
}
onConnect() {
Modals.spawnConnectModal(this.handle.settings.static("connect_default_host"));
Modals.spawnConnectModal(settings.static("connect_default_host", "ts.TeaSpeak.de"));
}
}
//# sourceMappingURL=ControlBar.js.map

File diff suppressed because one or more lines are too long

View File

@ -34,8 +34,8 @@ class ControlBar {
//Need an initialise
this.muteInput = this.handle.settings.global("mute_input") == "1";
this.muteOutput = this.handle.settings.global("mute_output") == "1";
this.muteInput = settings.global("mute_input") == "1";
this.muteOutput = settings.global("mute_output") == "1";
}
@ -69,9 +69,9 @@ class ControlBar {
if(this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_input_muted: this._muteInput ? 1 : 0
client_input_muted: this._muteInput
});
this.handle.settings.changeGlobal("mute_input", this._muteInput ? "1" : "0");
settings.changeGlobal("mute_input", this._muteInput);
this.updateMicrophoneRecordState();
}
@ -94,9 +94,9 @@ class ControlBar {
if(this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_output_muted: this._muteOutput ? 1 : 0
client_output_muted: this._muteOutput
});
this.handle.settings.changeGlobal("mute_output", this._muteOutput ? "1" : "0");
settings.changeGlobal("mute_output", this._muteOutput);
this.updateMicrophoneRecordState();
}
@ -121,7 +121,7 @@ class ControlBar {
if(this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_away: this._away ? 1 : 0,
client_away: this._away,
client_away_message: this._awayMessage
});
this.updateMicrophoneRecordState();
@ -135,9 +135,9 @@ class ControlBar {
updateProperties() {
if(this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_input_muted: this._muteInput ? 1 : 0,
client_output_muted: this._muteOutput ? 1 : 0,
client_away: this._away ? 1 : 0,
client_input_muted: this._muteInput,
client_output_muted: this._muteOutput,
client_away: this._away,
client_away_message: this._awayMessage,
});
}
@ -147,6 +147,6 @@ class ControlBar {
}
private onConnect() {
Modals.spawnConnectModal(this.handle.settings.static("connect_default_host"));
Modals.spawnConnectModal(settings.static("connect_default_host", "ts.TeaSpeak.de"));
}
}

View File

@ -1,4 +1,5 @@
/// <reference path="view.ts" />
/// <reference path="../utils/helpers.ts" />
var ChannelType;
(function (ChannelType) {
ChannelType[ChannelType["PERMANENT"] = 0] = "PERMANENT";
@ -13,29 +14,45 @@ var ChannelType;
}
ChannelType.normalize = normalize;
})(ChannelType || (ChannelType = {}));
class ChannelProperties {
constructor() {
this.channel_order = 0;
this.channel_name = "";
this.channel_topic = "";
this.channel_password = "";
this.channel_description = "";
this.channel_codec = 4;
this.channel_codec_quality = 0;
this.channel_codec_is_unencrypted = false;
this.channel_maxclients = -1;
this.channel_maxfamilyclients = -1;
this.channel_needed_talk_power = 1;
this.channel_flag_permanent = false;
this.channel_flag_semi_permanent = false;
this.channel_flag_default = false;
this.channel_flag_password = false;
this.channel_flag_maxclients_unlimited = false;
this.channel_flag_maxfamilyclients_inherited = false;
this.channel_flag_maxfamilyclients_unlimited = false;
}
}
class ChannelEntry {
constructor(channelId, channelName, parent = null, prevChannel = null) {
this.properties = {
channel_order: 0,
channel_name: "undefined",
channel_flag_permanent: 0,
channel_flag_semi_permanent: 0,
channel_flag_default: 0,
channel_flag_password: 0
};
this.properties = {};
this.properties = new ChannelProperties();
this.properties = new ChannelProperties();
this.channelId = channelId;
this._rawChannelName = channelName;
this._formatedChannelName = channelName;
this.parent = parent;
this.prevChannel = prevChannel;
this.channelTree = null;
this.__updateChannelPropertiesFromName();
this.initializeTag();
this.__updateChannelName();
}
channelName() {
return this.properties["channel_name"];
return this.properties.channel_name;
}
rawChannelName() {
return this._rawChannelName;
formatedChannelName() {
return this._formatedChannelName ? this._formatedChannelName : this.properties.channel_name;
}
parentChannel() { return this.parent; }
hasParent() { return this.parent != null; }
@ -83,37 +100,73 @@ class ChannelEntry {
});
return result;
}
get htmlTag() {
if (this._htmlTag)
return this._htmlTag;
let tag = $.spawn("div");
tag.attr("id", "channel_" + this.getChannelId());
tag.addClass("channel");
tag.append("<div class=\"icon_empty\"></div>");
let channelTag = $("<div></div>");
channelTag.addClass("channelLine");
channelTag.addClass(this._channelAlign); //For left
let channelType = $("<div/>");
channelType.addClass("channel_only_normal channel_type");
channelType.addClass("icon");
channelType.addClass("client-channel_green_subscribed");
channelTag.append(channelType);
channelTag.append("<a class='channel_name'>" + this.channelName() + "</a>");
let channelIcon = $("<span class='channel_only_normal'/>");
channelTag.append(channelIcon);
tag.append("<div style='position: absolute; width: calc(100% - 16px); margin: 0px'><div class=\"siblings\"></div></div>");
tag.append("<div style='position: absolute; width: calc(100% - 16px); margin: 0px'><div class=\"clients\"></div></div>");
tag.append(channelTag);
return this._htmlTag = tag;
initializeTag() {
let rootTag = $.spawn("div");
rootTag.attr("id", "channel_" + this.getChannelId());
rootTag.addClass("channel");
//rootTag.append($.spawn("div").addClass("icon_empty"));
//Tag channel
this._tag_channel = $.spawn("div");
this._tag_channel.addClass("channelLine");
this._tag_channel.addClass(this._channelAlign); //For left
let channelType = $.spawn("div");
channelType.addClass("channel_only_normal channel_type icon client-channel_green_subscribed");
this._tag_channel.append(channelType);
this._tag_channel.append($.spawn("div").addClass("channel_name_container").append($.spawn("a").addClass("channel_name").text(this.channelName())));
//Icons
let iconTag = $.spawn("span").addClass("icons");
iconTag.appendTo(this._tag_channel);
//Default icon (4)
iconTag.append($.spawn("div").addClass("channel_only_normal").append($.spawn("div").addClass("icon_entry icon_default icon client-channel_default").attr("title", "Default channel")));
//Password icon (3)
iconTag.append($.spawn("div").addClass("channel_only_normal").append($.spawn("div").addClass("icon_entry icon_password icon client-register").attr("title", "The channel is password protected")));
//Music icon (2)
iconTag.append($.spawn("div").addClass("channel_only_normal").append($.spawn("div").addClass("icon_entry icon_music icon client-music").attr("title", "Music quality")));
//Channel Icon (1)
iconTag.append($.spawn("div").addClass("channel_only_normal").addClass("icon_entry channel_icon").attr("title", "Channel icon"));
//Default no sound (0)
let container = $.spawn("div");
let noSound = $.spawn("div").addClass("icon_entry icon_no_sound icon client-conflict-icon").attr("title", "You don't support the channel codec");
let bg = $.spawn("div")
.width(10)
.height(14)
.css("background", "red")
.css("position", "absolute")
.css("top", "1px")
.css("left", "3px");
bg.appendTo(container);
noSound.appendTo(container);
iconTag.append(container);
/*
setInterval(() => {
let color = (Math.random() * 10000000).toString(16).substr(0, 6);
bg.css("background", "#" + color);
}, 150);
*/
//Build siblings
this._tag_siblings = $.spawn("div").addClass("siblings");
let tag_siblings_box = $.spawn("div").css("position", "absolute").css("width", "calc(100% - 16px)").css("margin", "0px");
this._tag_siblings.appendTo(tag_siblings_box);
//Build clients
this._tag_clients = $.spawn("div").addClass("clients");
let tag_clients_box = $.spawn("div").css("position", "absolute").css("width", "calc(100% - 16px)").css("margin", "0px");
this._tag_clients.appendTo(tag_clients_box);
this._tag_root = rootTag;
tag_clients_box.appendTo(this._tag_root);
tag_siblings_box.appendTo(this._tag_root);
this._tag_channel.appendTo(this._tag_root);
}
get channelTag() {
return this.htmlTag.find(".channelLine").last();
rootTag() {
return this._tag_root;
}
channelTag() {
return this._tag_channel;
}
siblingTag() {
return this.htmlTag.find(".siblings").first(); //Here the first because first comes the siblings tag than all other sibling comes
return this._tag_siblings;
}
clientTag() {
return this.htmlTag.find(".clients").last(); //Here last because from the sibling tag client tags could be before
return this._tag_clients;
}
adjustSize(parent = true) {
const size = this.originalHeight;
@ -121,164 +174,207 @@ class ChannelEntry {
let clientSize = 0;
const sub = this.siblings(false);
sub.forEach(function (e) {
subSize += e.htmlTag.outerHeight(true);
subSize += e.rootTag().outerHeight(true);
});
const clients = this.clients(false);
clients.forEach(function (e) {
clientSize += e.htmlTag.outerHeight(true);
clientSize += e.tag.outerHeight(true);
});
if (sub.length >= 1)
subSize -= 1;
if (clients.length >= 1)
clientSize -= 1;
this.htmlTag.css({ height: size + subSize + clientSize });
this.siblingTag().css("margin-top", (clientSize + 16) + "px");
this.clientTag().css({ height: clientSize });
this._tag_root.css({ height: size + subSize + clientSize });
this._tag_siblings.css("margin-top", (clientSize + 16) + "px");
this._tag_clients.css({ height: clientSize });
if (parent && this.parentChannel())
this.parentChannel().adjustSize(parent);
}
initializeListener() {
const _this = this;
this.channelTag.click(function () {
this.channelTag().click(function () {
_this.channelTree.onSelect(_this);
});
this.channelTag.dblclick(function () {
_this.channelTree.client.serverConnection.joinChannel(_this); //TODO may ask for password
});
this.channelTag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => { _this.channelTree.onSelect(undefined); });
});
this.channelTag().dblclick(() => this.joinChannel());
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
this.channelTag().on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => {
_this.channelTree.onSelect(undefined);
});
});
}
}
showContextMenu(x, y, on_close = undefined) {
const _this = this;
let channelCreate = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_TEMPORARY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
let channelModify = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_TEMPORARY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NAME).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TOPIC).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_PASSWORD).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC_QUALITY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC_LATENCY_FACTOR).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAXCLIENTS).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAXFAMILYCLIENTS).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_SORTORDER).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_CODEC_ENCRYPTED).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TEMP_DELETE_DELAY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_ICON_MANAGE).granted(1);
let flagDelete = true;
if (this.clients(true).length > 0)
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_FLAG_FORCE).granted(1);
if (flagDelete) {
if (this.properties.channel_flag_permanent)
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_PERMANENT).granted(1);
else if (this.properties.channel_flag_semi_permanent)
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_PERMANENT).granted(1);
else
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_TEMPORARY).granted(1);
}
spawnMenu(x, y, {
type: MenuEntryType.ENTRY,
icon: "client-channel_switch",
name: "<b>Switch to channel</b>",
callback: () => {
_this.channelTree.client.getServerConnection().joinChannel(_this); //TODO ask for password if required
this.joinChannel();
}
}, MenuEntry.HR(), {
type: MenuEntryType.ENTRY,
icon: "client-channel_edit",
name: "Edit channel",
invalidPermission: !channelModify,
callback: () => {
Modals.createChannelModal(this, undefined, (changes) => {
if (!changes)
return;
changes["cid"] = this.channelId;
log.info(LogCategory.CHANNEL, "Changed channel properties of channel %s: %o", this.channelName(), changes);
});
}
}, {
type: MenuEntryType.ENTRY,
icon: "client-channel_delete",
name: "Delete channel",
invalidPermission: !flagDelete,
callback: () => this.channelTree.client.serverConnection.sendCommand("channeldelete", { cid: this.channelId })
}, MenuEntry.HR(), {
type: MenuEntryType.ENTRY,
icon: "client-channel_create_sub",
name: "Create sub channel",
disabled: true,
callback: () => {
//TODO here
}
invalidPermission: !(channelCreate && this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_CHILD).granted(1)),
callback: () => this.channelTree.spawnCreateChannel(this)
}, {
type: MenuEntryType.ENTRY,
icon: "client-channel_create",
name: "Create channel",
disabled: true,
callback: () => {
//TODO here
}
invalidPermission: !channelCreate,
callback: () => this.channelTree.spawnCreateChannel()
}, MenuEntry.CLOSE(on_close));
}
__updateChannelPropertiesFromName() {
parseType: if (this.parentChannel() == null && this._rawChannelName.charAt(0) == '[' && this._rawChannelName.indexOf(']') != -1) {
let typeData = this._rawChannelName.substr(1, this._rawChannelName.indexOf(']') - 1);
//console.log("Having spacer etc? -> " + typeData);
if (typeData.indexOf("spacer") == -1)
__updateChannelName() {
this._formatedChannelName = undefined;
parseType: if (this.parentChannel() == null && this.properties.channel_name.charAt(0) == '[') {
let end = this.properties.channel_name.indexOf(']');
if (end == -1)
break parseType;
let strAlign = typeData.substr(0, typeData.indexOf("spacer"));
if (strAlign.length > 0) {
if (strAlign.length != 1) {
if (strAlign.length != 2 || strAlign[0] != '*')
break parseType;
strAlign = strAlign.substr(1);
//TODO support repeating pattern!
let options = this.properties.channel_name.substr(1, end - 1);
if (options.indexOf("spacer") == -1)
break parseType;
options = options.substr(0, options.indexOf("spacer"));
console.log("Channel options: '" + options + "'");
if (options.length == 0)
options = "l";
else if (options.length > 1)
options = options[0];
if (options == "r" || options == "l" || options == "c" || options == "*")
this._channelAlign = options;
else
break parseType;
this._formatedChannelName = this.properties.channel_name.substr(end + 1);
console.log("Got channel name: " + this._formatedChannelName);
}
let self = this.channelTag();
let channelName = self.find(".channel_name");
channelName.text(this.formatedChannelName());
channelName.parent().removeClass("l r c *"); //Alignments
(this._formatedChannelName ? $.fn.hide : $.fn.show).apply(self.find(".channel_only_normal"));
if (this._formatedChannelName) {
channelName.parent().addClass(this._channelAlign);
if (this._channelAlign == "*") {
let lastSuccess = "";
let index = 0;
do {
channelName.text((lastSuccess = channelName.text()) + this.formatedChannelName());
console.log(channelName.parent().width() + " : " + channelName.width() + " : " + channelName.innerWidth() + " : " + channelName.outerWidth());
} while (channelName.parent().width() >= channelName.width() && ++index < 255);
if (index == 255)
console.warn(LogCategory.CHANNEL, "Repeating spacer took too much repeats!");
if (lastSuccess.length > 0) {
channelName.text(lastSuccess);
self.addClass("c");
}
}
if (strAlign == "")
this._channelAlign = "l";
else
this._channelAlign = strAlign;
var repeatData = typeData.substr(typeData.indexOf("spacer") + 6);
//console.log("Repeat data: " + repeatData);
this.properties["channel_name"] = this._rawChannelName.substr(this._rawChannelName.indexOf(']') + 1);
}
if (this.properties.channel_name == undefined) {
this.properties.channel_name = this._rawChannelName;
this._channelAlign = "l";
}
let self = this.channelTag;
if (this.properties.channel_name == this._rawChannelName) {
self.find(".channel_only_normal").show();
}
else
self.find(".channel_only_normal").hide();
self.find(".channel_name").text(this.channelName());
self.removeClass("l r c"); //Alignments
self.addClass(this._channelAlign);
console.log("Align: " + this._channelAlign);
}
updateProperty(key, value) {
this.properties[key] = value;
console.debug("Updating channel " + this.channelId + ". Key: " + key + " Value: " + value);
if (key == "channel_name") {
this._rawChannelName = value;
this.properties.channel_name = undefined;
this.__updateChannelPropertiesFromName();
}
else if (key == "channel_order") {
var order = this.channelTree.findChannel(value);
this.channelTree.moveChannel(this, order, this.parent);
}
else if (key == "channel_icon_id") {
let icons = this.channelTag.find("span");
icons.find(".icon_property").detach();
if (value > 0) {
let tag = this.channelTree.client.fileManager.icons.generateTag(value);
if (icons.children().length > 0) {
icons.children().last().after(tag);
}
else
icons.append(tag);
console.log("Channel icon: " + value);
}
}
else if (key == "channel_codec") {
this.displayMusicIcon = value == 5 || value == 3;
}
else if (key == "channel_flag_default") {
let icons = this.channelTag.find("span");
icons.find(".icon_default").detach();
if (value == "1") {
console.log("Default: '" + value + "'");
let icon = $.spawn("div");
icon.addClass("icon_default icon client-channel_default");
icon.attr("title", "Default channel");
if (icons.children().length > 0) {
icons.children().first().before(icon);
}
else
icons.append(icon);
}
}
}
set displayMusicIcon(flag) {
if (this._displayMusicIcon == flag)
return;
this._displayMusicIcon = flag;
let icons = this.channelTag.find("span");
icons.find(".icon_music").detach();
if (flag) {
let icon = $("<div/>");
icon.addClass("icon_music icon client-music");
icon.attr("title", "Music quality");
if (icons.children(".icon_default").length > 0) {
icons.children(".icon_default").first().before(icon);
}
else if (icons.children().length > 0) {
icons.children().first().before(icon);
}
updateVariables(...variables) {
let group = log.group(log.LogType.DEBUG, LogCategory.CHANNEL, "Update properties (%i) of %s (%i)", variables.length, this.channelName(), this.getChannelId());
for (let variable of variables) {
let key = variable.key;
let value = variable.value;
if (typeof (this.properties[key]) == "number")
this.properties[key] = parseInt(value);
if (typeof (this.properties[key]) == "boolean")
this.properties[key] = value == "true" || value == "1";
else
icons.append(icon);
this.properties[key] = value;
group.log("Updating property " + key + " = '%s' -> %o", value, this.properties[key]);
if (key == "channel_name") {
this.__updateChannelName();
}
else if (key == "channel_order") {
let order = this.channelTree.findChannel(this.properties.channel_order);
this.channelTree.moveChannel(this, order, this.parent);
}
else if (key == "channel_icon_id") {
let tag = this.channelTag().find(".icons .channel_icon");
(this.properties.channel_icon_id > 0 ? $.fn.show : $.fn.hide).apply(tag);
if (this.properties.channel_icon_id > 0) {
tag.children().detach();
this.channelTree.client.fileManager.icons.generateTag(this.properties.channel_icon_id).appendTo(tag);
}
}
else if (key == "channel_codec") {
(this.properties.channel_codec == 5 || this.properties.channel_codec == 3 ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_music"));
(this.channelTree.client.voiceConnection.codecSupported(this.properties.channel_codec) ? $.fn.hide : $.fn.show).apply(this.channelTag().find(".icons .icon_no_sound"));
}
else if (key == "channel_flag_default") {
(this.properties.channel_flag_default ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_default"));
}
else if (key == "channel_flag_password")
(this.properties.channel_flag_password ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_password"));
if (key == "channel_maxclients" || key == "channel_maxfamilyclients" || key == "channel_flag_private" || key == "channel_flag_password")
this.updateChannelTypeIcon();
}
group.end();
}
updateChannelTypeIcon() {
let tag = this.channelTag().find(".channel_type");
tag.removeAttr('class');
tag.addClass("channel_only_normal channel_type icon");
let type;
if (this.properties.channel_flag_password == true && !this._cachedPassword)
type = "yellow";
else if ((!this.properties.channel_flag_maxclients_unlimited && this.clients().length >= this.properties.channel_maxclients) ||
(!this.properties.channel_flag_maxfamilyclients_unlimited && this.properties.channel_maxfamilyclients >= 0 && this.clients(true).length >= this.properties.channel_maxfamilyclients))
type = "red";
else
type = "green";
tag.addClass("client-channel_" + type + "_subscribed");
}
createChatTag(braces = false) {
let tag = $.spawn("div");
@ -296,12 +392,36 @@ class ChannelEntry {
return tag.wrap("<p/>").parent();
}
channelType() {
if (this.properties.channel_flag_permanent == "1")
if (this.properties.channel_flag_permanent == true)
return ChannelType.PERMANENT;
if (this.properties.channel_flag_semi_permanent == "1")
if (this.properties.channel_flag_semi_permanent == true)
return ChannelType.SEMI_PERMANENT;
return ChannelType.TEMPORARY;
}
joinChannel() {
if (this.properties.channel_flag_password == true &&
!this._cachedPassword &&
!this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_JOIN_IGNORE_PASSWORD).granted(1)) {
createInputModal("Channel password", "Channel password:", () => true, text => {
if (typeof (text) == typeof (true))
return;
helpers.hashPassword(text).then(result => {
this._cachedPassword = result;
this.joinChannel();
this.updateChannelTypeIcon();
});
}).open();
}
else
this.channelTree.client.getServerConnection().joinChannel(this, this._cachedPassword).catch(error => {
if (error instanceof CommandResult) {
if (error.id == 781) {
this._cachedPassword = undefined;
this.updateChannelTypeIcon();
}
}
});
}
}
//Global functions
function chat_channel_contextmenu(_element, event) {

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,5 @@
/// <reference path="view.ts" />
/// <reference path="../utils/helpers.ts" />
enum ChannelType {
PERMANENT,
@ -13,51 +14,80 @@ namespace ChannelType {
}
}
class ChannelProperties {
channel_order: number = 0;
channel_name: string = "";
channel_topic: string = "";
channel_password: string = "";
channel_description: string = "";
channel_codec: number = 4;
channel_codec_quality: number = 0;
channel_codec_is_unencrypted: boolean = false;
channel_maxclients: number = -1;
channel_maxfamilyclients: number = -1;
channel_needed_talk_power: number = 1;
channel_flag_permanent: boolean = false;
channel_flag_semi_permanent: boolean = false;
channel_flag_default: boolean = false;
channel_flag_password: boolean = false;
channel_flag_maxclients_unlimited: boolean = false;
channel_flag_maxfamilyclients_inherited: boolean = false;
channel_flag_maxfamilyclients_unlimited: boolean = false;
channel_icon_id: number;
}
class ChannelEntry {
channelTree: ChannelTree;
channelId: number;
parent?: ChannelEntry;
prevChannel?: ChannelEntry;
properties: any = {
channel_order: 0,
channel_name: "undefined",
channel_flag_permanent: 0,
channel_flag_semi_permanent: 0,
channel_flag_default: 0,
channel_flag_password: 0
};
properties: ChannelProperties = new ChannelProperties();
originalHeight: number;
private _channelAlign: string;
private _rawChannelName: string;
private _htmlTag: JQuery<HTMLElement>;
private _displayMusicIcon: boolean;
private _formatedChannelName: string;
//HTML DOM elements
private _tag_root: JQuery<HTMLElement>;
private _tag_siblings: JQuery<HTMLElement>;
private _tag_clients: JQuery<HTMLElement>;
private _tag_channel: JQuery<HTMLElement>;
private _cachedPassword: string;
constructor(channelId, channelName, parent = null, prevChannel = null) {
this.properties = {};
this.properties = new ChannelProperties();
this.channelId = channelId;
this._rawChannelName = channelName;
this._formatedChannelName = channelName;
this.parent = parent;
this.prevChannel = prevChannel;
this.channelTree = null;
this.__updateChannelPropertiesFromName();
this.initializeTag();
this.__updateChannelName();
}
channelName(){
return this.properties["channel_name"];
return this.properties.channel_name;
}
rawChannelName() {
return this._rawChannelName;
formatedChannelName() {
return this._formatedChannelName ? this._formatedChannelName : this.properties.channel_name;
}
parentChannel() { return this.parent; }
hasParent(){ return this.parent != null; }
getChannelId(){ return this.channelId; }
channelClass() { return "channel_full"; }
siblings(deep = false) {
const result = [];
siblings(deep = false) : ChannelEntry[] {
const result: ChannelEntry[] = [];
if(this.channelTree == null) return [];
const self = this;
@ -100,46 +130,85 @@ class ChannelEntry {
return result;
}
get htmlTag() : JQuery<HTMLElement> {
if(this._htmlTag) return this._htmlTag;
private initializeTag() {
let rootTag = $.spawn("div");
let tag = $.spawn("div");
rootTag.attr("id", "channel_" + this.getChannelId());
rootTag.addClass("channel");
//rootTag.append($.spawn("div").addClass("icon_empty"));
tag.attr("id", "channel_" + this.getChannelId());
tag.addClass("channel");
tag.append("<div class=\"icon_empty\"></div>");
//Tag channel
this._tag_channel = $.spawn("div");
this._tag_channel.addClass("channelLine");
this._tag_channel.addClass(this._channelAlign); //For left
let channelTag = $("<div></div>");
channelTag.addClass("channelLine");
channelTag.addClass(this._channelAlign); //For left
let channelType = $.spawn("div");
channelType.addClass("channel_only_normal channel_type icon client-channel_green_subscribed");
this._tag_channel.append(channelType);
let channelType = $("<div/>");
channelType.addClass("channel_only_normal channel_type");
channelType.addClass("icon");
channelType.addClass("client-channel_green_subscribed");
channelTag.append(channelType);
this._tag_channel.append($.spawn("div").addClass("channel_name_container").append($.spawn("a").addClass("channel_name").text(this.channelName())));
channelTag.append("<a class='channel_name'>" + this.channelName() + "</a>");
//Icons
let iconTag = $.spawn("span").addClass("icons");
iconTag.appendTo(this._tag_channel);
let channelIcon = $("<span class='channel_only_normal'/>");
channelTag.append(channelIcon);
//Default icon (4)
iconTag.append($.spawn("div").addClass("channel_only_normal").append($.spawn("div").addClass("icon_entry icon_default icon client-channel_default").attr("title", "Default channel")));
//Password icon (3)
iconTag.append($.spawn("div").addClass("channel_only_normal").append($.spawn("div").addClass("icon_entry icon_password icon client-register").attr("title", "The channel is password protected")));
//Music icon (2)
iconTag.append($.spawn("div").addClass("channel_only_normal").append($.spawn("div").addClass("icon_entry icon_music icon client-music").attr("title", "Music quality")));
//Channel Icon (1)
iconTag.append($.spawn("div").addClass("channel_only_normal").addClass("icon_entry channel_icon").attr("title", "Channel icon"));
//Default no sound (0)
let container = $.spawn("div");
let noSound = $.spawn("div").addClass("icon_entry icon_no_sound icon client-conflict-icon").attr("title", "You don't support the channel codec");
let bg = $.spawn("div")
.width(10)
.height(14)
.css("background", "red")
.css("position", "absolute")
.css("top", "1px")
.css("left", "3px");
bg.appendTo(container);
noSound.appendTo(container);
iconTag.append(container);
/*
setInterval(() => {
let color = (Math.random() * 10000000).toString(16).substr(0, 6);
bg.css("background", "#" + color);
}, 150);
*/
tag.append("<div style='position: absolute; width: calc(100% - 16px); margin: 0px'><div class=\"siblings\"></div></div>");
tag.append("<div style='position: absolute; width: calc(100% - 16px); margin: 0px'><div class=\"clients\"></div></div>");
tag.append(channelTag);
//Build siblings
this._tag_siblings = $.spawn("div").addClass("siblings");
let tag_siblings_box = $.spawn("div").css("position", "absolute").css("width", "calc(100% - 16px)").css("margin", "0px");
this._tag_siblings.appendTo(tag_siblings_box);
return this._htmlTag = tag;
//Build clients
this._tag_clients = $.spawn("div").addClass("clients");
let tag_clients_box = $.spawn("div").css("position", "absolute").css("width", "calc(100% - 16px)").css("margin", "0px");
this._tag_clients.appendTo(tag_clients_box);
this._tag_root = rootTag;
tag_clients_box.appendTo(this._tag_root);
tag_siblings_box.appendTo(this._tag_root);
this._tag_channel.appendTo(this._tag_root);
}
get channelTag() : JQuery<HTMLElement> {
return this.htmlTag.find(".channelLine").last();
rootTag() : JQuery<HTMLElement> {
return this._tag_root;
}
channelTag() : JQuery<HTMLElement> {
return this._tag_channel;
}
siblingTag() : JQuery<HTMLElement> {
return this.htmlTag.find(".siblings").first(); //Here the first because first comes the siblings tag than all other sibling comes
return this._tag_siblings;
}
clientTag() : JQuery<HTMLElement>{
return this.htmlTag.find(".clients").last(); //Here last because from the sibling tag client tags could be before
return this._tag_clients;
}
adjustSize(parent = true) {
@ -149,170 +218,230 @@ class ChannelEntry {
const sub = this.siblings(false);
sub.forEach(function (e) {
subSize += e.htmlTag.outerHeight(true);
subSize += e.rootTag().outerHeight(true);
});
const clients = this.clients(false);
clients.forEach(function (e) {
clientSize += e.htmlTag.outerHeight(true);
clientSize += e.tag.outerHeight(true);
});
if(sub.length >= 1) subSize -= 1;
if(clients.length >= 1) clientSize -= 1;
this.htmlTag.css({height: size + subSize + clientSize});
this.siblingTag().css("margin-top", (clientSize + 16) + "px");
this.clientTag().css({height: clientSize});
this._tag_root.css({height: size + subSize + clientSize});
this._tag_siblings.css("margin-top", (clientSize + 16) + "px");
this._tag_clients.css({height: clientSize});
if(parent && this.parentChannel()) this.parentChannel().adjustSize(parent);
}
initializeListener(){
initializeListener() {
const _this = this;
this.channelTag.click(function () {
this.channelTag().click(function () {
_this.channelTree.onSelect(_this);
});
this.channelTag.dblclick(function () {
_this.channelTree.client.serverConnection.joinChannel(_this); //TODO may ask for password
});
this.channelTag().dblclick(() => this.joinChannel());
this.channelTag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => { _this.channelTree.onSelect(undefined); });
});
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
this.channelTag().on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => {
_this.channelTree.onSelect(undefined);
});
});
}
}
showContextMenu(x: number, y: number, on_close: () => void = undefined) {
const _this = this;
let channelCreate =
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_TEMPORARY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
let channelModify =
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_TEMPORARY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NAME).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TOPIC).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_PASSWORD).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC_QUALITY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC_LATENCY_FACTOR).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAXCLIENTS).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAXFAMILYCLIENTS).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_SORTORDER).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_CODEC_ENCRYPTED).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TEMP_DELETE_DELAY).granted(1) ||
this.channelTree.client.permissions.neededPermission(PermissionType.B_ICON_MANAGE).granted(1);
let flagDelete = true;
if(this.clients(true).length > 0)
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_FLAG_FORCE).granted(1);
if(flagDelete) {
if (this.properties.channel_flag_permanent)
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_PERMANENT).granted(1);
else if (this.properties.channel_flag_semi_permanent)
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_PERMANENT).granted(1);
else
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_TEMPORARY).granted(1);
}
spawnMenu(x, y, {
type: MenuEntryType.ENTRY,
icon: "client-channel_switch",
name: "<b>Switch to channel</b>",
callback: () => {
_this.channelTree.client.getServerConnection().joinChannel(_this); //TODO ask for password if required
this.joinChannel();
}
},
MenuEntry.HR(),
{
type: MenuEntryType.ENTRY,
icon: "client-channel_edit",
name: "Edit channel",
invalidPermission: !channelModify,
callback: () => {
Modals.createChannelModal(this, undefined, (changes?: ChannelProperties) => {
if(!changes) return;
changes["cid"] = this.channelId;
log.info(LogCategory.CHANNEL, "Changed channel properties of channel %s: %o", this.channelName(), changes);
});
}
},
{
type: MenuEntryType.ENTRY,
icon: "client-channel_delete",
name: "Delete channel",
invalidPermission: !flagDelete,
callback: () => this.channelTree.client.serverConnection.sendCommand("channeldelete", {cid: this.channelId})
},
MenuEntry.HR(),
{
type: MenuEntryType.ENTRY,
icon: "client-channel_create_sub",
name: "Create sub channel",
disabled: true,
callback: () => {
//TODO here
}
invalidPermission: !(channelCreate && this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_CHILD).granted(1)),
callback: () => this.channelTree.spawnCreateChannel(this)
}, {
type: MenuEntryType.ENTRY,
icon: "client-channel_create",
name: "Create channel",
disabled: true,
callback: () => {
//TODO here
}
invalidPermission: !channelCreate,
callback: () => this.channelTree.spawnCreateChannel()
},
MenuEntry.CLOSE(on_close)
);
}
private __updateChannelPropertiesFromName() {
private __updateChannelName() {
this._formatedChannelName = undefined;
parseType:
if(this.parentChannel() == null && this._rawChannelName.charAt(0) == '[' && this._rawChannelName.indexOf(']') != -1) {
let typeData = this._rawChannelName.substr(1, this._rawChannelName.indexOf(']') - 1);
//console.log("Having spacer etc? -> " + typeData);
if(typeData.indexOf("spacer") == -1) break parseType;
let strAlign = typeData.substr(0, typeData.indexOf("spacer"));
if(strAlign.length > 0){
if(strAlign.length != 1){
if(strAlign.length != 2 || strAlign[0] != '*')
break parseType;
strAlign = strAlign.substr(1);
//TODO support repeating pattern!
if(this.parentChannel() == null && this.properties.channel_name.charAt(0) == '[') {
let end = this.properties.channel_name.indexOf(']');
if(end == -1) break parseType;
let options = this.properties.channel_name.substr(1, end - 1);
if(options.indexOf("spacer") == -1) break parseType;
options = options.substr(0, options.indexOf("spacer"));
console.log("Channel options: '" + options + "'");
if(options.length == 0) options = "l";
else if(options.length > 1) options = options[0];
if(options == "r" || options == "l" || options == "c" || options == "*")
this._channelAlign = options;
else break parseType;
this._formatedChannelName = this.properties.channel_name.substr(end + 1);
console.log("Got channel name: " + this._formatedChannelName);
}
let self = this.channelTag();
let channelName = self.find(".channel_name");
channelName.text(this.formatedChannelName());
channelName.parent().removeClass("l r c *"); //Alignments
(this._formatedChannelName ? $.fn.hide : $.fn.show).apply(self.find(".channel_only_normal"));
if(this._formatedChannelName) {
channelName.parent().addClass(this._channelAlign);
if(this._channelAlign == "*") {
let lastSuccess = "";
let index = 0;
do {
channelName.text((lastSuccess = channelName.text()) + this.formatedChannelName());
console.log(channelName.parent().width() + " : " + channelName.width() + " : " + channelName.innerWidth() + " : " + channelName.outerWidth());
} while (channelName.parent().width() >= channelName.width() && ++index < 255);
if(index == 255) console.warn(LogCategory.CHANNEL, "Repeating spacer took too much repeats!");
if(lastSuccess.length > 0) {
channelName.text(lastSuccess);
self.addClass("c");
}
}
if(strAlign == "") this._channelAlign = "l";
else this._channelAlign = strAlign;
var repeatData = typeData.substr(typeData.indexOf("spacer") + 6);
//console.log("Repeat data: " + repeatData);
this.properties["channel_name"] = this._rawChannelName.substr(this._rawChannelName.indexOf(']') + 1);
}
if(this.properties.channel_name == undefined) {
this.properties.channel_name = this._rawChannelName;
this._channelAlign = "l";
}
let self = this.channelTag;
if(this.properties.channel_name == this._rawChannelName) {
self.find(".channel_only_normal").show();
} else self.find(".channel_only_normal").hide();
self.find(".channel_name").text(this.channelName());
self.removeClass("l r c"); //Alignments
self.addClass(this._channelAlign);
console.log("Align: " + this._channelAlign);
}
updateProperty(key, value){
this.properties[key] = value;
console.debug("Updating channel " + this.channelId + ". Key: " + key + " Value: " + value);
if(key == "channel_name") {
this._rawChannelName = value;
this.properties.channel_name = undefined;
this.__updateChannelPropertiesFromName();
} else if(key == "channel_order") {
var order = this.channelTree.findChannel(value);
this.channelTree.moveChannel(this, order, this.parent);
} else if(key == "channel_icon_id") {
let icons = this.channelTag.find("span");
icons.find(".icon_property").detach();
if(value > 0) {
let tag = this.channelTree.client.fileManager.icons.generateTag(value);
if(icons.children().length > 0){ //Channel icons at the end :)
icons.children().last().after(tag);
} else
icons.append(tag);
console.log("Channel icon: " + value);
}
} else if(key == "channel_codec") {
this.displayMusicIcon = value == 5 || value == 3;
} else if(key == "channel_flag_default") {
let icons = this.channelTag.find("span");
icons.find(".icon_default").detach();
if(value == "1") {
console.log("Default: '" + value + "'");
let icon = $.spawn("div");
icon.addClass("icon_default icon client-channel_default");
icon.attr("title", "Default channel");
updateVariables(...variables: {key: string, value: string}[]) {
let group = log.group(log.LogType.DEBUG, LogCategory.CHANNEL, "Update properties (%i) of %s (%i)", variables.length, this.channelName(), this.getChannelId());
if(icons.children().length > 0){ //Music icon at the begin
icons.children().first().before(icon);
} else
icons.append(icon);
}
for(let variable of variables) {
let key = variable.key;
let value = variable.value;
if(typeof (this.properties[key]) == "number")
this.properties[key] = parseInt(value);
if(typeof (this.properties[key]) == "boolean")
this.properties[key] = value == "true" || value == "1";
else
this.properties[key] = value;
group.log("Updating property " + key + " = '%s' -> %o", value, this.properties[key]);
if(key == "channel_name") {
this.__updateChannelName();
} else if(key == "channel_order") {
let order = this.channelTree.findChannel(this.properties.channel_order);
this.channelTree.moveChannel(this, order, this.parent);
} else if(key == "channel_icon_id") {
let tag = this.channelTag().find(".icons .channel_icon");
(this.properties.channel_icon_id > 0 ? $.fn.show : $.fn.hide).apply(tag);
if(this.properties.channel_icon_id > 0) {
tag.children().detach();
this.channelTree.client.fileManager.icons.generateTag(this.properties.channel_icon_id).appendTo(tag);
}
} else if(key == "channel_codec") {
(this.properties.channel_codec == 5 || this.properties.channel_codec == 3 ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_music"));
(this.channelTree.client.voiceConnection.codecSupported(this.properties.channel_codec) ? $.fn.hide : $.fn.show).apply(this.channelTag().find(".icons .icon_no_sound"));
} else if(key == "channel_flag_default") {
(this.properties.channel_flag_default ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_default"));
} else if(key == "channel_flag_password")
(this.properties.channel_flag_password ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_password"));
if(key == "channel_maxclients" || key == "channel_maxfamilyclients" || key == "channel_flag_private" || key == "channel_flag_password")
this.updateChannelTypeIcon();
}
group.end();
}
set displayMusicIcon(flag: boolean) {
if(this._displayMusicIcon == flag) return;
updateChannelTypeIcon() {
let tag = this.channelTag().find(".channel_type");
tag.removeAttr('class');
tag.addClass("channel_only_normal channel_type icon");
this._displayMusicIcon = flag;
let type;
if(this.properties.channel_flag_password == true && !this._cachedPassword)
type = "yellow";
else if(
(!this.properties.channel_flag_maxclients_unlimited && this.clients().length >= this.properties.channel_maxclients) ||
(!this.properties.channel_flag_maxfamilyclients_unlimited && this.properties.channel_maxfamilyclients >= 0 && this.clients(true).length >= this.properties.channel_maxfamilyclients)
)
type = "red";
else
type = "green";
let icons = this.channelTag.find("span");
icons.find(".icon_music").detach();
if(flag) {
let icon = $("<div/>");
icon.addClass("icon_music icon client-music");
icon.attr("title", "Music quality");
if(icons.children(".icon_default").length > 0){ //Music icon after default icon
icons.children(".icon_default").first().before(icon);
} else if(icons.children().length > 0){ //Music icon at the begin
icons.children().first().before(icon);
} else
icons.append(icon);
}
tag.addClass("client-channel_" + type + "_subscribed");
}
createChatTag(braces: boolean = false) : JQuery {
@ -333,10 +462,33 @@ class ChannelEntry {
}
channelType() : ChannelType {
if(this.properties.channel_flag_permanent == "1") return ChannelType.PERMANENT;
if(this.properties.channel_flag_semi_permanent == "1") return ChannelType.SEMI_PERMANENT;
if(this.properties.channel_flag_permanent == true) return ChannelType.PERMANENT;
if(this.properties.channel_flag_semi_permanent == true) return ChannelType.SEMI_PERMANENT;
return ChannelType.TEMPORARY;
}
joinChannel() {
if(this.properties.channel_flag_password == true &&
!this._cachedPassword &&
!this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_JOIN_IGNORE_PASSWORD).granted(1)) {
createInputModal("Channel password", "Channel password:", () => true, text => {
if(typeof(text) == typeof(true)) return;
helpers.hashPassword(text as string).then(result => {
this._cachedPassword = result;
this.joinChannel();
this.updateChannelTypeIcon();
});
}).open();
} else
this.channelTree.client.getServerConnection().joinChannel(this, this._cachedPassword).catch(error => {
if(error instanceof CommandResult) {
if(error.id == 781) { //Invalid password
this._cachedPassword = undefined;
this.updateChannelTypeIcon();
}
}
});
}
}
//Global functions

View File

@ -1,14 +1,27 @@
/// <reference path="channel.ts" />
/// <reference path="modal/ModalChangeVolume.ts" />
class ClientProperties {
constructor() {
this.client_version = "";
this.client_platform = "";
this.client_nickname = "unknown";
this.client_unique_identifier = "unknown";
this.client_description = "";
this.client_servergroups = "";
this.client_channel_group_id = 0;
this.client_lastconnected = 0;
this.client_flag_avatar = "";
this.client_output_muted = false;
this.client_away_message = "";
this.client_away = false;
this.client_input_hardware = false;
this.client_input_muted = false;
this.client_is_channel_commander = false;
}
}
class ClientEntry {
constructor(clientId, clientName) {
this.properties = {
client_nickname: "",
client_unique_identifier: "",
client_servergroups: "0",
client_channel_group_id: "0",
client_lastconnected: "0"
};
this.properties = new ClientProperties();
this.lastVariableUpdate = 0;
this._speaking = false;
this._clientId = clientId;
@ -34,17 +47,19 @@ class ClientEntry {
}
initializeListener() {
const _this = this;
this.htmlTag.click(event => {
this.tag.click(event => {
_this.channelTree.onSelect(_this);
});
this.htmlTag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => {
_this.channelTree.onSelect(undefined);
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
this.tag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => {
_this.channelTree.onSelect(undefined);
});
return false;
});
return false;
});
}
}
showContextMenu(x, y, on_close = undefined) {
const _this = this;
@ -140,7 +155,7 @@ class ClientEntry {
name: "Change Volume",
callback: () => {
Modals.spawnChangeVolume(this.audioController.volume, volume => {
globalClient.settings.changeServer("volume_client_" + this.clientUid(), volume);
settings.changeServer("volume_client_" + this.clientUid(), volume);
this.audioController.volume = volume;
if (globalClient.selectInfo.currentSelected == this)
globalClient.selectInfo.update();
@ -148,21 +163,19 @@ class ClientEntry {
}
}, MenuEntry.CLOSE(on_close));
}
get htmlTag() {
if (this._htmlTag)
return this._htmlTag;
get tag() {
if (this._tag)
return this._tag;
let tag = $.spawn("div");
tag.attr("id", "client_" + this.clientId());
tag.addClass("client");
tag.append("<div class=\"icon_empty\"></div>");
let clientIcon = $.spawn("div");
clientIcon.addClass("icon_client_state");
tag.append(clientIcon);
tag.append("<div class='name'>" + this.clientNickName() + "</div>");
tag.append("<div class='away'>" + this.clientNickName() + "</div>");
tag.append($.spawn("div").addClass("icon_empty"));
tag.append($.spawn("div").addClass("icon_client_state").attr("title", "Client state"));
tag.append($.spawn("div").addClass("name").text(this.clientNickName()));
tag.append($.spawn("div").addClass("away").text(this.clientNickName()));
let clientIcons = $.spawn("span");
tag.append(clientIcons);
return this._htmlTag = tag;
return this._tag = tag;
}
static chatTag(id, name, uid, braces = false) {
let tag = $.spawn("div");
@ -192,42 +205,42 @@ class ClientEntry {
updateClientIcon() {
let icon = "";
let clicon = "";
if (this.properties.client_away == "1") {
if (this.properties.client_away) {
icon = "client-away";
}
else if (this.properties.client_output_muted == "1") {
else if (this.properties.client_output_muted) {
icon = "client-hardware_output_muted";
}
else if (this.properties.client_input_hardware == "0") {
else if (!this.properties.client_input_hardware) {
icon = "client-hardware_input_muted";
}
else if (this.properties.client_input_muted == "1") {
else if (this.properties.client_input_muted) {
icon = "client-input_muted";
}
else {
if (this._speaking) {
if (this.properties.client_is_channel_commander == 1)
if (this.properties.client_is_channel_commander)
clicon = "client_cc_talk";
else
clicon = "client_talk";
}
else {
if (this.properties.client_is_channel_commander == 1)
if (this.properties.client_is_channel_commander)
clicon = "client_cc_idle";
else
clicon = "client_idle";
}
}
if (clicon.length > 0)
this.htmlTag.find(".icon_client_state").attr('class', 'icon_client_state clicon ' + clicon);
this.tag.find(".icon_client_state").attr('class', 'icon_client_state clicon ' + clicon);
else if (icon.length > 0)
this.htmlTag.find(".icon_client_state").attr('class', 'icon_client_state icon ' + icon);
this.tag.find(".icon_client_state").attr('class', 'icon_client_state icon ' + icon);
else
this.htmlTag.find(".icon_client_state").attr('class', 'icon_client_state icon_empty');
this.tag.find(".icon_client_state").attr('class', 'icon_client_state icon_empty');
}
updateAwayMessage() {
let tag = this.htmlTag.find(".away");
if (this.properties.client_away == 1 && this.properties.client_away_message) {
let tag = this.tag.find(".away");
if (this.properties.client_away == true && this.properties.client_away_message) {
tag.text("[" + this.properties.client_away_message + "]");
tag.show();
}
@ -235,27 +248,37 @@ class ClientEntry {
tag.hide();
}
}
updateVariable(key, value) {
this.properties[key] = value;
console.debug("Updating client " + this.clientId() + ". Key " + key + " Value: '" + value + "'");
if (key == "client_nickname") {
this.htmlTag.find(".name").text(value);
let chat = this.chat(false);
if (chat)
chat.name = value;
}
if (key == "client_away" || key == "client_output_muted" || key == "client_input_hardware" || key == "client_input_muted" || key == "client_is_channel_commander") {
this.updateClientIcon();
}
if (key == "client_away_message" || key == "client_away") {
this.updateAwayMessage();
}
if (key == "client_unique_identifier") {
this.audioController.volume = parseFloat(globalClient.settings.server("volume_client_" + this.clientUid(), "1"));
console.error("Updated volume from config " + this.audioController.volume + " - " + "volume_client_" + this.clientUid() + " - " + globalClient.settings.server("volume_client_" + this.clientUid(), "1"));
updateVariables(...variables) {
let group = log.group(log.LogType.DEBUG, LogCategory.CLIENT, "Update properties (%i) of %s (%i)", variables.length, this.clientNickName(), this.clientId());
for (let variable of variables) {
if (typeof (this.properties[variable.key]) === "boolean")
this.properties[variable.key] = variable.value == "true" || variable.value == "1";
else if (typeof (this.properties[variable.key]) === "number")
this.properties[variable.key] = parseInt(variable.value);
else
this.properties[variable.key] = variable.value;
group.log("Updating client " + this.clientId() + ". Key " + variable.key + " Value: '" + variable.value + "' (" + typeof (this.properties[variable.key]) + ")");
if (variable.key == "client_nickname") {
this.tag.find(".name").text(variable.value);
let chat = this.chat(false);
if (chat)
chat.name = variable.value;
}
if (variable.key == "client_away" || variable.key == "client_output_muted" || variable.key == "client_input_hardware" || variable.key == "client_input_muted" || variable.key == "client_is_channel_commander") {
this.updateClientIcon();
}
if (variable.key == "client_away_message" || variable.key == "client_away") {
this.updateAwayMessage();
}
if (variable.key == "client_unique_identifier") {
this.audioController.volume = parseFloat(settings.server("volume_client_" + this.clientUid(), "1"));
console.error("Updated volume from config " + this.audioController.volume + " - " + "volume_client_" + this.clientUid() + " - " + settings.server("volume_client_" + this.clientUid(), "1"));
console.log(this.avatarId());
}
}
group.end();
}
updateVariables() {
updateClientVariables() {
if (this.lastVariableUpdate == 0 || new Date().getTime() - 10 * 60 * 1000 > this.lastVariableUpdate) {
this.lastVariableUpdate = new Date().getTime();
this.channelTree.client.serverConnection.sendCommand("clientgetvariables", { clid: this.clientId() });
@ -282,10 +305,9 @@ class ClientEntry {
}
updateGroupIcon(group) {
//TODO group icon order
this.htmlTag.find(".icon_group_" + group.id).detach();
if (group.properties.iconid > 0) {
this.htmlTag.find("span").append(this.channelTree.client.fileManager.icons.generateTag(group.properties.iconid).addClass("icon_group_" + group.id));
}
this.tag.find(".icon_group_" + group.id).detach();
if (group.properties.iconid > 0)
this.tag.find("span").append(this.channelTree.client.fileManager.icons.generateTag(group.properties.iconid).addClass("icon_group_" + group.id));
}
assignedServerGroupIds() {
let result = [];
@ -297,7 +319,7 @@ class ClientEntry {
return result;
}
assignedChannelGroup() {
return Number.parseInt(this.properties.client_channel_group_id);
return this.properties.client_channel_group_id;
}
groupAssigned(group) {
if (group.target == GroupTarget.SERVER) {
@ -314,7 +336,37 @@ class ClientEntry {
this.audioController = undefined;
}
calculateOnlineTime() {
return new Date().getTime() / 1000 - Number.parseInt(this.properties.client_lastconnected);
return new Date().getTime() / 1000 - this.properties.client_lastconnected;
}
avatarId() {
function str2ab(str) {
let buf = new ArrayBuffer(str.length); // 2 bytes for each char
let bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
try {
let raw = atob(this.properties.client_unique_identifier);
let input = hex.encode(str2ab(raw));
let result = "";
for (let index = 0; index < input.length; index++) {
let c = input.charAt(index);
let offset = 0;
if (c >= '0' && c <= '9')
offset = c.charCodeAt(0) - '0'.charCodeAt(0);
else if (c >= 'A' && c <= 'F')
offset = c.charCodeAt(0) - 'A'.charCodeAt(0) + 0x0A;
else if (c >= 'a' && c <= 'f')
offset = c.charCodeAt(0) - 'a'.charCodeAt(0) + 0x0A;
result += String.fromCharCode('a'.charCodeAt(0) + offset);
}
return result;
}
catch (e) {
return undefined;
}
}
}
class LocalClientEntry extends ClientEntry {
@ -322,9 +374,6 @@ class LocalClientEntry extends ClientEntry {
super(0, "local client");
this.handle = handle;
}
updateVariable(key, value) {
super.updateVariable(key, value);
}
showContextMenu(x, y, on_close = undefined) {
const _self = this;
spawnMenu(x, y, {
@ -351,15 +400,15 @@ class LocalClientEntry extends ClientEntry {
}
initializeListener() {
super.initializeListener();
this.htmlTag.find(".name").addClass("own_name");
this.tag.find(".name").addClass("own_name");
const _self = this;
this.htmlTag.dblclick(function () {
this.tag.dblclick(function () {
_self.openRename();
});
}
openRename() {
const _self = this;
const elm = this.htmlTag.find(".name");
const elm = this.tag.find(".name");
elm.attr("contenteditable", "true");
elm.removeClass("own_name");
elm.css("background-color", "white");

File diff suppressed because one or more lines are too long

View File

@ -1,18 +1,36 @@
/// <reference path="channel.ts" />
/// <reference path="modal/ModalChangeVolume.ts" />
class ClientProperties {
client_version: string = "";
client_platform: string = "";
client_nickname: string = "unknown";
client_unique_identifier: string = "unknown";
client_description: string = "";
client_servergroups: string = "";
client_channel_group_id: number = 0;
client_lastconnected: number = 0;
client_flag_avatar: string = "";
client_output_muted: boolean = false;
client_away_message: string = "";
client_away: boolean = false;
client_input_hardware: boolean = false;
client_input_muted: boolean = false;
client_is_channel_commander: boolean = false;
}
class ClientEntry {
private _clientId: number;
private _channel: ChannelEntry;
private _htmlTag: JQuery<HTMLElement>;
private _tag: JQuery<HTMLElement>;
properties: any = {
client_nickname: "",
client_unique_identifier: "",
client_servergroups: "0",
client_channel_group_id: "0",
client_lastconnected: "0"
};
properties: ClientProperties = new ClientProperties();
private lastVariableUpdate: number = 0;
private _speaking: boolean = false;
@ -48,17 +66,20 @@ class ClientEntry {
initializeListener(){
const _this = this;
this.htmlTag.click(event => {
this.tag.click(event => {
_this.channelTree.onSelect(_this);
});
this.htmlTag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => {
_this.channelTree.onSelect(undefined);
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
this.tag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.showContextMenu(event.pageX, event.pageY, () => {
_this.channelTree.onSelect(undefined);
});
return false;
});
return false;
});
}
}
showContextMenu(x: number, y: number, on_close: () => void = undefined) {
@ -164,7 +185,7 @@ class ClientEntry {
name: "Change Volume",
callback: () => {
Modals.spawnChangeVolume(this.audioController.volume, volume => {
globalClient.settings.changeServer("volume_client_" + this.clientUid(), volume);
settings.changeServer("volume_client_" + this.clientUid(), volume);
this.audioController.volume = volume;
if(globalClient.selectInfo.currentSelected == this)
globalClient.selectInfo.update();
@ -175,26 +196,24 @@ class ClientEntry {
);
}
get htmlTag() : JQuery<HTMLElement> {
if(this._htmlTag) return this._htmlTag;
get tag() : JQuery<HTMLElement> {
if(this._tag) return this._tag;
let tag = $.spawn("div")
let tag = $.spawn("div");
tag.attr("id", "client_" + this.clientId());
tag.addClass("client");
tag.append("<div class=\"icon_empty\"></div>");
tag.append($.spawn("div").addClass("icon_empty"));
let clientIcon = $.spawn("div");
clientIcon.addClass("icon_client_state");
tag.append(clientIcon);
tag.append($.spawn("div").addClass("icon_client_state").attr("title", "Client state"));
tag.append("<div class='name'>" + this.clientNickName() + "</div>");
tag.append("<div class='away'>" + this.clientNickName() + "</div>");
tag.append($.spawn("div").addClass("name").text(this.clientNickName()));
tag.append($.spawn("div").addClass("away").text(this.clientNickName()));
let clientIcons = $.spawn("span");
tag.append(clientIcons);
return this._htmlTag = tag;
return this._tag = tag;
}
static chatTag(id: number, name: string, uid: string, braces: boolean = false) : JQuery {
@ -229,38 +248,38 @@ class ClientEntry {
updateClientIcon() {
let icon: string = "";
let clicon: string = "";
if(this.properties.client_away == "1") {
if(this.properties.client_away) {
icon = "client-away";
} else if(this.properties.client_output_muted == "1") {
} else if(this.properties.client_output_muted) {
icon = "client-hardware_output_muted";
} else if(this.properties.client_input_hardware == "0") {
} else if(!this.properties.client_input_hardware) {
icon = "client-hardware_input_muted";
} else if(this.properties.client_input_muted == "1") {
} else if(this.properties.client_input_muted) {
icon = "client-input_muted";
} else {
if(this._speaking) {
if(this.properties.client_is_channel_commander == 1)
if(this.properties.client_is_channel_commander)
clicon = "client_cc_talk";
else
clicon = "client_talk";
} else {
if(this.properties.client_is_channel_commander == 1)
if(this.properties.client_is_channel_commander)
clicon = "client_cc_idle";
else
clicon = "client_idle";
}
}
if(clicon.length > 0)
this.htmlTag.find(".icon_client_state").attr('class', 'icon_client_state clicon ' + clicon);
this.tag.find(".icon_client_state").attr('class', 'icon_client_state clicon ' + clicon);
else if(icon.length > 0)
this.htmlTag.find(".icon_client_state").attr('class', 'icon_client_state icon ' + icon);
this.tag.find(".icon_client_state").attr('class', 'icon_client_state icon ' + icon);
else
this.htmlTag.find(".icon_client_state").attr('class', 'icon_client_state icon_empty');
this.tag.find(".icon_client_state").attr('class', 'icon_client_state icon_empty');
}
updateAwayMessage() {
let tag = this.htmlTag.find(".away");
if(this.properties.client_away == 1 && this.properties.client_away_message){
let tag = this.tag.find(".away");
if(this.properties.client_away == true && this.properties.client_away_message){
tag.text("[" + this.properties.client_away_message + "]");
tag.show();
} else {
@ -268,28 +287,39 @@ class ClientEntry {
}
}
updateVariable(key: string, value: string) {
this.properties[key] = value;
updateVariables(...variables: {key: string, value: string}[]) {
let group = log.group(log.LogType.DEBUG, LogCategory.CLIENT, "Update properties (%i) of %s (%i)", variables.length, this.clientNickName(), this.clientId());
console.debug("Updating client " + this.clientId() + ". Key " + key + " Value: '" + value + "'");
if(key == "client_nickname") {
this.htmlTag.find(".name").text(value);
let chat = this.chat(false);
if(chat) chat.name = value;
}
if(key == "client_away" || key == "client_output_muted" || key == "client_input_hardware" || key == "client_input_muted" || key == "client_is_channel_commander"){
this.updateClientIcon();
}
if(key == "client_away_message" || key == "client_away") {
this.updateAwayMessage();
}
if(key == "client_unique_identifier") {
this.audioController.volume = parseFloat(globalClient.settings.server("volume_client_" + this.clientUid(), "1"));
console.error("Updated volume from config " + this.audioController.volume + " - " + "volume_client_" + this.clientUid() + " - " + globalClient.settings.server("volume_client_" + this.clientUid(), "1"));
for(let variable of variables) {
if(typeof(this.properties[variable.key]) === "boolean")
this.properties[variable.key] = variable.value == "true" || variable.value == "1";
else if(typeof (this.properties[variable.key]) === "number")
this.properties[variable.key] = parseInt(variable.value);
else
this.properties[variable.key] = variable.value;
group.log("Updating client " + this.clientId() + ". Key " + variable.key + " Value: '" + variable.value + "' (" + typeof (this.properties[variable.key]) + ")");
if(variable.key == "client_nickname") {
this.tag.find(".name").text(variable.value);
let chat = this.chat(false);
if(chat) chat.name = variable.value;
}
if(variable.key == "client_away" || variable.key == "client_output_muted" || variable.key == "client_input_hardware" || variable.key == "client_input_muted" || variable.key == "client_is_channel_commander"){
this.updateClientIcon();
}
if(variable.key == "client_away_message" || variable.key == "client_away") {
this.updateAwayMessage();
}
if(variable.key == "client_unique_identifier") {
this.audioController.volume = parseFloat(settings.server("volume_client_" + this.clientUid(), "1"));
console.error("Updated volume from config " + this.audioController.volume + " - " + "volume_client_" + this.clientUid() + " - " + settings.server("volume_client_" + this.clientUid(), "1"));
console.log(this.avatarId());
}
}
group.end();
}
updateVariables(){
updateClientVariables(){
if(this.lastVariableUpdate == 0 || new Date().getTime() - 10 * 60 * 1000 > this.lastVariableUpdate){ //Cache these only 10 min
this.lastVariableUpdate = new Date().getTime();
this.channelTree.client.serverConnection.sendCommand("clientgetvariables", {clid: this.clientId()});
@ -318,13 +348,13 @@ class ClientEntry {
return c;
}
updateGroupIcon(group: Group) {
//TODO group icon order
this.htmlTag.find(".icon_group_" + group.id).detach();
this.tag.find(".icon_group_" + group.id).detach();
if(group.properties.iconid > 0){
this.htmlTag.find("span").append(this.channelTree.client.fileManager.icons.generateTag(group.properties.iconid).addClass("icon_group_" + group.id));
}
if(group.properties.iconid > 0)
this.tag.find("span").append(this.channelTree.client.fileManager.icons.generateTag(group.properties.iconid).addClass("icon_group_" + group.id));
}
assignedServerGroupIds() : number[] {
@ -337,7 +367,7 @@ class ClientEntry {
}
assignedChannelGroup() : number {
return Number.parseInt(this.properties.client_channel_group_id);
return this.properties.client_channel_group_id;
}
groupAssigned(group: Group) : boolean {
@ -354,7 +384,39 @@ class ClientEntry {
}
calculateOnlineTime() : number {
return new Date().getTime() / 1000 - Number.parseInt(this.properties.client_lastconnected);
return new Date().getTime() / 1000 - this.properties.client_lastconnected;
}
avatarId?() : string {
function str2ab(str) {
let buf = new ArrayBuffer(str.length); // 2 bytes for each char
let bufView = new Uint8Array(buf);
for (let i=0, strLen=str.length; i<strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
try {
let raw = atob(this.properties.client_unique_identifier);
let input = hex.encode(str2ab(raw));
let result: string = "";
for(let index = 0; index < input.length; index++) {
let c = input.charAt(index);
let offset: number = 0;
if(c >= '0' && c <= '9')
offset = c.charCodeAt(0) - '0'.charCodeAt(0);
else if(c >= 'A' && c <= 'F')
offset = c.charCodeAt(0) - 'A'.charCodeAt(0) + 0x0A;
else if(c >= 'a' && c <= 'f')
offset = c.charCodeAt(0) - 'a'.charCodeAt(0) + 0x0A;
result += String.fromCharCode('a'.charCodeAt(0) + offset);
}
return result;
} catch (e) { //invalid base 64 (like music bot etc)
return undefined;
}
}
}
@ -368,12 +430,6 @@ class LocalClientEntry extends ClientEntry {
this.handle = handle;
}
updateVariable(key: string, value: string): void {
super.updateVariable(key, value);
}
showContextMenu(x: number, y: number, on_close: () => void = undefined): void {
const _self = this;
@ -406,10 +462,10 @@ class LocalClientEntry extends ClientEntry {
initializeListener(): void {
super.initializeListener();
this.htmlTag.find(".name").addClass("own_name");
this.tag.find(".name").addClass("own_name");
const _self = this;
this.htmlTag.dblclick(function () {
this.tag.dblclick(function () {
_self.openRename();
});
}
@ -417,7 +473,7 @@ class LocalClientEntry extends ClientEntry {
openRename() : void {
const _self = this;
const elm = this.htmlTag.find(".name");
const elm = this.tag.find(".name");
elm.attr("contenteditable", "true");
elm.removeClass("own_name");
elm.css("background-color", "white");
@ -449,7 +505,6 @@ class LocalClientEntry extends ClientEntry {
_self.openRename();
});
});
}
}
//Global functions

View File

@ -50,12 +50,12 @@ var Modals;
tag.find(".connect_address").on("keyup", () => updateFields());
tag.find(".connect_nickname").on("keyup", () => updateFields());
tag.find(".identity_select").on('change', function () {
globalClient.settings.changeGlobal("connect_identity_type", this.value);
settings.changeGlobal("connect_identity_type", this.value);
tag.find(".error_message").hide();
tag.find(".identity_config:not(" + ".identity_config_" + this.value + ")").hide();
tag.find(".identity_config_" + this.value).show().trigger('shown');
});
tag.find(".identity_select").val(globalClient.settings.global("connect_identity_type", "forum"));
tag.find(".identity_select").val(settings.global("connect_identity_type", "forum"));
setTimeout(() => tag.find(".identity_select").trigger('change'), 0); //For some reason could not be run instantly
tag.find(".identity_file").change(function () {
const reader = new FileReader();
@ -66,7 +66,7 @@ var Modals;
tag.find(".error_message").text("Could not read identity! " + TSIdentityHelper.last_error());
else {
tag.find(".identity_string").val(connectIdentity.exported());
globalClient.settings.changeGlobal("connect_identity_teamspeak_identity", connectIdentity.exported());
settings.changeGlobal("connect_identity_teamspeak_identity", connectIdentity.exported());
}
(!!connectIdentity ? tag.hide : tag.show).apply(tag.find(".error_message"));
updateFields();
@ -86,13 +86,13 @@ var Modals;
if (!connectIdentity)
tag.find(".error_message").text("Could not parse identity! " + TSIdentityHelper.last_error());
else
globalClient.settings.changeGlobal("connect_identity_teamspeak_identity", this.value);
settings.changeGlobal("connect_identity_teamspeak_identity", this.value);
}
(!!connectIdentity ? tag.hide : tag.show).apply(tag.find(".error_message"));
tag.find(".identity_file").val("");
updateFields();
});
tag.find(".identity_string").val(globalClient.settings.global("connect_identity_teamspeak_identity", ""));
tag.find(".identity_string").val(settings.global("connect_identity_teamspeak_identity", ""));
tag.find(".identity_config_teamspeak").on('shown', ev => { tag.find(".identity_string").trigger('change'); });
if (!forumIdentity)
tag.find(".identity_config_forum").html("You cant use your TeaSpeak forum account.<br>You're not connected!");

File diff suppressed because one or more lines are too long

View File

@ -53,12 +53,12 @@ namespace Modals {
tag.find(".connect_nickname").on("keyup", () => updateFields());
tag.find(".identity_select").on('change', function (this: HTMLSelectElement) {
globalClient.settings.changeGlobal("connect_identity_type", this.value);
settings.changeGlobal("connect_identity_type", this.value);
tag.find(".error_message").hide();
tag.find(".identity_config:not(" + ".identity_config_" + this.value + ")").hide();
tag.find(".identity_config_" + this.value).show().trigger('shown');
});
tag.find(".identity_select").val(globalClient.settings.global("connect_identity_type", "forum"));
tag.find(".identity_select").val(settings.global("connect_identity_type", "forum"));
setTimeout(() => tag.find(".identity_select").trigger('change'), 0); //For some reason could not be run instantly
tag.find(".identity_file").change(function (this: HTMLInputElement) {
@ -70,7 +70,7 @@ namespace Modals {
if(!connectIdentity) tag.find(".error_message").text("Could not read identity! " + TSIdentityHelper.last_error());
else {
tag.find(".identity_string").val((connectIdentity as TeamSpeakIdentity).exported());
globalClient.settings.changeGlobal("connect_identity_teamspeak_identity", (connectIdentity as TeamSpeakIdentity).exported());
settings.changeGlobal("connect_identity_teamspeak_identity", (connectIdentity as TeamSpeakIdentity).exported());
}
(!!connectIdentity ? tag.hide : tag.show).apply(tag.find(".error_message"));
@ -89,13 +89,13 @@ namespace Modals {
} else {
connectIdentity = TSIdentityHelper.loadIdentity(this.value);
if(!connectIdentity) tag.find(".error_message").text("Could not parse identity! " + TSIdentityHelper.last_error());
else globalClient.settings.changeGlobal("connect_identity_teamspeak_identity", this.value);
else settings.changeGlobal("connect_identity_teamspeak_identity", this.value);
}
(!!connectIdentity ? tag.hide : tag.show).apply(tag.find(".error_message"));
tag.find(".identity_file").val("");
updateFields();
});
tag.find(".identity_string").val(globalClient.settings.global("connect_identity_teamspeak_identity", ""));
tag.find(".identity_string").val(settings.global("connect_identity_teamspeak_identity", ""));
tag.find(".identity_config_teamspeak").on('shown', ev => { tag.find(".identity_string").trigger('change'); });
if(!forumIdentity)

View File

@ -1,37 +1,125 @@
/// <reference path="../../utils/modal.ts" />
var Modals;
(function (Modals) {
function createChannelModal(channel) {
function createChannelModal(channel, parent, callback) {
let properties = {}; //The changes properties
const modal = createModal({
header: "Create channel",
header: channel ? "Edit channel" : "Create channel",
body: () => {
let template = $("#tmpl_channel_edit").tmpl({
channel_name: "Hello World",
myArray: [
"A",
"B",
"C"
]
});
let template = $("#tmpl_channel_edit").tmpl(channel ? channel.properties : new ChannelProperties());
template = $.spawn("div").append(template);
let tag = template.tabify();
return tag;
return template.tabify();
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
footer.css("margin", "5px");
let buttonCancel = $.spawn("button");
buttonCancel.text("Cancel");
buttonCancel.text("Cancel").addClass("button_cancel");
let buttonOk = $.spawn("button");
buttonOk.text("Ok");
buttonOk.text("Ok").addClass("button_ok");
footer.append(buttonCancel);
footer.append(buttonOk);
return footer;
},
width: 500
});
applyGeneralListener(properties, modal.htmlTag.find(".channel_general_properties"), modal.htmlTag.find(".button_ok"), !channel);
applyStandardListener(properties, modal.htmlTag.find(".settings_standard"), modal.htmlTag.find(".button_ok"), parent, !channel);
modal.htmlTag.find(".button_ok").click(() => {
modal.close();
callback(properties);
});
modal.htmlTag.find(".button_cancel").click(() => {
modal.close();
callback();
});
modal.open();
}
Modals.createChannelModal = createChannelModal;
function applyGeneralListener(properties, tag, button, create) {
let updateButton = () => {
if (tag.find(".input_error").length == 0)
button.removeAttr("disabled");
else
button.attr("disabled", "true");
};
tag.find(".channel_name").change(function () {
properties.channel_name = this.value;
$(this).removeClass("input_error");
if (this.value.length < 1 || this.value.length > 40)
$(this).addClass("input_error");
updateButton();
}).prop("disabled", !create && !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NAME).granted(1));
tag.find(".channel_password").change(function () {
properties.channel_flag_password = this.value.length != 0;
if (properties.channel_flag_password)
helpers.hashPassword(this.value).then(pass => properties.channel_password = pass);
$(this).removeClass("input_error");
if (!properties.channel_flag_password)
if (globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_FORCE_PASSWORD).granted(1))
$(this).addClass("input_error");
updateButton();
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_PASSWORD : PermissionType.B_CHANNEL_MODIFY_PASSWORD).granted(1));
tag.find(".channel_topic").change(function () {
properties.channel_topic = this.value;
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_TOPIC : PermissionType.B_CHANNEL_MODIFY_TOPIC).granted(1));
tag.find(".channel_description").change(function () {
properties.channel_description = this.value;
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DESCRIPTION : PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1));
if (create) {
tag.find(".channel_name").trigger("change");
tag.find(".channel_password").trigger('change');
}
}
function applyStandardListener(properties, tag, button, parent, create) {
tag.find("input[name=\"channel_type\"]").change(function () {
switch (this.value) {
case "semi":
properties.channel_flag_permanent = false;
properties.channel_flag_semi_permanent = true;
break;
case "perm":
properties.channel_flag_permanent = true;
properties.channel_flag_semi_permanent = false;
break;
default:
properties.channel_flag_permanent = false;
properties.channel_flag_semi_permanent = false;
break;
}
});
tag.find("input[name=\"channel_type\"][value=\"temp\"]")
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_TEMPORARY : PermissionType.B_CHANNEL_MODIFY_MAKE_TEMPORARY).granted(1));
tag.find("input[name=\"channel_type\"][value=\"semi\"]")
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT).granted(1));
tag.find("input[name=\"channel_type\"][value=\"perm\"]")
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1));
tag.find("input[name=\"channel_type\"]:not(:disabled)").last().prop("checked", true).trigger('change');
tag.find("input[name=\"channel_default\"]").change(function () {
console.log(this.checked);
properties.channel_flag_default = this.checked;
let elements = tag.find("input[name=\"channel_type\"]");
if (this.checked) {
elements.prop("enabled", false);
elements.prop("checked", false);
tag.find("input[name=\"channel_type\"][value=\"perm\"]").prop("checked", true).trigger("change");
}
else
elements.removeProp("enabled");
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
!globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DEFAULT : PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1));
tag.find("input[name=\"talk_power\"]").change(function () {
properties.channel_needed_talk_power = parseInt(this.value);
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER : PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1));
let orderTag = tag.find(".order_id");
for (let channel of (parent ? parent.siblings() : globalClient.channelTree.rootChannel()))
$.spawn("option").attr("channelId", channel.channelId.toString()).text(channel.channelName()).appendTo(orderTag);
orderTag.change(function () {
let selected = $(this.options.item(this.selectedIndex));
properties.channel_order = parseInt(selected.attr("channelId"));
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_SORTORDER : PermissionType.B_CHANNEL_MODIFY_SORTORDER).granted(1));
orderTag.find("option").last().prop("selected", true);
}
})(Modals || (Modals = {}));
//# sourceMappingURL=ModalCreateChannel.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,33 +1,25 @@
/// <reference path="../../utils/modal.ts" />
namespace Modals {
export function createChannelModal(channel?: ChannelEntry) {
export function createChannelModal(channel: ChannelEntry | undefined, parent: ChannelEntry | undefined, callback: (ChannelProperties?: ChannelProperties) => void) {
let properties: ChannelProperties = { } as ChannelProperties; //The changes properties
const modal = createModal({
header: "Create channel",
header: channel ? "Edit channel" : "Create channel",
body: () => {
let template = $("#tmpl_channel_edit").tmpl({
channel_name: "Hello World",
myArray: [
"A",
"B",
"C"
]
});
let template = $("#tmpl_channel_edit").tmpl(channel ? channel.properties : new ChannelProperties());
template = $.spawn("div").append(template);
let tag = template.tabify();
return tag;
return template.tabify();
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
footer.css("margin", "5px");
let buttonCancel = $.spawn("button");
buttonCancel.text("Cancel");
buttonCancel.text("Cancel").addClass("button_cancel");
let buttonOk = $.spawn("button");
buttonOk.text("Ok");
buttonOk.text("Ok").addClass("button_ok");
footer.append(buttonCancel);
footer.append(buttonOk);
@ -36,5 +28,117 @@ namespace Modals {
},
width: 500
});
applyGeneralListener(properties, modal.htmlTag.find(".channel_general_properties"), modal.htmlTag.find(".button_ok"), !channel);
applyStandardListener(properties, modal.htmlTag.find(".settings_standard"), modal.htmlTag.find(".button_ok"), parent, !channel);
modal.htmlTag.find(".button_ok").click(() => {
modal.close();
callback(properties);
});
modal.htmlTag.find(".button_cancel").click(() => {
modal.close();
callback();
});
modal.open();
}
function applyGeneralListener(properties: ChannelProperties, tag: JQuery, button: JQuery, create: boolean) {
let updateButton = () => {
if(tag.find(".input_error").length == 0)
button.removeAttr("disabled");
else button.attr("disabled", "true");
};
tag.find(".channel_name").change(function (this: HTMLInputElement) {
properties.channel_name = this.value;
$(this).removeClass("input_error");
if(this.value.length < 1 || this.value.length > 40)
$(this).addClass("input_error");
updateButton();
}).prop("disabled", !create && !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NAME).granted(1));
tag.find(".channel_password").change(function (this: HTMLInputElement) {
properties.channel_flag_password = this.value.length != 0;
if(properties.channel_flag_password)
helpers.hashPassword(this.value).then(pass => properties.channel_password = pass);
$(this).removeClass("input_error");
if(!properties.channel_flag_password)
if(globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_FORCE_PASSWORD).granted(1))
$(this).addClass("input_error");
updateButton();
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_PASSWORD : PermissionType.B_CHANNEL_MODIFY_PASSWORD).granted(1));
tag.find(".channel_topic").change(function (this: HTMLInputElement) {
properties.channel_topic = this.value;
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_TOPIC : PermissionType.B_CHANNEL_MODIFY_TOPIC).granted(1));
tag.find(".channel_description").change(function (this: HTMLInputElement) {
properties.channel_description = this.value;
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DESCRIPTION : PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1));
if(create) {
tag.find(".channel_name").trigger("change");
tag.find(".channel_password").trigger('change');
}
}
function applyStandardListener(properties: ChannelProperties, tag: JQuery, button: JQuery, parent: ChannelEntry, create: boolean) {
tag.find("input[name=\"channel_type\"]").change(function (this: HTMLInputElement) {
switch(this.value) {
case "semi":
properties.channel_flag_permanent = false;
properties.channel_flag_semi_permanent = true;
break;
case "perm":
properties.channel_flag_permanent = true;
properties.channel_flag_semi_permanent = false;
break;
default:
properties.channel_flag_permanent = false;
properties.channel_flag_semi_permanent = false;
break;
}
});
tag.find("input[name=\"channel_type\"][value=\"temp\"]")
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_TEMPORARY : PermissionType.B_CHANNEL_MODIFY_MAKE_TEMPORARY).granted(1));
tag.find("input[name=\"channel_type\"][value=\"semi\"]")
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT).granted(1));
tag.find("input[name=\"channel_type\"][value=\"perm\"]")
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1));
tag.find("input[name=\"channel_type\"]:not(:disabled)").last().prop("checked", true).trigger('change');
tag.find("input[name=\"channel_default\"]").change(function (this: HTMLInputElement) {
console.log(this.checked);
properties.channel_flag_default = this.checked;
let elements = tag.find("input[name=\"channel_type\"]");
if(this.checked) {
elements.prop("enabled", false);
elements.prop("checked", false);
tag.find("input[name=\"channel_type\"][value=\"perm\"]").prop("checked", true).trigger("change");
} else elements.removeProp("enabled");
}).prop("disabled",
!globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
!globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DEFAULT : PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1));
tag.find("input[name=\"talk_power\"]").change(function (this: HTMLInputElement) {
properties.channel_needed_talk_power = parseInt(this.value);
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER : PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1));
let orderTag = tag.find(".order_id");
for(let channel of (parent ? parent.siblings() : globalClient.channelTree.rootChannel()))
$.spawn("option").attr("channelId", channel.channelId.toString()).text(channel.channelName()).appendTo(orderTag);
orderTag.change(function (this: HTMLSelectElement) {
let selected = $(this.options.item(this.selectedIndex));
properties.channel_order = parseInt(selected.attr("channelId"));
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_SORTORDER : PermissionType.B_CHANNEL_MODIFY_SORTORDER).granted(1));
orderTag.find("option").last().prop("selected", true);
}
}

View File

@ -35,16 +35,16 @@ var Modals;
initialiseVoiceListeners(modal, tag.find(".settings_voice"));
}
function initialiseVoiceListeners(modal, tag) {
let currentVAD = globalClient.settings.global("vad_type");
let currentVAD = settings.global("vad_type");
tag.find("input[type=radio][name=\"vad_type\"]").change(function () {
tag.find(".vad_settings .vad_type").text($(this).attr("display"));
tag.find(".vad_settings .vad_type_settings").hide();
tag.find(".vad_settings .vad_type_" + this.value).show();
globalClient.settings.changeGlobal("vad_type", this.value);
settings.changeGlobal("vad_type", this.value);
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
switch (this.value) {
case "ppt":
let keyCode = parseInt(globalClient.settings.global("vad_ppt_key", 84 /* T */.toString()));
let keyCode = parseInt(settings.global("vad_ppt_key", 84 /* T */.toString()));
tag.find(".vat_ppt_key").text(String.fromCharCode(keyCode));
break;
case "vad":
@ -78,7 +78,7 @@ var Modals;
$(document).one("keypress", function (e) {
console.log("Got key " + e.keyCode);
modal.close();
globalClient.settings.changeGlobal("vad_ppt_key", e.keyCode.toString());
settings.changeGlobal("vad_ppt_key", e.keyCode.toString());
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
tag.find(".vat_ppt_key").text(String.fromCharCode(e.keyCode));
});
@ -87,7 +87,7 @@ var Modals;
//VAD VAD
let slider = tag.find(".vad_vad_slider");
slider.on("input change", () => {
globalClient.settings.changeGlobal("vad_threshold", slider.val().toString());
settings.changeGlobal("vad_threshold", slider.val().toString());
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
if (vad instanceof VoiceActivityDetectorVAD)
vad.percentageThreshold = slider.val();

File diff suppressed because one or more lines are too long

View File

@ -38,18 +38,18 @@ namespace Modals {
}
function initialiseVoiceListeners(modal: Modal, tag: JQuery) {
let currentVAD = globalClient.settings.global("vad_type");
let currentVAD = settings.global("vad_type");
tag.find("input[type=radio][name=\"vad_type\"]").change(function (this: HTMLButtonElement) {
tag.find(".vad_settings .vad_type").text($(this).attr("display"));
tag.find(".vad_settings .vad_type_settings").hide();
tag.find(".vad_settings .vad_type_" + this.value).show();
globalClient.settings.changeGlobal("vad_type", this.value);
settings.changeGlobal("vad_type", this.value);
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
switch (this.value) {
case "ppt":
let keyCode: number = parseInt(globalClient.settings.global("vad_ppt_key", Key.T.toString()));
let keyCode: number = parseInt(settings.global("vad_ppt_key", Key.T.toString()));
tag.find(".vat_ppt_key").text(String.fromCharCode(keyCode));
break;
case "vad":
@ -86,7 +86,7 @@ namespace Modals {
$(document).one("keypress", function (e) {
console.log("Got key " + e.keyCode);
modal.close();
globalClient.settings.changeGlobal("vad_ppt_key", e.keyCode.toString());
settings.changeGlobal("vad_ppt_key", e.keyCode.toString());
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
tag.find(".vat_ppt_key").text(String.fromCharCode(e.keyCode));
});
@ -97,7 +97,7 @@ namespace Modals {
//VAD VAD
let slider = tag.find(".vad_vad_slider");
slider.on("input change", () => {
globalClient.settings.changeGlobal("vad_threshold", slider.val().toString());
settings.changeGlobal("vad_threshold", slider.val().toString());
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
if(vad instanceof VoiceActivityDetectorVAD)
vad.percentageThreshold = slider.val() as number;

View File

@ -24,7 +24,7 @@ class ServerEntry {
let tag = $.spawn("div");
tag.attr("id", "server");
tag.addClass("server");
tag.append("<div class=\"icon client-server_green\"></div>");
tag.append($.spawn("div").addClass("server_type icon client-server_green"));
tag.append("<a class='name'>" + this.properties.virtualserver_name + "</a>");
const serverIcon = $("<span/>");
//we cant spawn an icon on creation :)
@ -37,13 +37,15 @@ class ServerEntry {
this._htmlTag.click(function () {
_this.channelTree.onSelect(_this);
});
this.htmlTag.on("contextmenu", function (event) {
_this.channelTree.onSelect(_this);
event.preventDefault();
_this.spawnContextMenue(event.pageY, event.pageY, () => { _this.channelTree.onSelect(undefined); });
});
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
this.htmlTag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.spawnContextMenu(event.pageX, event.pageY, () => { _this.channelTree.onSelect(undefined); });
});
}
}
spawnContextMenue(x, y, on_close = () => { }) {
spawnContextMenu(x, y, on_close = () => { }) {
spawnMenu(x, y, {
type: MenuEntryType.ENTRY,
icon: "",
@ -52,7 +54,7 @@ class ServerEntry {
}, MenuEntry.CLOSE(on_close));
}
updateProperty(key, value) {
console.trace("Updating property " + key + " => '" + value + "' for the server");
console.log("Updating property " + key + " => '" + value + "' for the server");
this.properties[key] = value;
if (key == "virtualserver_name") {
this.htmlTag.find(".name").text(value);

View File

@ -1 +1 @@
{"version":3,"file":"server.js","sourceRoot":"","sources":["server.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"server.js","sourceRoot":"","sources":["server.ts"],"names":[],"mappings":"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"}

View File

@ -32,7 +32,7 @@ class ServerEntry {
tag.attr("id", "server");
tag.addClass("server");
tag.append("<div class=\"icon client-server_green\"></div>");
tag.append($.spawn("div").addClass("server_type icon client-server_green"));
tag.append("<a class='name'>" + this.properties.virtualserver_name + "</a>");
@ -50,14 +50,17 @@ class ServerEntry {
this._htmlTag.click(function () {
_this.channelTree.onSelect(_this);
});
this.htmlTag.on("contextmenu", function (event) {
_this.channelTree.onSelect(_this);
event.preventDefault();
_this.spawnContextMenue(event.pageY, event.pageY, () => { _this.channelTree.onSelect(undefined); });
});
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
this.htmlTag.on("contextmenu", function (event) {
event.preventDefault();
_this.channelTree.onSelect(_this);
_this.spawnContextMenu(event.pageX, event.pageY, () => { _this.channelTree.onSelect(undefined); });
});
}
}
spawnContextMenue(x: number, y: number, on_close: () => void = () => {}) {
spawnContextMenu(x: number, y: number, on_close: () => void = () => {}) {
spawnMenu(x, y, {
type: MenuEntryType.ENTRY,
icon: "",
@ -69,7 +72,7 @@ class ServerEntry {
}
updateProperty(key, value) : void {
console.trace("Updating property " + key + " => '" + value + "' for the server");
console.log("Updating property " + key + " => '" + value + "' for the server");
this.properties[key] = value;
if(key == "virtualserver_name") {
this.htmlTag.find(".name").text(value);

View File

@ -4,11 +4,34 @@
/// <reference path="../proto.ts" />
/// <reference path="channel.ts" />
/// <reference path="client.ts" />
/// <reference path="modal/ModalCreateChannel.ts" />
class ChannelTree {
constructor(client, htmlTree) {
this.client = client;
this.htmlTree = htmlTree;
this.reset();
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
let _this = this;
this.htmlTree.parent().on("contextmenu", function (event) {
if (event.isDefaultPrevented())
return;
event.preventDefault();
_this.onSelect(undefined);
_this.showContextMenu(event.pageX, event.pageY);
});
}
}
showContextMenu(x, y, on_close = undefined) {
let channelCreate = this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_TEMPORARY).granted(1) ||
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
spawnMenu(x, y, {
type: MenuEntryType.ENTRY,
icon: "client-channel_create",
name: "Create channel",
invalidPermission: !channelCreate,
callback: () => this.spawnCreateChannel()
}, MenuEntry.CLOSE(on_close));
}
initialiseHead(serverName) {
this.server = new ServerEntry(this, serverName);
@ -16,8 +39,9 @@ class ChannelTree {
this.server.initializeListener();
}
__deleteAnimation(element) {
$(this.htmlTree).find(element.htmlTag).fadeOut("slow", function () {
$(this).remove();
let tag = element instanceof ChannelEntry ? element.rootTag() : element.tag;
this.htmlTree.find(tag).fadeOut("slow", () => {
tag.remove();
if (element instanceof ChannelEntry) {
if (element.parentChannel())
element.parentChannel().adjustSize(true);
@ -27,6 +51,9 @@ class ChannelTree {
}
});
}
rootChannel() {
return this.channels.filter(e => e.parent == undefined);
}
deleteChannel(channel) {
const _this = this;
for (let index = 0; index < this.channels.length; index++) {
@ -58,19 +85,19 @@ class ChannelTree {
let parent = channel.parentChannel();
let siblings = parent.siblings();
if (siblings.length == 0) {
elm = parent.htmlTag;
elm = parent.rootTag();
prevChannel = null;
}
else {
prevChannel = siblings.last();
elm = prevChannel.htmlTag;
elm = prevChannel.tag;
}
tag = parent.siblingTag();
}
channel.prevChannel = prevChannel;
let entry = channel.htmlTag.css({ display: "none" }).fadeIn("slow");
let entry = channel.rootTag().css({ display: "none" }).fadeIn("slow");
entry.appendTo(tag);
channel.originalHeight = entry.outerHeight(true);
channel.originalHeight = entry.outerHeight(false);
if (elm != undefined)
elm.after(entry);
channel.adjustSize(true);
@ -91,21 +118,21 @@ class ChannelTree {
channel.prevChannel = prevChannel;
channel.parent = parent;
if (prevChannel)
prevChannel.htmlTag.after(channel.htmlTag);
prevChannel.rootTag().after(channel.rootTag());
else {
if (parent) {
var siblings = parent.siblings();
let siblings = parent.siblings();
if (siblings.length <= 1) {
var left = channel.htmlTag;
let left = channel.rootTag();
left.appendTo($(parent.siblingTag()));
}
else {
channel.prevChannel = siblings[siblings.length - 2];
channel.prevChannel.htmlTag.after(channel.htmlTag);
channel.prevChannel.rootTag().after(channel.rootTag());
}
}
else
this.htmlTree.find(".server").after(channel.htmlTag);
this.htmlTree.find(".server").after(channel.rootTag());
}
if (oldParent)
oldParent.adjustSize();
@ -125,10 +152,11 @@ class ChannelTree {
this.clients.push(client);
client.channelTree = this;
client["_channel"] = channel;
let tag = client.htmlTag.css({ display: "none" }).fadeIn("slow");
let tag = client.tag.css({ display: "none" }).fadeIn("slow");
tag.appendTo(channel.clientTag());
channel.adjustSize(true);
client.initializeListener();
channel.updateChannelTypeIcon();
return client;
}
registerClient(client) {
@ -139,13 +167,17 @@ class ChannelTree {
moveClient(client, channel) {
let oldChannel = client.currentChannel();
client["_channel"] = channel;
let tag = client.htmlTag;
let tag = client.tag;
tag.detach();
tag.appendTo(client.currentChannel().clientTag());
if (oldChannel)
if (oldChannel) {
oldChannel.adjustSize();
if (client.currentChannel())
oldChannel.updateChannelTypeIcon();
}
if (client.currentChannel()) {
client.currentChannel().adjustSize();
client.currentChannel().updateChannelTypeIcon();
}
}
findClient(clientId) {
for (let index = 0; index < this.clients.length; index++)
@ -154,13 +186,13 @@ class ChannelTree {
return null;
}
onSelect(entry) {
$(this.htmlTree).find(".selected").each(function (idx, e) {
this.htmlTree.find(".selected").each(function (idx, e) {
$(e).removeClass("selected");
});
if (entry instanceof ChannelEntry)
entry.htmlTag.find("> .channelLine").addClass("selected");
entry.rootTag().find("> .channelLine").addClass("selected");
else if (entry instanceof ClientEntry)
entry.htmlTag.addClass("selected");
entry.tag.addClass("selected");
else if (entry instanceof ServerEntry)
entry.htmlTag.addClass("selected");
this.client.selectInfo.currentSelected = entry;
@ -187,5 +219,14 @@ class ChannelTree {
this.channels = [];
this.htmlTree.empty();
}
spawnCreateChannel(parent) {
Modals.createChannelModal(undefined, parent, (properties) => {
if (!properties)
return;
properties["cpid"] = parent ? parent.channelId : 0;
log.debug(LogCategory.CHANNEL, "Creating new channel with properties: %o", properties);
this.client.serverConnection.sendCommand("channelcreate", properties);
});
}
}
//# sourceMappingURL=view.js.map

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@
/// <reference path="../proto.ts" />
/// <reference path="channel.ts" />
/// <reference path="client.ts" />
/// <reference path="modal/ModalCreateChannel.ts" />
class ChannelTree {
client: TSClient;
@ -16,6 +17,35 @@ class ChannelTree {
this.client = client;
this.htmlTree = htmlTree;
this.reset();
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
let _this = this;
this.htmlTree.parent().on("contextmenu", function (event) {
if(event.isDefaultPrevented()) return;
event.preventDefault();
_this.onSelect(undefined);
_this.showContextMenu(event.pageX, event.pageY);
});
}
}
showContextMenu(x: number, y: number, on_close: () => void = undefined) {
let channelCreate =
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_TEMPORARY).granted(1) ||
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
spawnMenu(x, y,
{
type: MenuEntryType.ENTRY,
icon: "client-channel_create",
name: "Create channel",
invalidPermission: !channelCreate,
callback: () => this.spawnCreateChannel()
},
MenuEntry.CLOSE(on_close)
);
}
initialiseHead(serverName: string) {
@ -25,8 +55,9 @@ class ChannelTree {
}
private __deleteAnimation(element: ChannelEntry | ClientEntry) {
$(this.htmlTree).find(element.htmlTag).fadeOut("slow", function () {
$(this).remove();
let tag = element instanceof ChannelEntry ? element.rootTag() : element.tag;
this.htmlTree.find(tag).fadeOut("slow", () => {
tag.remove();
if(element instanceof ChannelEntry) {
if(element.parentChannel())
element.parentChannel().adjustSize(true);
@ -36,6 +67,10 @@ class ChannelTree {
});
}
rootChannel() : ChannelEntry[] {
return this.channels.filter(e => e.parent == undefined);
}
deleteChannel(channel: ChannelEntry) {
const _this = this;
for(let index = 0; index < this.channels.length; index++) {
@ -68,19 +103,19 @@ class ChannelTree {
let parent = channel.parentChannel();
let siblings = parent.siblings();
if(siblings.length == 0) {
elm = parent.htmlTag;
elm = parent.rootTag();
prevChannel = null;
} else {
prevChannel = siblings.last();
elm = prevChannel.htmlTag;
elm = prevChannel.tag;
}
tag = parent.siblingTag();
}
channel.prevChannel = prevChannel;
let entry = channel.htmlTag.css({display: "none"}).fadeIn("slow");
let entry = channel.rootTag().css({display: "none"}).fadeIn("slow");
entry.appendTo(tag);
channel.originalHeight = entry.outerHeight(true);
channel.originalHeight = entry.outerHeight(false);
if(elm != undefined)
elm.after(entry);
@ -104,19 +139,19 @@ class ChannelTree {
channel.parent = parent;
if(prevChannel)
prevChannel.htmlTag.after(channel.htmlTag);
prevChannel.rootTag().after(channel.rootTag());
else {
if(parent) {
var siblings = parent.siblings();
let siblings = parent.siblings();
if(siblings.length <= 1) { //Self should be already in there
var left = channel.htmlTag;
let left = channel.rootTag();
left.appendTo($(parent.siblingTag()));
} else {
channel.prevChannel = siblings[siblings.length - 2];
channel.prevChannel.htmlTag.after(channel.htmlTag);
channel.prevChannel.rootTag().after(channel.rootTag());
}
} else
this.htmlTree.find(".server").after(channel.htmlTag);
this.htmlTree.find(".server").after(channel.rootTag());
}
@ -138,11 +173,12 @@ class ChannelTree {
client.channelTree = this;
client["_channel"] = channel;
let tag = client.htmlTag.css({display: "none"}).fadeIn("slow");
let tag = client.tag.css({display: "none"}).fadeIn("slow");
tag.appendTo(channel.clientTag());
channel.adjustSize(true);
client.initializeListener();
channel.updateChannelTypeIcon();
return client;
}
@ -156,11 +192,17 @@ class ChannelTree {
let oldChannel = client.currentChannel();
client["_channel"] = channel;
let tag = client.htmlTag;
let tag = client.tag;
tag.detach();
tag.appendTo(client.currentChannel().clientTag());
if(oldChannel) oldChannel.adjustSize();
if(client.currentChannel()) client.currentChannel().adjustSize();
if(oldChannel) {
oldChannel.adjustSize();
oldChannel.updateChannelTypeIcon();
}
if(client.currentChannel()) {
client.currentChannel().adjustSize();
client.currentChannel().updateChannelTypeIcon();
}
}
findClient(clientId) : ClientEntry {
@ -170,14 +212,14 @@ class ChannelTree {
}
onSelect(entry?: ChannelEntry | ClientEntry | ServerEntry) {
$(this.htmlTree).find(".selected").each(function (idx, e) {
this.htmlTree.find(".selected").each(function (idx, e) {
$(e).removeClass("selected");
});
if(entry instanceof ChannelEntry)
(entry as ChannelEntry).htmlTag.find("> .channelLine").addClass("selected");
(entry as ChannelEntry).rootTag().find("> .channelLine").addClass("selected");
else if(entry instanceof ClientEntry)
(entry as ClientEntry).htmlTag.addClass("selected");
(entry as ClientEntry).tag.addClass("selected");
else if(entry instanceof ServerEntry)
(entry as ServerEntry).htmlTag.addClass("selected");
this.client.selectInfo.currentSelected = entry;
@ -211,4 +253,13 @@ class ChannelTree {
this.channels = [];
this.htmlTree.empty();
}
spawnCreateChannel(parent?: ChannelEntry) {
Modals.createChannelModal(undefined, parent, (properties?: ChannelProperties) => {
if(!properties) return;
properties["cpid"] = parent ? parent.channelId : 0;
log.debug(LogCategory.CHANNEL, "Creating new channel with properties: %o", properties);
this.client.serverConnection.sendCommand("channelcreate", properties);
});
}
}

11
js/utils/helpers.ts Normal file
View File

@ -0,0 +1,11 @@
/// <reference path="../crypto/sha.ts" />
namespace helpers {
export function hashPassword(password: string) : Promise<string> {
return new Promise<string>((resolve, reject) => {
sha.sha1(password).then(result => {
resolve(btoa(String.fromCharCode.apply(null, new Uint8Array(result))));
});
});
}
}

View File

@ -67,9 +67,12 @@ class Modal {
constructor(props) {
this.properties = props;
}
get htmlTag() {
if (!this._htmlTag)
this._create();
return this._htmlTag;
}
_create() {
if (this.htmlTag)
return;
let modal = $.spawn("div");
modal.addClass("modal");
let content = $.spawn("div");
@ -88,10 +91,9 @@ class Modal {
if (this.properties.closeable)
this.close();
}.bind(this));
this.htmlTag = modal;
this._htmlTag = modal;
}
open() {
this._create();
this.htmlTag.appendTo($("body"));
this.htmlTag.show();
}
@ -117,10 +119,9 @@ function createInputModal(headMessage, question, validator, callback, props = {}
let body = $.spawn("div");
ModalFunctions.divify(ModalFunctions.jqueriefy(question)).appendTo(body);
let input = $.spawn("input");
input.width("100%");
if (props.maxLength)
input.attr("maxlength", props.maxLength);
input.css("width", "100%");
input.appendTo(body);
console.log(input);
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");

File diff suppressed because one or more lines are too long

View File

@ -66,15 +66,19 @@ class ModalProperties {
}
class Modal {
htmlTag: JQuery;
private _htmlTag: JQuery;
properties: ModalProperties;
constructor(props: ModalProperties) {
this.properties = props;
}
get htmlTag() : JQuery {
if(!this._htmlTag) this._create();
return this._htmlTag;
}
private _create() {
if(this.htmlTag) return;
let modal = $.spawn("div");
modal.addClass("modal");
@ -99,11 +103,10 @@ class Modal {
this.close();
}.bind(this));
this.htmlTag = modal;
this._htmlTag = modal;
}
open() {
this._create();
this.htmlTag.appendTo($("body"));
this.htmlTag.show();
}
@ -137,10 +140,9 @@ function createInputModal(headMessage: BodyCreator, question: BodyCreator, valid
let body = $.spawn("div");
ModalFunctions.divify(ModalFunctions.jqueriefy(question)).appendTo(body);
let input = $.spawn("input");
input.width("100%");
if(props.maxLength)
input.attr("maxlength", props.maxLength);
input.css("width", "100%");
input.appendTo(body);
console.log(input);
let footer = $.spawn("div");
footer.addClass("modal-button-group");

View File

@ -1,15 +1,20 @@
class X_Tab extends HTMLElement {
if (typeof (customElements) !== "undefined") {
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' });
}
class X_Entry extends HTMLElement {
else {
console.warn("Could not defied tab customElements!");
}
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' });
var TabFunctions = {
tabify(template) {
console.log("Tabify:");

View File

@ -1 +1 @@
{"version":3,"file":"tab.js","sourceRoot":"","sources":["tab.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"tab.js","sourceRoot":"","sources":["tab.ts"],"names":[],"mappings":"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"}

View File

@ -6,15 +6,20 @@ interface JQuery {
changeElementType(type: string) : JQuery;
}
class X_Tab extends HTMLElement {}
class X_Entry extends HTMLElement {}
class X_Tag extends HTMLElement {}
class X_Content extends HTMLElement {}
if(typeof (customElements) !== "undefined") {
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' });
} else {
console.warn("Could not defied tab customElements!");
}
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' });
var TabFunctions = {
tabify(template: JQuery) : JQuery {
console.log("Tabify:");

View File

@ -11,6 +11,13 @@ class CodecPool {
this.handle = handle;
this.codecIndex = index;
}
initialize(cached) {
for (let i = 0; i < cached; i++)
this.ownCodec(i);
for (let i = 0; i < cached; i++)
this.releaseCodec(i);
}
supported() { return this.creator != undefined; }
ownCodec(clientId, create = true) {
if (!this.creator)
return null;
@ -64,6 +71,11 @@ class VoiceConnection {
this.voiceRecorder.on_data = this.handleVoiceData.bind(this);
this.voiceRecorder.on_end = this.handleVoiceEnded.bind(this);
this.voiceRecorder.reinitialiseVAD();
this.codecPool[4].initialize(2);
this.codecPool[5].initialize(2);
}
codecSupported(type) {
return this.codecPool.length > type && this.codecPool[type].supported();
}
sendVoicePacket(data, codec) {
if (this.dataChannel) {

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,15 @@ class CodecPool {
entries: CodecPoolEntry[] = [];
maxInstances: number = 2;
initialize(cached: number) {
for(let i = 0; i < cached; i++)
this.ownCodec(i);
for(let i = 0; i < cached; i++)
this.releaseCodec(i);
}
supported() { return this.creator != undefined; }
ownCodec?(clientId: number, create: boolean = true) : BasicCodec {
if(!this.creator) return null;
@ -72,6 +81,7 @@ class VoiceConnection {
new CodecPool(this,3,undefined), //CELT Mono
new CodecPool(this,4,() => { return new CodecWrapper(CodecWorkerType.WORKER_OPUS, 1) }), //opus voice
new CodecPool(this,5,() => { return new CodecWrapper(CodecWorkerType.WORKER_OPUS, 2) }) //opus music
//FIXME Why is it at index 5 currently only 1?
];
@ -84,6 +94,13 @@ class VoiceConnection {
this.voiceRecorder.on_data = this.handleVoiceData.bind(this);
this.voiceRecorder.on_end = this.handleVoiceEnded.bind(this);
this.voiceRecorder.reinitialiseVAD();
this.codecPool[4].initialize(2);
this.codecPool[5].initialize(2);
}
codecSupported(type: number) : boolean {
return this.codecPool.length > type && this.codecPool[type].supported();
}
sendVoicePacket(data: Uint8Array, codec: number) {

View File

@ -21,7 +21,7 @@ class VoiceRecorder {
this._chunkCount = 0;
this.handle = handle;
this.userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
this._deviceId = handle.client.settings.global("microphone_id", "default");
this._deviceId = settings.global("microphone_id", "default");
this.audioContext = AudioController.globalContext;
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
this.processor.addEventListener('audioprocess', ev => {
@ -57,9 +57,9 @@ class VoiceRecorder {
return this.microphoneStream;
}
reinitialiseVAD() {
let type = this.handle.client.settings.global("vad_type", "vad");
let type = settings.global("vad_type", "vad");
if (type == "ppt") {
let keyCode = parseInt(this.handle.client.settings.global("vad_ppt_key", 84 /* T */.toString()));
let keyCode = parseInt(settings.global("vad_ppt_key", 84 /* T */.toString()));
if (!(this.getVADHandler() instanceof PushToTalkVAD))
this.setVADHander(new PushToTalkVAD(keyCode));
else
@ -72,7 +72,7 @@ class VoiceRecorder {
else if (type == "vad") {
if (!(this.getVADHandler() instanceof VoiceActivityDetectorVAD))
this.setVADHander(new VoiceActivityDetectorVAD());
let threshold = parseInt(this.handle.client.settings.global("vad_threshold", "50"));
let threshold = parseInt(settings.global("vad_threshold", "50"));
this.getVADHandler().percentageThreshold = threshold;
}
else {
@ -104,7 +104,7 @@ class VoiceRecorder {
if (this._deviceId == device)
return;
this._deviceId = device;
this.handle.client.settings.changeGlobal("microphone_id", device);
settings.changeGlobal("microphone_id", device);
if (this._recording) {
this.stop();
this.start(device);

File diff suppressed because one or more lines are too long

View File

@ -45,7 +45,7 @@ class VoiceRecorder {
this.handle = handle;
this.userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
this._deviceId = handle.client.settings.global("microphone_id", "default");
this._deviceId = settings.global("microphone_id", "default");
this.audioContext = AudioController.globalContext;
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
@ -91,9 +91,9 @@ class VoiceRecorder {
}
reinitialiseVAD() {
let type = this.handle.client.settings.global("vad_type", "vad");
let type = settings.global("vad_type", "vad");
if(type == "ppt") {
let keyCode: number = parseInt(this.handle.client.settings.global("vad_ppt_key", Key.T.toString()));
let keyCode: number = parseInt(settings.global("vad_ppt_key", Key.T.toString()));
if(!(this.getVADHandler() instanceof PushToTalkVAD))
this.setVADHander(new PushToTalkVAD(keyCode));
else (this.getVADHandler() as PushToTalkVAD).key = keyCode;
@ -103,7 +103,7 @@ class VoiceRecorder {
} else if(type == "vad") {
if(!(this.getVADHandler() instanceof VoiceActivityDetectorVAD))
this.setVADHander(new VoiceActivityDetectorVAD());
let threshold = parseInt(this.handle.client.settings.global("vad_threshold", "50"));
let threshold = parseInt(settings.global("vad_threshold", "50"));
(this.getVADHandler() as VoiceActivityDetectorVAD).percentageThreshold = threshold;
} else {
console.warn("Invalid VAD handler! (" + type + ")");
@ -134,7 +134,7 @@ class VoiceRecorder {
changeDevice(device: string) {
if(this._deviceId == device) return;
this._deviceId = device;
this.handle.client.settings.changeGlobal("microphone_id", device);
settings.changeGlobal("microphone_id", device);
if(this._recording) {
this.stop();
this.start(device);

View File

@ -18,6 +18,7 @@
"dependencies": {
"@types/emscripten": "0.0.31",
"@types/jquery": "^3.3.0",
"@types/text-encoding": "0.0.32",
"@types/websocket": "0.0.38"
}
}

3
public_files.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
tsc -p tsconfig/tsconfig_release.json
uglifyjs -c --source-map --verbose -o generated/js/client.min.js generated/js/client.js

View File

@ -15,35 +15,40 @@
<body>
<!-- Template for chennel create & edit-->
<template id="tmpl_channel_edit">
<table style="margin-bottom: 20px">
<tr>
<td>Name:</td>
<td><input value="${channel_name}"/></td>
</tr>
<tr>
<td>Password:</td>
<td><input/></td>
</tr>
<tr>
<td>Topic:</td>
<td><input/></td>
</tr>
<tr>
<td>Description:</td>
<td><input/></td>
</tr>
</table>
<div class="align_column channel_general_properties">
<div class="align_row property_entry">
<a class="key">Name:</a>
<input class="value channel_name" value="${channel_name}"/>
</div>
<div class="align_row property_entry">
<a class="key">Password:</a>
{{if channel_flag_password == "1"}}
<input class="value channel_password" type="password" value="WolverinDEV">
{{else}}
<input class="value channel_password" type="password">
{{/if}}
</div>
<div class="align_row property_entry">
<a class="key">Topic:</a>
<input class="value channel_topic" value="${channel_topic}"/>
</div>
<div class="align_row property_entry">
<a class="key">Description:</a>
<textarea class="value channel_description" style="height: 150px; resize: none">${channel_description}</textarea>
</div>
</div>
<div style="margin-bottom: 5px"></div>
<x-tab>
<x-entry>
<x-tag>Standard</x-tag>
<x-content>
<div style="display: flex; flex-direction: row; width: 100%; justify-content: space-evenly">
<div class="settings_standard" style="display: flex; flex-direction: row; width: 100%; justify-content: space-evenly">
<div style="vertical-align: center; margin: 20px;">
<a>Channel Type</a><br>
<fieldset style="border: gray solid; border-width: 2px; border-radius: 0px 6px 6px 6px;">
<div><input type="radio" name="channel_type" id="temp" value="temp" checked> Temporary</div>
<div><input type="radio" name="channel_type" id="semi" value="semiperm"> Semi-Permanent</div>
<div><input type="radio" name="channel_type" id="perm" value="perm"> Permanent</div>
<div><input type="radio" name="channel_type" value="temp"> Temporary</div>
<div><input type="radio" name="channel_type" value="semi"> Semi-Permanent</div>
<div><input type="radio" name="channel_type" value="perm"> Permanent</div>
<hr style="width: 100%;">
<div><input type="checkbox" name="channel_default" id="default" value="def"> Default Channel</div>
</fieldset>
@ -53,12 +58,11 @@
<div>
<div>Sort this channel after:</div>
<select class="order_id" style="width: 150px">
<option value="channel_3">Audi</option>
</select>
</div>
<div style="margin-top: 20px">
<div>Needed Talk Power:</div>
<input type="number" min="0" value="0" style="width: 150px">
<input type="number" min="0" value="0" name="talk_power" style="width: 150px">
</div>
</div>
</div>
@ -71,28 +75,31 @@
<x-entry>
<x-tag>Permissions</x-tag>
<x-content>
<!--
<div style="display: flex; justify-content: space-evenly">
<div>
Regular needed powers:
<table class="channel_perm_tbl">
<tr><td class="key">Join:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Subscribe:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Desc. view:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Modify:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Delete:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Join:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Subscribe:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Desc. view:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Modify:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Delete:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
</table>
</div>
<div>
File transfare needed powers:
<table class="channel_perm_tbl">
<tr><td class="key">Join:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Subscribe:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Desc. view:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Modify:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Delete:</td><td><input type="number" min="0" value="0"></td></tr>
<tr><td class="key">Join:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Subscribe:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Desc. view:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Modify:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
<tr><td class="key">Delete:</td><td><input type="number" min="0" value="0" class="value"></td></tr>
</table>
</div>
</div>
-->
TODO Implement!
</x-content>
</x-entry>
<x-entry>
@ -113,7 +120,9 @@
</div>
<div style="width: 20%">
<div>Server password:</div>
<input type="password" style="width: 100%" class="connect_password">
<form name="server_password_form" onsubmit="return false;">
<input type="password" autocomplete="off" style="width: 100%" class="connect_password">
</form>
</div>
</div>
<div>
@ -141,9 +150,7 @@
You're using your forum account as verification
</div>
<div style="background-color: red; border-radius: 1px; display: none" class="error_message">
Identity isnt valid!
</div>
<div style="background-color: red; border-radius: 1px; display: none" class="error_message"></div>
</div>
</div>
</template>

View File

@ -1,4 +1,11 @@
{
"extends": "./tsconfig/tsconfig_debug.json"
//"extends": "./tsconfig/tsconfig_release.json"
"compilerOptions": {
"module": "none",
"target": "es6",
"sourceMap": true
},
"exclude": [
"node_modules",
"js/codec/workers"
]
}