Added 2 new features

canary
WolverinDEV 2018-12-02 14:12:23 +01:00
parent 05642f3fbe
commit bbdae986b8
6 changed files with 269 additions and 39 deletions

View File

@ -1,4 +1,12 @@
# Changelog: # Changelog:
* **2.12.18**
- Fixed `[spacerX]` detection
- Added a hint if the channel encryption has been overridden by the server settings
- Enabled log grouping
* **1.12.18**
- Added the possibility to navigate via arrow keys within the channel tree
* **25.11.18** * **25.11.18**
- Implemented support for svg and image detection - Implemented support for svg and image detection
- Fixed keeped host banner - Fixed keeped host banner

View File

@ -1510,6 +1510,13 @@
{{else}} {{else}}
Encrypted Encrypted
{{/if}} {{/if}}
{{if server_encryption == 2}}
(Overridden by the server with Encrypted)
{{/if}}
{{if server_encryption == 1}}
(Overridden by the server with Unencrypted)
{{/if}}
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -106,7 +106,7 @@ namespace log {
} }
log(message: string, ...optionalParams: any[]) : this { log(message: string, ...optionalParams: any[]) : this {
if(!this.initialized && false) { if(!this.initialized) {
if(this._collapsed && console.groupCollapsed) if(this._collapsed && console.groupCollapsed)
console.groupCollapsed(this.name, ...this.optionalParams); console.groupCollapsed(this.name, ...this.optionalParams);
else else

View File

@ -50,10 +50,12 @@ class ChannelEntry {
channelTree: ChannelTree; channelTree: ChannelTree;
channelId: number; channelId: number;
parent?: ChannelEntry; parent?: ChannelEntry;
prevChannel?: ChannelEntry;
properties: ChannelProperties = new ChannelProperties(); properties: ChannelProperties = new ChannelProperties();
originalHeight: number; originalHeight: number;
channel_previous?: ChannelEntry;
channel_next?: ChannelEntry;
private _channelAlign: string; private _channelAlign: string;
private _formatedChannelName: string; private _formatedChannelName: string;
private _family_index: number = 0; private _family_index: number = 0;
@ -70,12 +72,11 @@ class ChannelEntry {
private _cached_channel_description_promise_resolve: any = undefined; private _cached_channel_description_promise_resolve: any = undefined;
private _cached_channel_description_promise_reject: any = undefined; private _cached_channel_description_promise_reject: any = undefined;
constructor(channelId, channelName, parent = null, prevChannel = null) { constructor(channelId, channelName, parent = null) {
this.properties = new ChannelProperties(); this.properties = new ChannelProperties();
this.channelId = channelId; this.channelId = channelId;
this._formatedChannelName = channelName; this._formatedChannelName = channelName;
this.parent = parent; this.parent = parent;
this.prevChannel = prevChannel;
this.channelTree = null; this.channelTree = null;
this.initializeTag(); this.initializeTag();
@ -87,7 +88,7 @@ class ChannelEntry {
} }
formatedChannelName() { formatedChannelName() {
return this._formatedChannelName ? this._formatedChannelName : this.properties.channel_name; return this._formatedChannelName !== undefined ? this._formatedChannelName : this.properties.channel_name;
} }
getChannelDescription() : Promise<string> { getChannelDescription() : Promise<string> {
@ -104,7 +105,7 @@ class ChannelEntry {
}); });
} }
parentChannel() { return this.parent; } parent_channel?() { return this.parent; }
hasParent(){ return this.parent != null; } hasParent(){ return this.parent != null; }
getChannelId(){ return this.channelId; } getChannelId(){ return this.channelId; }
channelClass() { return "channel_full"; } channelClass() { return "channel_full"; }
@ -118,14 +119,14 @@ class ChannelEntry {
let current = entry; let current = entry;
if(deep) { if(deep) {
while(current) { while(current) {
if(current.parentChannel() == self) { if(current.parent_channel() == self) {
result.push(entry); result.push(entry);
break; break;
} }
current = current.parentChannel(); current = current.parent_channel();
} }
} else } else
if(current.parentChannel() == self) if(current.parent_channel() == self)
result.push(entry); result.push(entry);
}); });
return result; return result;
@ -140,11 +141,11 @@ class ChannelEntry {
let current = entry.currentChannel(); let current = entry.currentChannel();
if(deep) { if(deep) {
while(current) { while(current) {
if(current.parentChannel() == self) { if(current.parent_channel() == self) {
result.push(entry); result.push(entry);
break; break;
} }
current = current.parentChannel(); current = current.parent_channel();
} }
} else } else
if(current == self) if(current == self)
@ -153,6 +154,25 @@ class ChannelEntry {
return result; return result;
} }
clients_ordered() : ClientEntry[] {
const clients = this.clients(false);
clients.sort((a, b) => {
if(a.properties.client_talk_power < b.properties.client_talk_power)
return 1;
if(a.properties.client_talk_power > b.properties.client_talk_power)
return -1;
if(a.properties.client_nickname > b.properties.client_nickname)
return 1;
if(a.properties.client_nickname < b.properties.client_nickname)
return -1;
return 0;
});
return clients;
}
private initializeTag() { private initializeTag() {
let rootTag = $.spawn("div"); let rootTag = $.spawn("div");
@ -285,7 +305,7 @@ class ChannelEntry {
this._tag_root.css({height: size + subSize + clientSize}); this._tag_root.css({height: size + subSize + clientSize});
this._tag_siblings.css("margin-top", (clientSize + 16) + "px"); this._tag_siblings.css("margin-top", (clientSize + 16) + "px");
this._tag_clients.css({height: clientSize}); this._tag_clients.css({height: clientSize});
if(parent && this.parentChannel()) this.parentChannel().adjustSize(parent); if(parent && this.parent_channel()) this.parent_channel().adjustSize(parent);
} }
initializeListener() { initializeListener() {
@ -445,7 +465,7 @@ class ChannelEntry {
private __updateChannelName() { private __updateChannelName() {
this._formatedChannelName = undefined; this._formatedChannelName = undefined;
parseType: parseType:
if(this.parentChannel() == null && this.properties.channel_name.charAt(0) == '[') { if(this.parent_channel() == null && this.properties.channel_name.charAt(0) == '[') {
let end = this.properties.channel_name.indexOf(']'); let end = this.properties.channel_name.indexOf(']');
if(end == -1) break parseType; if(end == -1) break parseType;
@ -469,9 +489,9 @@ class ChannelEntry {
let channelName = self.find(".channel_name"); let channelName = self.find(".channel_name");
channelName.text(this.formatedChannelName()); channelName.text(this.formatedChannelName());
channelName.parent().removeClass("l r c *"); //Alignments channelName.parent().removeClass("l r c *"); //Alignments
(this._formatedChannelName ? $.fn.hide : $.fn.show).apply(self.find(".channel_only_normal")); (this._formatedChannelName !== undefined ? $.fn.hide : $.fn.show).apply(self.find(".channel_only_normal"));
if(this._formatedChannelName) { if(this._formatedChannelName !== undefined) {
channelName.parent().addClass(this._channelAlign); channelName.parent().addClass(this._channelAlign);
if(this._channelAlign == "*") { if(this._channelAlign == "*") {

View File

@ -308,6 +308,7 @@ class ChannelInfoManager extends InfoManager<ChannelEntry> {
properties["channel_type"] = ChannelType.normalize(channel.channelType()); properties["channel_type"] = ChannelType.normalize(channel.channelType());
properties["channel_clients"] = channel.channelTree.clientsByChannel(channel).length; properties["channel_clients"] = channel.channelTree.clientsByChannel(channel).length;
properties["channel_subscribed"] = true; //TODO properties["channel_subscribed"] = true; //TODO
properties["server_encryption"] = channel.channelTree.server.properties.virtualserver_codec_encryption_mode;
for(let key in channel.properties) for(let key in channel.properties)
properties["property_" + key] = channel.properties[key]; properties["property_" + key] = channel.properties[key];

View File

@ -6,6 +6,7 @@
/// <reference path="client.ts" /> /// <reference path="client.ts" />
/// <reference path="modal/ModalCreateChannel.ts" /> /// <reference path="modal/ModalCreateChannel.ts" />
class ChannelTree { class ChannelTree {
client: TSClient; client: TSClient;
htmlTree: JQuery; htmlTree: JQuery;
@ -17,6 +18,11 @@ class ChannelTree {
currently_selected_context_callback: (event) => any = undefined; currently_selected_context_callback: (event) => any = undefined;
readonly client_mover: ClientMover; readonly client_mover: ClientMover;
private channel_last?: ChannelEntry;
private channel_first?: ChannelEntry;
private selected_event?: Event;
constructor(client, htmlTree) { constructor(client, htmlTree) {
document.addEventListener("touchstart", function(){}, true); document.addEventListener("touchstart", function(){}, true);
@ -44,6 +50,16 @@ class ChannelTree {
} }
this.htmlTree.on('resize', this.handle_resized.bind(this)); this.htmlTree.on('resize', this.handle_resized.bind(this));
/* TODO release these events again when ChannelTree get deinitialized */
$(document).on('click', event => {
if(this.selected_event != event.originalEvent)
this.selected_event = undefined;
});
$(document).on('keydown', this.handle_key_press.bind(this));
this.htmlTree.on('click', event => {{
this.selected_event = event.originalEvent;
}});
} }
showContextMenu(x: number, y: number, on_close: () => void = undefined) { showContextMenu(x: number, y: number, on_close: () => void = undefined) {
@ -75,8 +91,8 @@ class ChannelTree {
this.htmlTree.find(tag).fadeOut("slow", () => { this.htmlTree.find(tag).fadeOut("slow", () => {
tag.remove(); tag.remove();
if(element instanceof ChannelEntry) { if(element instanceof ChannelEntry) {
if(element.parentChannel()) if(element.parent_channel())
element.parentChannel().adjustSize(true); element.parent_channel().adjustSize(true);
} else if(element instanceof ClientEntry) { } else if(element instanceof ClientEntry) {
element.currentChannel().adjustSize(true); element.currentChannel().adjustSize(true);
} }
@ -99,13 +115,25 @@ class ChannelTree {
entry.channelTree = null; entry.channelTree = null;
index--; index--;
break; break;
} else currentEntry = currentEntry.parentChannel(); } else currentEntry = currentEntry.parent_channel();
} }
} }
this.channels.remove(channel); this.channels.remove(channel);
this.__deleteAnimation(channel); this.__deleteAnimation(channel);
channel.channelTree = null; channel.channelTree = null;
if(channel.channel_previous)
channel.channel_previous.channel_next = channel.channel_next;
if(channel.channel_next)
channel.channel_next.channel_previous = channel.channel_previous;
if(channel == this.channel_first)
this.channel_first = channel.channel_next;
if(channel == this.channel_last)
this.channel_last = channel.channel_previous;
} }
insertChannel(channel: ChannelEntry) { insertChannel(channel: ChannelEntry) {
@ -114,29 +142,53 @@ class ChannelTree {
let elm = undefined; let elm = undefined;
let tag = this.htmlTree; let tag = this.htmlTree;
let prevChannel = null;
let previous_channel = null;
if(channel.hasParent()) { if(channel.hasParent()) {
let parent = channel.parentChannel(); let parent = channel.parent_channel();
let siblings = parent.siblings(); let siblings = parent.siblings();
if(siblings.length == 0) { if(siblings.length == 0) {
elm = parent.rootTag(); elm = parent.rootTag();
prevChannel = null; previous_channel = null;
} else { } else {
prevChannel = siblings.last(); previous_channel = siblings.last();
elm = prevChannel.tag; elm = previous_channel.tag;
} }
tag = parent.siblingTag(); tag = parent.siblingTag();
} } else {
channel.prevChannel = prevChannel; previous_channel = this.channel_last;
let entry = channel.rootTag().css({display: "none"}).fadeIn("slow");
if(!this.channel_last)
this.channel_last = channel;
if(!this.channel_first)
this.channel_first = channel;
}
channel.channel_previous = previous_channel;
channel.channel_next = undefined;
if(previous_channel) {
channel.channel_next = previous_channel.channel_next;
previous_channel.channel_next = channel;
if(channel.channel_next)
channel.channel_next.channel_previous = channel;
}
let entry = channel.rootTag().css({display: "none"}).fadeIn("slow");
entry.appendTo(tag); entry.appendTo(tag);
channel.originalHeight = entry.outerHeight(false); channel.originalHeight = entry.outerHeight(false);
if(elm != undefined) if(elm != undefined)
elm.after(entry); elm.after(entry);
channel.adjustSize(true); if(channel.channel_previous == channel) /* shall never happen */
channel.channel_previous = undefined;
if(channel.channel_next == channel) /* shall never happen */
channel.channel_next = undefined;
channel.adjustSize(true);
channel.initializeListener(); channel.initializeListener();
} }
@ -153,31 +205,71 @@ class ChannelTree {
return undefined; return undefined;
} }
moveChannel(channel: ChannelEntry, prevChannel: ChannelEntry, parent: ChannelEntry) { moveChannel(channel: ChannelEntry, channel_previus: ChannelEntry, parent: ChannelEntry) {
if(prevChannel != null && prevChannel.parent != parent) { if(channel_previus != null && channel_previus.parent != parent) {
console.error("Invalid channel move (different parents! (" + prevChannel.parent + "|" + parent + ")"); console.error("Invalid channel move (different parents! (" + channel_previus.parent + "|" + parent + ")");
return; return;
} }
let oldParent = channel.parentChannel();
channel.prevChannel = prevChannel; if(channel.channel_next)
channel.channel_next.channel_previous = channel.channel_previous;
if(channel.channel_previous)
channel.channel_previous.channel_next = channel.channel_next;
if(channel == this.channel_last)
this.channel_last = channel.channel_previous;
if(channel == this.channel_first)
this.channel_first = channel.channel_next;
let oldParent = channel.parent_channel();
channel.channel_next = undefined;
channel.channel_previous = channel_previus;
channel.parent = parent; channel.parent = parent;
if(prevChannel) if(channel_previus) {
prevChannel.rootTag().after(channel.rootTag()); if(channel_previus == this.channel_last)
else { this.channel_last = channel;
channel.channel_next = channel_previus.channel_next;
channel_previus.channel_next = channel;
channel_previus.rootTag().after(channel.rootTag());
if(channel.channel_next)
channel.channel_next.channel_previous = channel;
} else {
if(parent) { if(parent) {
let siblings = parent.siblings(); let siblings = parent.siblings();
if(siblings.length <= 1) { //Self should be already in there if(siblings.length <= 1) { //Self should be already in there
let left = channel.rootTag(); let left = channel.rootTag();
left.appendTo($(parent.siblingTag())); left.appendTo(parent.siblingTag());
channel.channel_next = undefined;
} else { } else {
channel.prevChannel = siblings[siblings.length - 2]; channel.channel_previous = siblings[siblings.length - 2];
channel.prevChannel.rootTag().after(channel.rootTag()); channel.channel_previous.rootTag().after(channel.rootTag());
channel.channel_next = channel.channel_previous.channel_next;
channel.channel_next.channel_previous = channel;
channel.channel_previous.channel_next = channel;
} }
} else } else {
this.htmlTree.find(".server").after(channel.rootTag()); this.htmlTree.find(".server").after(channel.rootTag());
channel.channel_next = this.channel_first;
if(this.channel_first)
this.channel_first.channel_previous = channel;
this.channel_first = channel;
}
} }
if(channel.channel_previous == channel) /* shall never happen */
channel.channel_previous = undefined;
if(channel.channel_next == channel) /* shall never happen */
channel.channel_next = undefined;
if(oldParent) { if(oldParent) {
oldParent.adjustSize(); oldParent.adjustSize();
@ -471,6 +563,9 @@ class ChannelTree {
this.clients = []; this.clients = [];
this.channels = []; this.channels = [];
this.htmlTree.children().detach(); //Do not remove the listener! this.htmlTree.children().detach(); //Do not remove the listener!
this.channel_first = undefined;
this.channel_last = undefined;
} }
spawnCreateChannel(parent?: ChannelEntry) { spawnCreateChannel(parent?: ChannelEntry) {
@ -511,4 +606,103 @@ class ChannelTree {
for(let channel of this.channels) for(let channel of this.channels)
channel.handle_frame_resized(); channel.handle_frame_resized();
} }
private select_next_channel(channel: ChannelEntry, select_client: boolean) {
if(select_client) {
const clients = channel.clients_ordered();
if(clients.length > 0) {
this.onSelect(clients[0], true);
return;
}
}
const children = channel.siblings();
if(children.length > 0) {
this.onSelect(children[0], true);
return;
}
const next = channel.channel_next;
if(next) {
this.onSelect(next, true);
return;
}
let parent = channel.parent_channel();
while(parent) {
const p_next = parent.channel_next;
if(p_next) {
this.onSelect(p_next, true);
return;
}
parent = parent.parent_channel();
}
}
handle_key_press(event: KeyboardEvent) {
if(!this.selected_event || !this.currently_selected || $.isArray(this.currently_selected)) return;
if(event.keyCode == JQuery.Key.ArrowUp) {
event.preventDefault();
if(this.currently_selected instanceof ChannelEntry) {
let previous = this.currently_selected.channel_previous;
if(previous) {
while(true) {
const siblings = previous.siblings();
if(siblings.length == 0) break;
previous = siblings.last();
}
const clients = previous.clients_ordered();
if(clients.length > 0) {
this.onSelect(clients.last(), true);
return;
} else {
this.onSelect(previous, true);
return;
}
} else if(this.currently_selected.hasParent()) {
const channel = this.currently_selected.parent_channel();
const clients = channel.clients_ordered();
if(clients.length > 0) {
this.onSelect(clients.last(), true);
return;
} else {
this.onSelect(channel, true);
return;
}
} else
this.onSelect(this.server, true);
} else if(this.currently_selected instanceof ClientEntry) {
const channel = this.currently_selected.currentChannel();
const clients = channel.clients_ordered();
const index = clients.indexOf(this.currently_selected);
if(index > 0) {
this.onSelect(clients[index - 1], true);
return;
}
this.onSelect(channel, true);
return;
}
} else if(event.keyCode == JQuery.Key.ArrowDown) {
event.preventDefault();
if(this.currently_selected instanceof ChannelEntry) {
this.select_next_channel(this.currently_selected, true);
} else if(this.currently_selected instanceof ClientEntry){
const channel = this.currently_selected.currentChannel();
const clients = channel.clients_ordered();
const index = clients.indexOf(this.currently_selected);
if(index + 1 < clients.length) {
this.onSelect(clients[index + 1], true);
return;
}
this.select_next_channel(channel, false);
} else if(this.currently_selected instanceof ServerEntry)
this.onSelect(this.channel_first, true);
}
}
} }