From bbdae986b8febe0bf21bc9b78d46d30c1ed0ba8d Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sun, 2 Dec 2018 14:12:23 +0100 Subject: [PATCH] Added 2 new features --- ChangeLog.md | 8 + shared/html/templates.html | 7 + shared/js/log.ts | 2 +- shared/js/ui/channel.ts | 48 +++-- shared/js/ui/frames/SelectedItemInfo.ts | 1 + shared/js/ui/view.ts | 242 +++++++++++++++++++++--- 6 files changed, 269 insertions(+), 39 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 6c5176e3..a8b06238 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,12 @@ # 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** - Implemented support for svg and image detection - Fixed keeped host banner diff --git a/shared/html/templates.html b/shared/html/templates.html index f8d70839..b4a177d6 100644 --- a/shared/html/templates.html +++ b/shared/html/templates.html @@ -1510,6 +1510,13 @@ {{else}} Encrypted {{/if}} + + {{if server_encryption == 2}} + (Overridden by the server with Encrypted) + {{/if}} + {{if server_encryption == 1}} + (Overridden by the server with Unencrypted) + {{/if}} diff --git a/shared/js/log.ts b/shared/js/log.ts index 31e6a486..616fdc46 100644 --- a/shared/js/log.ts +++ b/shared/js/log.ts @@ -106,7 +106,7 @@ namespace log { } log(message: string, ...optionalParams: any[]) : this { - if(!this.initialized && false) { + if(!this.initialized) { if(this._collapsed && console.groupCollapsed) console.groupCollapsed(this.name, ...this.optionalParams); else diff --git a/shared/js/ui/channel.ts b/shared/js/ui/channel.ts index f0160372..e51526ce 100644 --- a/shared/js/ui/channel.ts +++ b/shared/js/ui/channel.ts @@ -50,10 +50,12 @@ class ChannelEntry { channelTree: ChannelTree; channelId: number; parent?: ChannelEntry; - prevChannel?: ChannelEntry; properties: ChannelProperties = new ChannelProperties(); originalHeight: number; + channel_previous?: ChannelEntry; + channel_next?: ChannelEntry; + private _channelAlign: string; private _formatedChannelName: string; private _family_index: number = 0; @@ -70,12 +72,11 @@ class ChannelEntry { private _cached_channel_description_promise_resolve: 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.channelId = channelId; this._formatedChannelName = channelName; this.parent = parent; - this.prevChannel = prevChannel; this.channelTree = null; this.initializeTag(); @@ -87,7 +88,7 @@ class ChannelEntry { } formatedChannelName() { - return this._formatedChannelName ? this._formatedChannelName : this.properties.channel_name; + return this._formatedChannelName !== undefined ? this._formatedChannelName : this.properties.channel_name; } getChannelDescription() : Promise { @@ -104,7 +105,7 @@ class ChannelEntry { }); } - parentChannel() { return this.parent; } + parent_channel?() { return this.parent; } hasParent(){ return this.parent != null; } getChannelId(){ return this.channelId; } channelClass() { return "channel_full"; } @@ -118,14 +119,14 @@ class ChannelEntry { let current = entry; if(deep) { while(current) { - if(current.parentChannel() == self) { + if(current.parent_channel() == self) { result.push(entry); break; } - current = current.parentChannel(); + current = current.parent_channel(); } } else - if(current.parentChannel() == self) + if(current.parent_channel() == self) result.push(entry); }); return result; @@ -140,11 +141,11 @@ class ChannelEntry { let current = entry.currentChannel(); if(deep) { while(current) { - if(current.parentChannel() == self) { + if(current.parent_channel() == self) { result.push(entry); break; } - current = current.parentChannel(); + current = current.parent_channel(); } } else if(current == self) @@ -153,6 +154,25 @@ class ChannelEntry { 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() { let rootTag = $.spawn("div"); @@ -285,7 +305,7 @@ class ChannelEntry { 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); + if(parent && this.parent_channel()) this.parent_channel().adjustSize(parent); } initializeListener() { @@ -445,7 +465,7 @@ class ChannelEntry { private __updateChannelName() { this._formatedChannelName = undefined; 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(']'); if(end == -1) break parseType; @@ -469,9 +489,9 @@ class ChannelEntry { 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")); + (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); if(this._channelAlign == "*") { diff --git a/shared/js/ui/frames/SelectedItemInfo.ts b/shared/js/ui/frames/SelectedItemInfo.ts index 9db19ba8..f7112b8d 100644 --- a/shared/js/ui/frames/SelectedItemInfo.ts +++ b/shared/js/ui/frames/SelectedItemInfo.ts @@ -308,6 +308,7 @@ class ChannelInfoManager extends InfoManager { properties["channel_type"] = ChannelType.normalize(channel.channelType()); properties["channel_clients"] = channel.channelTree.clientsByChannel(channel).length; properties["channel_subscribed"] = true; //TODO + properties["server_encryption"] = channel.channelTree.server.properties.virtualserver_codec_encryption_mode; for(let key in channel.properties) properties["property_" + key] = channel.properties[key]; diff --git a/shared/js/ui/view.ts b/shared/js/ui/view.ts index 6af9dd6c..d619b04c 100644 --- a/shared/js/ui/view.ts +++ b/shared/js/ui/view.ts @@ -6,6 +6,7 @@ /// /// + class ChannelTree { client: TSClient; htmlTree: JQuery; @@ -17,6 +18,11 @@ class ChannelTree { currently_selected_context_callback: (event) => any = undefined; readonly client_mover: ClientMover; + private channel_last?: ChannelEntry; + private channel_first?: ChannelEntry; + + private selected_event?: Event; + constructor(client, htmlTree) { document.addEventListener("touchstart", function(){}, true); @@ -44,6 +50,16 @@ class ChannelTree { } 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) { @@ -75,8 +91,8 @@ class ChannelTree { this.htmlTree.find(tag).fadeOut("slow", () => { tag.remove(); if(element instanceof ChannelEntry) { - if(element.parentChannel()) - element.parentChannel().adjustSize(true); + if(element.parent_channel()) + element.parent_channel().adjustSize(true); } else if(element instanceof ClientEntry) { element.currentChannel().adjustSize(true); } @@ -99,13 +115,25 @@ class ChannelTree { entry.channelTree = null; index--; break; - } else currentEntry = currentEntry.parentChannel(); + } else currentEntry = currentEntry.parent_channel(); } } this.channels.remove(channel); this.__deleteAnimation(channel); 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) { @@ -114,29 +142,53 @@ class ChannelTree { let elm = undefined; let tag = this.htmlTree; - let prevChannel = null; + + let previous_channel = null; if(channel.hasParent()) { - let parent = channel.parentChannel(); + let parent = channel.parent_channel(); let siblings = parent.siblings(); if(siblings.length == 0) { elm = parent.rootTag(); - prevChannel = null; + previous_channel = null; } else { - prevChannel = siblings.last(); - elm = prevChannel.tag; + previous_channel = siblings.last(); + elm = previous_channel.tag; } tag = parent.siblingTag(); - } - channel.prevChannel = prevChannel; - let entry = channel.rootTag().css({display: "none"}).fadeIn("slow"); + } else { + previous_channel = this.channel_last; + 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); + channel.originalHeight = entry.outerHeight(false); if(elm != undefined) 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(); } @@ -153,31 +205,71 @@ class ChannelTree { return undefined; } - moveChannel(channel: ChannelEntry, prevChannel: ChannelEntry, parent: ChannelEntry) { - if(prevChannel != null && prevChannel.parent != parent) { - console.error("Invalid channel move (different parents! (" + prevChannel.parent + "|" + parent + ")"); + moveChannel(channel: ChannelEntry, channel_previus: ChannelEntry, parent: ChannelEntry) { + if(channel_previus != null && channel_previus.parent != parent) { + console.error("Invalid channel move (different parents! (" + channel_previus.parent + "|" + parent + ")"); 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; - if(prevChannel) - prevChannel.rootTag().after(channel.rootTag()); - else { + if(channel_previus) { + if(channel_previus == this.channel_last) + 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) { let siblings = parent.siblings(); if(siblings.length <= 1) { //Self should be already in there let left = channel.rootTag(); - left.appendTo($(parent.siblingTag())); + left.appendTo(parent.siblingTag()); + + channel.channel_next = undefined; } else { - channel.prevChannel = siblings[siblings.length - 2]; - channel.prevChannel.rootTag().after(channel.rootTag()); + channel.channel_previous = siblings[siblings.length - 2]; + 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()); + + 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) { oldParent.adjustSize(); @@ -471,6 +563,9 @@ class ChannelTree { this.clients = []; this.channels = []; this.htmlTree.children().detach(); //Do not remove the listener! + + this.channel_first = undefined; + this.channel_last = undefined; } spawnCreateChannel(parent?: ChannelEntry) { @@ -511,4 +606,103 @@ class ChannelTree { for(let channel of this.channels) 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); + } + } } \ No newline at end of file