427 lines
No EOL
16 KiB
TypeScript
427 lines
No EOL
16 KiB
TypeScript
/* the bar on the right with the chats (Channel & Client) */
|
|
import {ClientEntry, MusicClientEntry} from "../../tree/Client";
|
|
import {ConnectionHandler} from "../../ConnectionHandler";
|
|
import {ChannelEntry} from "../../tree/Channel";
|
|
import {ServerEntry} from "../../tree/Server";
|
|
import {openMusicManage} from "../../ui/modal/ModalMusicManage";
|
|
import {formatMessage} from "../../ui/frames/chat";
|
|
import {MusicInfo} from "../../ui/frames/side/music_info";
|
|
import {ConversationManager} from "../../ui/frames/side/ConversationManager";
|
|
import {PrivateConversationManager} from "../../ui/frames/side/PrivateConversationManager";
|
|
import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons";
|
|
import { tr } from "tc-shared/i18n/localize";
|
|
import {ClientInfoController} from "tc-shared/ui/frames/side/ClientInfoController";
|
|
|
|
export enum InfoFrameMode {
|
|
NONE = "none",
|
|
CHANNEL_CHAT = "channel_chat",
|
|
PRIVATE_CHAT = "private_chat",
|
|
CLIENT_INFO = "client_info",
|
|
MUSIC_BOT = "music_bot"
|
|
}
|
|
export class InfoFrame {
|
|
private readonly handle: Frame;
|
|
private _html_tag: JQuery;
|
|
private _mode: InfoFrameMode;
|
|
|
|
private _value_ping: JQuery;
|
|
private _ping_updater: number;
|
|
|
|
private _channel_text: ChannelEntry;
|
|
private _channel_voice: ChannelEntry;
|
|
|
|
private _button_conversation: HTMLElement;
|
|
|
|
private _button_bot_manage: JQuery;
|
|
private _button_song_add: JQuery;
|
|
|
|
constructor(handle: Frame) {
|
|
this.handle = handle;
|
|
this._build_html_tag();
|
|
this.update_channel_talk();
|
|
this.update_channel_text();
|
|
this.set_mode(InfoFrameMode.CHANNEL_CHAT);
|
|
this._ping_updater = setInterval(() => this.update_ping(), 2000);
|
|
this.update_ping();
|
|
}
|
|
|
|
html_tag() : JQuery { return this._html_tag; }
|
|
destroy() {
|
|
clearInterval(this._ping_updater);
|
|
|
|
this._html_tag && this._html_tag.remove();
|
|
this._html_tag = undefined;
|
|
this._value_ping = undefined;
|
|
}
|
|
|
|
private _build_html_tag() {
|
|
this._html_tag = $("#tmpl_frame_chat_info").renderTag();
|
|
this._html_tag.find(".button-switch-chat-channel").on('click', () => this.handle.show_channel_conversations());
|
|
this._value_ping = this._html_tag.find(".value-ping");
|
|
this._html_tag.find(".chat-counter").on('click', event => this.handle.show_private_conversations());
|
|
this._button_conversation = this._html_tag.find(".button.open-conversation").on('click', event => {
|
|
const selected_client = this.handle.getClientInfo().getClient();
|
|
if(!selected_client) return;
|
|
|
|
const conversation = selected_client ? this.handle.private_conversations().findOrCreateConversation(selected_client) : undefined;
|
|
if(!conversation) return;
|
|
|
|
this.handle.private_conversations().setActiveConversation(conversation);
|
|
this.handle.show_private_conversations();
|
|
})[0];
|
|
|
|
this._button_bot_manage = this._html_tag.find(".bot-manage").on('click', event => {
|
|
const bot = this.handle.music_info().current_bot();
|
|
if(!bot) return;
|
|
|
|
openMusicManage(this.handle.handle, bot);
|
|
});
|
|
this._button_song_add = this._html_tag.find(".bot-add-song").on('click', event => {
|
|
this.handle.music_info().events.fire("action_song_add");
|
|
});
|
|
}
|
|
|
|
update_ping() {
|
|
this._value_ping.removeClass("very-good good medium poor very-poor");
|
|
const connection = this.handle.handle.serverConnection;
|
|
if(!this.handle.handle.connected || !connection) {
|
|
this._value_ping.text("Not connected");
|
|
return;
|
|
}
|
|
|
|
const ping = connection.ping();
|
|
if(!ping || typeof(ping.native) !== "number") {
|
|
this._value_ping.text("Not available");
|
|
return;
|
|
}
|
|
|
|
let value;
|
|
if(typeof(ping.javascript) !== "undefined") {
|
|
value = ping.javascript;
|
|
this._value_ping.text(ping.javascript.toFixed(0) + "ms").attr('title', 'Native: ' + ping.native.toFixed(3) + "ms \nJavascript: " + ping.javascript.toFixed(3) + "ms");
|
|
} else {
|
|
value = ping.native;
|
|
this._value_ping.text(ping.native.toFixed(0) + "ms").attr('title', "Ping: " + ping.native.toFixed(3) + "ms");
|
|
}
|
|
|
|
if(value <= 10)
|
|
this._value_ping.addClass("very-good");
|
|
else if(value <= 30)
|
|
this._value_ping.addClass("good");
|
|
else if(value <= 60)
|
|
this._value_ping.addClass("medium");
|
|
else if(value <= 150)
|
|
this._value_ping.addClass("poor");
|
|
else
|
|
this._value_ping.addClass("very-poor");
|
|
}
|
|
|
|
update_channel_talk() {
|
|
const client = this.handle.handle.getClient();
|
|
const channel = client ? client.currentChannel() : undefined;
|
|
this._channel_voice = channel;
|
|
|
|
const html_tag = this._html_tag.find(".value-voice-channel");
|
|
const html_limit_tag = this._html_tag.find(".value-voice-limit");
|
|
|
|
html_limit_tag.text("");
|
|
html_tag.children().remove();
|
|
|
|
if(channel) {
|
|
if(channel.properties.channel_icon_id != 0) {
|
|
const connection = channel.channelTree.client;
|
|
generateIconJQueryTag(getIconManager().resolveIcon(channel.properties.channel_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId)).appendTo(html_tag);
|
|
}
|
|
$.spawn("div").text(channel.formattedChannelName()).appendTo(html_tag);
|
|
|
|
this.update_channel_limit(channel, html_limit_tag);
|
|
} else {
|
|
$.spawn("div").text("Not connected").appendTo(html_tag);
|
|
}
|
|
}
|
|
|
|
update_channel_text() {
|
|
const channel_tree = this.handle.handle.connected ? this.handle.handle.channelTree : undefined;
|
|
const current_channel_id = channel_tree ? this.handle.channel_conversations().selectedConversation() : 0;
|
|
const channel = channel_tree ? channel_tree.findChannel(current_channel_id) : undefined;
|
|
this._channel_text = channel;
|
|
|
|
const tag_container = this._html_tag.find(".mode-channel_chat.channel");
|
|
const html_tag_title = tag_container.find(".title");
|
|
const html_tag = tag_container.find(".value-text-channel");
|
|
const html_limit_tag = tag_container.find(".value-text-limit");
|
|
|
|
/* reset */
|
|
html_tag_title.text(tr("You're chatting in Channel"));
|
|
html_limit_tag.text("");
|
|
html_tag.children().detach();
|
|
|
|
/* initialize */
|
|
if(channel) {
|
|
if(channel.properties.channel_icon_id != 0) {
|
|
const connection = channel.channelTree.client;
|
|
generateIconJQueryTag(getIconManager().resolveIcon(channel.properties.channel_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId)).appendTo(html_tag);
|
|
}
|
|
$.spawn("div").text(channel.formattedChannelName()).appendTo(html_tag);
|
|
|
|
this.update_channel_limit(channel, html_limit_tag);
|
|
} else if(channel_tree && current_channel_id > 0) {
|
|
html_tag.append(formatMessage(tr("Unknown channel id {}"), current_channel_id));
|
|
} else if(channel_tree && current_channel_id == 0) {
|
|
const server = this.handle.handle.channelTree.server;
|
|
if(server.properties.virtualserver_icon_id != 0) {
|
|
const connection = server.channelTree.client;
|
|
generateIconJQueryTag(getIconManager().resolveIcon(server.properties.virtualserver_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId)).appendTo(html_tag);
|
|
}
|
|
$.spawn("div").text(server.properties.virtualserver_name).appendTo(html_tag);
|
|
html_tag_title.text(tr("You're chatting in Server"));
|
|
|
|
this.update_server_limit(server, html_limit_tag);
|
|
} else if(this.handle.handle.connected) {
|
|
$.spawn("div").text("No channel selected").appendTo(html_tag);
|
|
} else {
|
|
$.spawn("div").text("Not connected").appendTo(html_tag);
|
|
}
|
|
}
|
|
|
|
update_channel_client_count(channel: ChannelEntry) {
|
|
if(channel === this._channel_text) {
|
|
this.update_channel_limit(channel, this._html_tag.find(".value-text-limit"));
|
|
}
|
|
|
|
if(channel === this._channel_voice) {
|
|
this.update_channel_limit(channel, this._html_tag.find(".value-voice-limit"));
|
|
}
|
|
}
|
|
|
|
private update_channel_limit(channel: ChannelEntry, tag: JQuery) {
|
|
let channel_limit = tr("Unlimited");
|
|
if(!channel.properties.channel_flag_maxclients_unlimited)
|
|
channel_limit = "" + channel.properties.channel_maxclients;
|
|
else if(!channel.properties.channel_flag_maxfamilyclients_unlimited) {
|
|
if(channel.properties.channel_maxfamilyclients >= 0)
|
|
channel_limit = "" + channel.properties.channel_maxfamilyclients;
|
|
}
|
|
tag.text(channel.clients(false).length + " / " + channel_limit);
|
|
}
|
|
|
|
private update_server_limit(server: ServerEntry, tag: JQuery) {
|
|
const fn = () => {
|
|
let text = server.properties.virtualserver_clientsonline + " / " + server.properties.virtualserver_maxclients;
|
|
if(server.properties.virtualserver_reserved_slots)
|
|
text += " (" + server.properties.virtualserver_reserved_slots + " " + tr("Reserved") + ")";
|
|
tag.text(text);
|
|
};
|
|
|
|
server.updateProperties().then(fn).catch(error => tag.text(tr("Failed to update info")));
|
|
fn();
|
|
}
|
|
|
|
update_chat_counter() {
|
|
const privateConversations = this.handle.private_conversations().getConversations();
|
|
{
|
|
const count = privateConversations.filter(e => e.hasUnreadMessages()).length;
|
|
const count_container = this._html_tag.find(".container-indicator");
|
|
const count_tag = count_container.find(".chat-unread-counter");
|
|
count_container.toggle(count > 0);
|
|
count_tag.text(count);
|
|
}
|
|
{
|
|
const count_tag = this._html_tag.find(".chat-counter");
|
|
if(privateConversations.length == 0)
|
|
count_tag.text(tr("No conversations"));
|
|
else if(privateConversations.length == 1)
|
|
count_tag.text(tr("One conversation"));
|
|
else
|
|
count_tag.text(privateConversations.length + " " + tr("conversations"));
|
|
}
|
|
}
|
|
|
|
current_mode() : InfoFrameMode {
|
|
return this._mode;
|
|
}
|
|
|
|
set_mode(mode: InfoFrameMode) {
|
|
for(const mode in InfoFrameMode)
|
|
this._html_tag.removeClass("mode-" + InfoFrameMode[mode]);
|
|
this._html_tag.addClass("mode-" + mode);
|
|
|
|
if(mode === InfoFrameMode.CLIENT_INFO && this._button_conversation) {
|
|
//Will be called every time a client is shown
|
|
const selected_client = this.handle.getClientInfo().getClient();
|
|
const conversation = selected_client ? this.handle.private_conversations().findConversation(selected_client) : undefined;
|
|
|
|
const visibility = (selected_client && selected_client.clientId() !== this.handle.handle.getClientId()) ? "visible" : "hidden";
|
|
if(this._button_conversation.style.visibility !== visibility)
|
|
this._button_conversation.style.visibility = visibility;
|
|
if(conversation) {
|
|
this._button_conversation.innerText = tr("Open conversation");
|
|
} else {
|
|
this._button_conversation.innerText = tr("Start a conversation");
|
|
}
|
|
} else if(mode === InfoFrameMode.MUSIC_BOT) {
|
|
//TODO?
|
|
}
|
|
}
|
|
}
|
|
|
|
export enum FrameContent {
|
|
NONE,
|
|
PRIVATE_CHAT,
|
|
CHANNEL_CHAT,
|
|
CLIENT_INFO,
|
|
MUSIC_BOT
|
|
}
|
|
|
|
export class Frame {
|
|
readonly handle: ConnectionHandler;
|
|
private infoFrame: InfoFrame;
|
|
private htmlTag: JQuery;
|
|
private containerInfo: JQuery;
|
|
private containerChannelChat: JQuery;
|
|
private _content_type: FrameContent;
|
|
|
|
private clientInfo: ClientInfoController;
|
|
private musicInfo: MusicInfo;
|
|
private channelConversations: ConversationManager;
|
|
private privateConversations: PrivateConversationManager;
|
|
|
|
constructor(handle: ConnectionHandler) {
|
|
this.handle = handle;
|
|
|
|
this._content_type = FrameContent.NONE;
|
|
this.infoFrame = new InfoFrame(this);
|
|
this.privateConversations = new PrivateConversationManager(handle);
|
|
this.channelConversations = new ConversationManager(handle);
|
|
this.clientInfo = new ClientInfoController(handle);
|
|
this.musicInfo = new MusicInfo(this);
|
|
|
|
this._build_html_tag();
|
|
this.show_channel_conversations();
|
|
this.info_frame().update_chat_counter();
|
|
}
|
|
|
|
html_tag() : JQuery { return this.htmlTag; }
|
|
info_frame() : InfoFrame { return this.infoFrame; }
|
|
|
|
content_type() : FrameContent { return this._content_type; }
|
|
|
|
destroy() {
|
|
this.htmlTag && this.htmlTag.remove();
|
|
this.htmlTag = undefined;
|
|
|
|
this.infoFrame && this.infoFrame.destroy();
|
|
this.infoFrame = undefined;
|
|
|
|
this.clientInfo?.destroy();
|
|
this.clientInfo = undefined;
|
|
|
|
this.musicInfo && this.musicInfo.destroy();
|
|
this.musicInfo = undefined;
|
|
|
|
this.privateConversations && this.privateConversations.destroy();
|
|
this.privateConversations = undefined;
|
|
|
|
this.channelConversations && this.channelConversations.destroy();
|
|
this.channelConversations = undefined;
|
|
|
|
this.containerInfo && this.containerInfo.remove();
|
|
this.containerInfo = undefined;
|
|
|
|
this.containerChannelChat && this.containerChannelChat.remove();
|
|
this.containerChannelChat = undefined;
|
|
}
|
|
|
|
private _build_html_tag() {
|
|
this.htmlTag = $("#tmpl_frame_chat").renderTag();
|
|
this.containerInfo = this.htmlTag.find(".container-info");
|
|
this.containerChannelChat = this.htmlTag.find(".container-chat");
|
|
|
|
this.infoFrame.html_tag().appendTo(this.containerInfo);
|
|
}
|
|
|
|
|
|
private_conversations() : PrivateConversationManager {
|
|
return this.privateConversations;
|
|
}
|
|
|
|
channel_conversations() : ConversationManager {
|
|
return this.channelConversations;
|
|
}
|
|
|
|
getClientInfo() : ClientInfoController {
|
|
return this.clientInfo;
|
|
}
|
|
|
|
music_info() : MusicInfo {
|
|
return this.musicInfo;
|
|
}
|
|
|
|
private _clear() {
|
|
this._content_type = FrameContent.NONE;
|
|
this.containerChannelChat.children().detach();
|
|
}
|
|
|
|
show_private_conversations() {
|
|
if(this._content_type === FrameContent.PRIVATE_CHAT)
|
|
return;
|
|
|
|
this._clear();
|
|
this._content_type = FrameContent.PRIVATE_CHAT;
|
|
this.containerChannelChat.append(this.privateConversations.htmlTag);
|
|
this.privateConversations.handlePanelShow();
|
|
this.infoFrame.set_mode(InfoFrameMode.PRIVATE_CHAT);
|
|
}
|
|
|
|
show_channel_conversations() {
|
|
if(this._content_type === FrameContent.CHANNEL_CHAT)
|
|
return;
|
|
|
|
this._clear();
|
|
this._content_type = FrameContent.CHANNEL_CHAT;
|
|
this.containerChannelChat.append(this.channelConversations.htmlTag);
|
|
this.channelConversations.handlePanelShow();
|
|
|
|
this.infoFrame.set_mode(InfoFrameMode.CHANNEL_CHAT);
|
|
}
|
|
|
|
show_client_info(client: ClientEntry) {
|
|
this.clientInfo.setClient(client);
|
|
this.infoFrame.set_mode(InfoFrameMode.CLIENT_INFO); /* specially needs an update here to update the conversation button */
|
|
|
|
if(this._content_type === FrameContent.CLIENT_INFO)
|
|
return;
|
|
|
|
this._clear();
|
|
this._content_type = FrameContent.CLIENT_INFO;
|
|
this.containerChannelChat.append(this.clientInfo.getHtmlTag());
|
|
}
|
|
|
|
show_music_player(client: MusicClientEntry) {
|
|
this.musicInfo.set_current_bot(client);
|
|
|
|
if(this._content_type === FrameContent.MUSIC_BOT)
|
|
return;
|
|
|
|
this.infoFrame.set_mode(InfoFrameMode.MUSIC_BOT);
|
|
this.musicInfo.previous_frame_content = this._content_type;
|
|
this._clear();
|
|
this._content_type = FrameContent.MUSIC_BOT;
|
|
this.containerChannelChat.append(this.musicInfo.html_tag());
|
|
}
|
|
|
|
set_content(type: FrameContent) {
|
|
if(this._content_type === type)
|
|
return;
|
|
|
|
if(type === FrameContent.CHANNEL_CHAT)
|
|
this.show_channel_conversations();
|
|
else if(type === FrameContent.PRIVATE_CHAT)
|
|
this.show_private_conversations();
|
|
else {
|
|
this._clear();
|
|
this._content_type = FrameContent.NONE;
|
|
this.infoFrame.set_mode(InfoFrameMode.NONE);
|
|
}
|
|
}
|
|
} |