Properly logging channel creations, deletions, shows and hides
parent
409f7489c4
commit
92191b259b
|
@ -1,4 +1,7 @@
|
|||
# Changelog:
|
||||
* **04.12.20**
|
||||
- Properly logging channel creations, deletions, shows and hides
|
||||
|
||||
* **03.12.20**
|
||||
- Fixed server connection tab move handler
|
||||
- Fixed file browser context menu when having an overlay
|
||||
|
|
|
@ -1088,10 +1088,11 @@ export class ConnectionHandler {
|
|||
setSubscribeToAllChannels(flag: boolean) {
|
||||
if(this.client_status.channel_subscribe_all === flag) return;
|
||||
this.client_status.channel_subscribe_all = flag;
|
||||
if(flag)
|
||||
if(flag) {
|
||||
this.channelTree.subscribe_all_channels();
|
||||
else
|
||||
} else {
|
||||
this.channelTree.unsubscribe_all_channels();
|
||||
}
|
||||
this.event_registry.fire("notify_state_updated", { state: "subscribe" });
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as log from "../log";
|
||||
import {LogCategory} from "../log";
|
||||
import {LogCategory, logError} from "../log";
|
||||
import {AbstractServerConnection, CommandOptions, ServerCommand} from "../connection/ConnectionBase";
|
||||
import {Sound} from "../sound/Sounds";
|
||||
import {CommandResult} from "../connection/ServerConnectionDeclaration";
|
||||
|
@ -12,7 +12,6 @@ import {
|
|||
MusicClientEntry,
|
||||
SongInfo
|
||||
} from "../tree/Client";
|
||||
import {ChannelEntry} from "../tree/Channel";
|
||||
import {ConnectionHandler, ConnectionState, DisconnectReason, ViewReasonId} from "../ConnectionHandler";
|
||||
import {formatMessage} from "../ui/frames/chat";
|
||||
import {spawnPoke} from "../ui/modal/ModalPoke";
|
||||
|
@ -24,6 +23,7 @@ import {tr} from "../i18n/localize";
|
|||
import {EventClient, EventType} from "../ui/frames/log/Definitions";
|
||||
import {ErrorCode} from "../connection/ErrorCode";
|
||||
import {server_connections} from "tc-shared/ConnectionManager";
|
||||
import {ChannelEntry} from "tc-shared/tree/Channel";
|
||||
|
||||
export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss {
|
||||
constructor(connection: AbstractServerConnection) {
|
||||
|
@ -86,22 +86,24 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
this["notifyplaylistsongloaded"] = this.handleNotifyPlaylistSongLoaded;
|
||||
}
|
||||
|
||||
private loggable_invoker(unique_id, client_id, name) : EventClient | undefined {
|
||||
const id = parseInt(client_id);
|
||||
if(typeof(client_id) === "undefined" || Number.isNaN(id))
|
||||
private loggable_invoker(uniqueId, clientId, clientName) : EventClient | undefined {
|
||||
const id = typeof clientId === "string" ? parseInt(clientId) : clientId;
|
||||
if(typeof(clientId) === "undefined" || Number.isNaN(id)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if(id == 0)
|
||||
if(id == 0) {
|
||||
return {
|
||||
client_id: 0,
|
||||
client_unique_id: this.connection_handler.channelTree.server.properties.virtualserver_unique_identifier,
|
||||
client_name: this.connection_handler.channelTree.server.properties.virtualserver_name,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
client_unique_id: unique_id,
|
||||
client_name: name,
|
||||
client_id: client_id
|
||||
client_unique_id: uniqueId,
|
||||
client_name: clientName,
|
||||
client_id: clientId
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -290,35 +292,36 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
client.set_connection_info(object);
|
||||
}
|
||||
|
||||
private createChannelFromJson(json, ignoreOrder: boolean = false) {
|
||||
private createChannelFromJson(json, ignoreMissingPreviousChannel: boolean = false) : ChannelEntry {
|
||||
let tree = this.connection.client.channelTree;
|
||||
|
||||
let channel = new ChannelEntry(parseInt(json["cid"]), json["channel_name"]);
|
||||
let parent, previous;
|
||||
if(json["channel_order"] !== "0") {
|
||||
previous = tree.findChannel(json["channel_order"]);
|
||||
if(!previous && json["channel_order"] != 0) {
|
||||
if(!ignoreOrder) {
|
||||
log.error(LogCategory.NETWORKING, tr("Invalid channel order id!"));
|
||||
return;
|
||||
}
|
||||
let channelId = parseInt(json["cid"]);
|
||||
let channelName = json["channel_name"];
|
||||
|
||||
let previousChannelId = parseInt(json["channel_order"]);
|
||||
let parentChannelId = parseInt(json["cpid"]);
|
||||
|
||||
let parentChannel: ChannelEntry;
|
||||
let previousChannel: ChannelEntry;
|
||||
|
||||
if(previousChannelId !== 0) {
|
||||
previousChannel = tree.findChannel(previousChannelId);
|
||||
|
||||
if(!previousChannel && !ignoreMissingPreviousChannel) {
|
||||
logError(LogCategory.NETWORKING, tr("Received a channel with an invalid order id (%d)"), previousChannelId);
|
||||
/* maybe disconnect? */
|
||||
}
|
||||
}
|
||||
|
||||
parent = tree.findChannel(json["cpid"]);
|
||||
if(!parent && json["cpid"] != 0) {
|
||||
log.error(LogCategory.NETWORKING, tr("Invalid channel parent"));
|
||||
return;
|
||||
if(parentChannelId !== 0) {
|
||||
parentChannel = tree.findChannel(parentChannelId);
|
||||
if(!parentChannel) {
|
||||
logError(LogCategory.NETWORKING, tr("Received a channel with an invalid parent channel (%d)"), parentChannelId);
|
||||
/* maybe disconnect? */
|
||||
}
|
||||
}
|
||||
|
||||
tree.insertChannel(channel, previous, parent);
|
||||
if(ignoreOrder) {
|
||||
for(let ch of tree.channels) {
|
||||
if(ch.properties.channel_order == channel.channelId) {
|
||||
tree.moveChannel(ch, channel, channel.parent, true); //Corrent the order :)
|
||||
}
|
||||
}
|
||||
}
|
||||
const channel = tree.handleChannelCreated(previousChannel, parentChannel, channelId, channelName);
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
|
@ -338,22 +341,27 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
if(tree.channelsInitialized) {
|
||||
channel.updateSubscribeMode().then(undefined);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
private batch_update_finished_timeout;
|
||||
private batchTreeUpdateFinishedTimeout;
|
||||
handleCommandChannelList(json) {
|
||||
if(this.batch_update_finished_timeout) {
|
||||
clearTimeout(this.batch_update_finished_timeout);
|
||||
this.batch_update_finished_timeout = 0;
|
||||
if(this.batchTreeUpdateFinishedTimeout) {
|
||||
clearTimeout(this.batchTreeUpdateFinishedTimeout);
|
||||
this.batchTreeUpdateFinishedTimeout = 0;
|
||||
/* batch update is still active */
|
||||
} else {
|
||||
batch_updates(BatchUpdateType.CHANNEL_TREE);
|
||||
}
|
||||
|
||||
for(let index = 0; index < json.length; index++)
|
||||
for(let index = 0; index < json.length; index++) {
|
||||
this.createChannelFromJson(json[index], true);
|
||||
}
|
||||
|
||||
this.batch_update_finished_timeout = setTimeout(() => {
|
||||
this.batchTreeUpdateFinishedTimeout = setTimeout(() => {
|
||||
flush_batched_updates(BatchUpdateType.CHANNEL_TREE);
|
||||
this.batchTreeUpdateFinishedTimeout = 0;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
@ -362,34 +370,74 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
this.connection.client.channelTree.channelsInitialized = true;
|
||||
this.connection.client.channelTree.events.fire_react("notify_channel_list_received");
|
||||
|
||||
if(this.batch_update_finished_timeout) {
|
||||
clearTimeout(this.batch_update_finished_timeout);
|
||||
this.batch_update_finished_timeout = 0;
|
||||
if(this.batchTreeUpdateFinishedTimeout) {
|
||||
clearTimeout(this.batchTreeUpdateFinishedTimeout);
|
||||
this.batchTreeUpdateFinishedTimeout = 0;
|
||||
flush_batched_updates(BatchUpdateType.CHANNEL_TREE);
|
||||
}
|
||||
}
|
||||
|
||||
handleCommandChannelCreate(json) {
|
||||
this.createChannelFromJson(json[0]);
|
||||
json = json[0];
|
||||
|
||||
const channel = this.createChannelFromJson(json);
|
||||
if(!channel) { return; }
|
||||
|
||||
const ownAction = parseInt(json["invokerid"]) === this.connection.client.getClientId();
|
||||
if(ownAction) {
|
||||
this.connection.client.sound.play(Sound.CHANNEL_CREATED);
|
||||
}
|
||||
|
||||
const log = this.connection.client.log;
|
||||
log.log("channel.create", {
|
||||
channel: channel.log_data(),
|
||||
creator: this.loggable_invoker(json["invokeruid"], json["invokerid"], json["invokername"]),
|
||||
ownAction: ownAction
|
||||
});
|
||||
}
|
||||
|
||||
handleCommandChannelShow(json) {
|
||||
this.createChannelFromJson(json[0]); //TODO may chat?
|
||||
json = json[0];
|
||||
const channel = this.createChannelFromJson(json);
|
||||
|
||||
const log = this.connection.client.log;
|
||||
log.log("channel.show", {
|
||||
channel: channel.log_data(),
|
||||
});
|
||||
}
|
||||
|
||||
handleCommandChannelDelete(json) {
|
||||
let tree = this.connection.client.channelTree;
|
||||
const conversations = this.connection.client.side_bar.channel_conversations();
|
||||
|
||||
let playSound = false;
|
||||
|
||||
log.info(LogCategory.NETWORKING, tr("Got %d channel deletions"), json.length);
|
||||
for(let index = 0; index < json.length; index++) {
|
||||
conversations.destroyConversation(parseInt(json[index]["cid"]));
|
||||
let channel = tree.findChannel(json[index]["cid"]);
|
||||
if(!channel) {
|
||||
log.error(LogCategory.NETWORKING, tr("Invalid channel onDelete (Unknown channel)"));
|
||||
logError(LogCategory.NETWORKING, tr("Invalid channel onDelete (Unknown channel)"));
|
||||
continue;
|
||||
}
|
||||
tree.deleteChannel(channel);
|
||||
|
||||
const ownAction = parseInt(json[index]["invokerid"]) === this.connection.client.getClientId();
|
||||
|
||||
const log = this.connection.client.log;
|
||||
log.log("channel.delete", {
|
||||
channel: channel.log_data(),
|
||||
deleter: this.loggable_invoker(json[index]["invokeruid"], json[index]["invokerid"], json[index]["invokername"]),
|
||||
ownAction: ownAction
|
||||
});
|
||||
|
||||
if(ownAction) {
|
||||
playSound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(playSound) {
|
||||
this.connection.client.sound.play(Sound.CHANNEL_DELETED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,10 +450,15 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
conversations.destroyConversation(parseInt(json[index]["cid"]));
|
||||
let channel = tree.findChannel(json[index]["cid"]);
|
||||
if(!channel) {
|
||||
log.error(LogCategory.NETWORKING, tr("Invalid channel on hide (Unknown channel)"));
|
||||
logError(LogCategory.NETWORKING, tr("Invalid channel on hide (Unknown channel)"));
|
||||
continue;
|
||||
}
|
||||
tree.deleteChannel(channel);
|
||||
|
||||
const log = this.connection.client.log;
|
||||
log.log("channel.hide", {
|
||||
channel: channel.log_data(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -974,7 +1027,7 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
continue;
|
||||
}
|
||||
|
||||
channel.flag_subscribed = true;
|
||||
channel.setSubscribed(true);
|
||||
}
|
||||
} finally {
|
||||
flush_batched_updates(BatchUpdateType.CHANNEL_TREE);
|
||||
|
@ -989,11 +1042,12 @@ export class ConnectionCommandHandler extends AbstractCommandHandler {
|
|||
continue;
|
||||
}
|
||||
|
||||
channel.flag_subscribed = false;
|
||||
for(const client of channel.clients(false))
|
||||
channel.setSubscribed(false);
|
||||
for(const client of channel.clients(false)) {
|
||||
this.connection.client.channelTree.deleteClient(client, { reason: ViewReasonId.VREASON_SYSTEM, serverLeave: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
handleNotifyConversationMessageDelete(json: any[]) {
|
||||
|
|
|
@ -18,7 +18,6 @@ import {formatMessage} from "../ui/frames/chat";
|
|||
import {Registry} from "../events";
|
||||
import {ChannelTreeEntry, ChannelTreeEntryEvents} from "./ChannelTreeEntry";
|
||||
import {spawnFileTransferModal} from "../ui/modal/transfer/ModalFileTransfer";
|
||||
import {ViewReasonId} from "../ConnectionHandler";
|
||||
import {EventChannelData} from "../ui/frames/log/Definitions";
|
||||
import {ErrorCode} from "../connection/ErrorCode";
|
||||
import {ClientIcon} from "svg-sprites/client-icons";
|
||||
|
@ -173,22 +172,22 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
private _cached_channel_description_promise_resolve: any = undefined;
|
||||
private _cached_channel_description_promise_reject: any = undefined;
|
||||
|
||||
private _flag_collapsed: boolean;
|
||||
private _flag_subscribed: boolean;
|
||||
private _subscribe_mode: ChannelSubscribeMode;
|
||||
private collapsed: boolean;
|
||||
private subscribed: boolean;
|
||||
private subscriptionMode: ChannelSubscribeMode;
|
||||
|
||||
private client_list: ClientEntry[] = []; /* this list is sorted correctly! */
|
||||
private readonly clientPropertyChangedListener;
|
||||
|
||||
constructor(channelId, channelName) {
|
||||
constructor(channelTree: ChannelTree, channelId: number, channelName: string) {
|
||||
super();
|
||||
|
||||
this.channelTree = channelTree;
|
||||
this.events = new Registry<ChannelEvents>();
|
||||
|
||||
this.properties = new ChannelProperties();
|
||||
this.channelId = channelId;
|
||||
this.properties.channel_name = channelName;
|
||||
this.channelTree = null;
|
||||
|
||||
this.parsed_channel_name = new ParsedChannelName("undefined", false);
|
||||
|
||||
|
@ -205,6 +204,9 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
updatedProperties: event.updated_properties
|
||||
});
|
||||
});
|
||||
|
||||
this.collapsed = this.channelTree.client.settings.server(Settings.FN_SERVER_CHANNEL_COLLAPSED(this.channelId));
|
||||
this.subscriptionMode = this.channelTree.client.settings.server(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
@ -428,21 +430,21 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
icon: "client-subscribe_to_channel",
|
||||
name: bold(tr("Subscribe to channel")),
|
||||
callback: () => this.subscribe(),
|
||||
visible: !this.flag_subscribed
|
||||
visible: !this.isSubscribed()
|
||||
},
|
||||
{
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon: "client-channel_unsubscribed",
|
||||
name: bold(tr("Unsubscribe from channel")),
|
||||
callback: () => this.unsubscribe(),
|
||||
visible: this.flag_subscribed
|
||||
visible: this.isSubscribed()
|
||||
},
|
||||
{
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon: "client-subscribe_mode",
|
||||
name: bold(tr("Use inherited subscribe mode")),
|
||||
callback: () => this.unsubscribe(true),
|
||||
visible: this.subscribe_mode != ChannelSubscribeMode.INHERITED
|
||||
visible: this.subscriptionMode != ChannelSubscribeMode.INHERITED
|
||||
}
|
||||
];
|
||||
return [];
|
||||
|
@ -488,10 +490,7 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
name: tr("Delete channel"),
|
||||
invalidPermission: !flagDelete,
|
||||
callback: () => {
|
||||
const client = this.channelTree.client;
|
||||
this.channelTree.client.serverConnection.send_command("channeldelete", {cid: this.channelId}).then(() => {
|
||||
client.sound.play(Sound.CHANNEL_DELETED);
|
||||
});
|
||||
this.channelTree.client.serverConnection.send_command("channeldelete", {cid: this.channelId});
|
||||
}
|
||||
},
|
||||
contextmenu.Entry.HR(),
|
||||
|
@ -679,7 +678,7 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
|
||||
async updateSubscribeMode() {
|
||||
let shouldBeSubscribed = false;
|
||||
switch (this.subscribe_mode) {
|
||||
switch (this.subscriptionMode) {
|
||||
case ChannelSubscribeMode.INHERITED:
|
||||
shouldBeSubscribed = this.channelTree.client.isSubscribeToAllChannels();
|
||||
break;
|
||||
|
@ -693,13 +692,13 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
break;
|
||||
}
|
||||
|
||||
if(this.flag_subscribed === shouldBeSubscribed) {
|
||||
if(this.subscribed === shouldBeSubscribed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const connection = this.channelTree.client.getServerConnection();
|
||||
if(!connection.connected()) {
|
||||
this.flag_subscribed = shouldBeSubscribed;
|
||||
this.setSubscribed(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -715,87 +714,53 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
}
|
||||
|
||||
async subscribe() : Promise<void> {
|
||||
if(this.subscribe_mode == ChannelSubscribeMode.SUBSCRIBED) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscribe_mode = ChannelSubscribeMode.SUBSCRIBED;
|
||||
|
||||
const connection = this.channelTree.client.getServerConnection();
|
||||
if(!this.flag_subscribed && connection) {
|
||||
await connection.send_command('channelsubscribe', {
|
||||
'cid': this.getChannelId()
|
||||
});
|
||||
} else {
|
||||
this.flag_subscribed = false;
|
||||
}
|
||||
this.setSubscriptionMode(ChannelSubscribeMode.SUBSCRIBED);
|
||||
}
|
||||
|
||||
async unsubscribe(inherited_subscription_mode?: boolean) : Promise<void> {
|
||||
const connection = this.channelTree.client.getServerConnection();
|
||||
let unsubscribe: boolean;
|
||||
|
||||
if(inherited_subscription_mode) {
|
||||
this.subscribe_mode = ChannelSubscribeMode.INHERITED;
|
||||
unsubscribe = this.flag_subscribed && !this.channelTree.client.isSubscribeToAllChannels();
|
||||
} else {
|
||||
this.subscribe_mode = ChannelSubscribeMode.UNSUBSCRIBED;
|
||||
unsubscribe = this.flag_subscribed;
|
||||
this.setSubscriptionMode(inherited_subscription_mode ? ChannelSubscribeMode.INHERITED : ChannelSubscribeMode.UNSUBSCRIBED);
|
||||
}
|
||||
|
||||
if(unsubscribe) {
|
||||
if(connection) {
|
||||
await connection.send_command('channelunsubscribe', {
|
||||
'cid': this.getChannelId()
|
||||
});
|
||||
} else {
|
||||
this.flag_subscribed = false;
|
||||
isCollapsed() : boolean {
|
||||
return this.collapsed;
|
||||
}
|
||||
|
||||
for(const client of this.clients(false)) {
|
||||
this.channelTree.deleteClient(client, { serverLeave: false, reason: ViewReasonId.VREASON_SYSTEM });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get collapsed() : boolean {
|
||||
if(typeof this._flag_collapsed === "undefined")
|
||||
this._flag_collapsed = this.channelTree.client.settings.server(Settings.FN_SERVER_CHANNEL_COLLAPSED(this.channelId));
|
||||
return this._flag_collapsed;
|
||||
}
|
||||
|
||||
set collapsed(flag: boolean) {
|
||||
if(this._flag_collapsed === flag) {
|
||||
setCollapsed(flag: boolean) {
|
||||
if(this.collapsed === flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._flag_collapsed = flag;
|
||||
this.collapsed = flag;
|
||||
this.events.fire("notify_collapsed_state_changed", { collapsed: flag });
|
||||
this.channelTree.client.settings.changeServer(Settings.FN_SERVER_CHANNEL_COLLAPSED(this.channelId), flag);
|
||||
}
|
||||
|
||||
get flag_subscribed() : boolean {
|
||||
return this._flag_subscribed;
|
||||
isSubscribed() : boolean {
|
||||
return this.subscribed;
|
||||
}
|
||||
|
||||
set flag_subscribed(flag: boolean) {
|
||||
if(this._flag_subscribed == flag)
|
||||
/* Attention: This method is not to subscribe to a channel! It's used to update the current subscription state.*/
|
||||
setSubscribed(flag: boolean) {
|
||||
if(this.subscribed === flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._flag_subscribed = flag;
|
||||
this.subscribed = flag;
|
||||
this.events.fire("notify_subscribe_state_changed", { channel_subscribed: flag });
|
||||
}
|
||||
|
||||
get subscribe_mode() : ChannelSubscribeMode {
|
||||
return typeof(this._subscribe_mode) !== 'undefined' ? this._subscribe_mode : (this._subscribe_mode = this.channelTree.client.settings.server(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId), ChannelSubscribeMode.INHERITED));
|
||||
getSubscriptionMode() : ChannelSubscribeMode {
|
||||
return this.subscriptionMode;
|
||||
}
|
||||
|
||||
set subscribe_mode(mode: ChannelSubscribeMode) {
|
||||
if(this.subscribe_mode == mode)
|
||||
setSubscriptionMode(mode: ChannelSubscribeMode) {
|
||||
if(this.subscriptionMode === mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._subscribe_mode = mode;
|
||||
this.subscriptionMode = mode;
|
||||
this.channelTree.client.settings.changeServer(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId), mode);
|
||||
this.updateSubscribeMode().then(undefined);
|
||||
}
|
||||
|
||||
log_data() : EventChannelData {
|
||||
|
@ -810,7 +775,7 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const subscribed = this.flag_subscribed;
|
||||
const subscribed = this.isSubscribed();
|
||||
if (this.properties.channel_flag_password === true && !this.cached_password()) {
|
||||
return subscribed ? ClientIcon.ChannelYellowSubscribed : ClientIcon.ChannelYellow;
|
||||
} else if (!this.properties.channel_flag_maxclients_unlimited && this.clients().length >= this.properties.channel_maxclients) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import {EventType} from "tc-shared/ui/frames/log/Definitions";
|
|||
import {renderChannelTree} from "tc-shared/ui/tree/Controller";
|
||||
import {ChannelTreePopoutController} from "tc-shared/ui/tree/popout/Controller";
|
||||
import {Settings, settings} from "tc-shared/settings";
|
||||
import {ServerConnection} from "tc-backend/web/connection/ServerConnection";
|
||||
|
||||
export interface ChannelTreeEvents {
|
||||
/* general tree notified */
|
||||
|
@ -98,7 +99,7 @@ export class ChannelTree {
|
|||
private channelLast?: ChannelEntry;
|
||||
private channelFirst?: ChannelEntry;
|
||||
|
||||
constructor(client) {
|
||||
constructor(client: ConnectionHandler) {
|
||||
this.events = new Registry<ChannelTreeEvents>();
|
||||
this.events.enableDebug("channel-tree");
|
||||
|
||||
|
@ -222,7 +223,6 @@ export class ChannelTree {
|
|||
}
|
||||
|
||||
channel.channelTree = null;
|
||||
|
||||
batch_updates(BatchUpdateType.CHANNEL_TREE);
|
||||
try {
|
||||
if(!this.channels.remove(channel)) {
|
||||
|
@ -244,12 +244,12 @@ export class ChannelTree {
|
|||
}
|
||||
}
|
||||
|
||||
insertChannel(channel: ChannelEntry, previous: ChannelEntry, parent: ChannelEntry) {
|
||||
channel.channelTree = this;
|
||||
handleChannelCreated(previous: ChannelEntry, parent: ChannelEntry, channelId: number, channelName: string) : ChannelEntry {
|
||||
const channel = new ChannelEntry(this, channelId, channelName);
|
||||
this.channels.push(channel);
|
||||
|
||||
this.moveChannel(channel, previous, parent, false);
|
||||
this.events.fire("notify_channel_created", { channel: channel });
|
||||
return channel;
|
||||
}
|
||||
|
||||
findChannel(channelId: number) : ChannelEntry | undefined {
|
||||
|
@ -783,6 +783,7 @@ export class ChannelTree {
|
|||
spawnCreateChannel(parent?: ChannelEntry) {
|
||||
createChannelModal(this.client, undefined, parent, this.client.permissions, (properties?, permissions?) => {
|
||||
if(!properties) return;
|
||||
|
||||
properties["cpid"] = parent ? parent.channelId : 0;
|
||||
log.debug(LogCategory.CHANNEL, tr("Creating a new channel.\nProperties: %o\nPermissions: %o"), properties);
|
||||
this.client.serverConnection.send_command("channelcreate", properties).then(() => {
|
||||
|
@ -809,12 +810,6 @@ export class ChannelTree {
|
|||
}
|
||||
|
||||
return new Promise<ChannelEntry>(resolve => { resolve(channel); })
|
||||
}).then(channel => {
|
||||
this.client.log.log(EventType.CHANNEL_CREATE_OWN, {
|
||||
channel: channel.log_data(),
|
||||
creator: this.client.getClient().log_data(),
|
||||
});
|
||||
this.client.sound.play(Sound.CHANNEL_CREATED);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -831,16 +826,18 @@ export class ChannelTree {
|
|||
return this.channelFirst;
|
||||
}
|
||||
|
||||
unsubscribe_all_channels(subscribe_specified?: boolean) {
|
||||
if(!this.client.serverConnection || !this.client.serverConnection.connected())
|
||||
unsubscribe_all_channels() {
|
||||
if(!this.client.serverConnection || !this.client.serverConnection.connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.client.serverConnection.send_command('channelunsubscribeall').then(() => {
|
||||
const channels: number[] = [];
|
||||
for(const channel of this.channels) {
|
||||
if(channel.subscribe_mode == ChannelSubscribeMode.SUBSCRIBED)
|
||||
if(channel.getSubscriptionMode() == ChannelSubscribeMode.SUBSCRIBED) {
|
||||
channels.push(channel.getChannelId());
|
||||
}
|
||||
}
|
||||
|
||||
if(channels.length > 0) {
|
||||
this.client.serverConnection.send_command('channelsubscribe', channels.map(e => { return {cid: e}; })).catch(error => {
|
||||
|
@ -859,9 +856,10 @@ export class ChannelTree {
|
|||
this.client.serverConnection.send_command('channelsubscribeall').then(() => {
|
||||
const channels: number[] = [];
|
||||
for(const channel of this.channels) {
|
||||
if(channel.subscribe_mode == ChannelSubscribeMode.UNSUBSCRIBED)
|
||||
if(channel.getSubscriptionMode() == ChannelSubscribeMode.UNSUBSCRIBED) {
|
||||
channels.push(channel.getChannelId());
|
||||
}
|
||||
}
|
||||
|
||||
if(channels.length > 0) {
|
||||
this.client.serverConnection.send_command('channelunsubscribe', channels.map(e => { return {cid: e}; })).catch(error => {
|
||||
|
@ -877,17 +875,18 @@ export class ChannelTree {
|
|||
if(typeof root === "undefined")
|
||||
this.rootChannel().forEach(e => this.expand_channels(e));
|
||||
else {
|
||||
root.collapsed = false;
|
||||
for(const child of root.children(false))
|
||||
root.setCollapsed(false);
|
||||
for(const child of root.children(false)) {
|
||||
this.expand_channels(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collapse_channels(root?: ChannelEntry) {
|
||||
if(typeof root === "undefined")
|
||||
if(typeof root === "undefined") {
|
||||
this.rootChannel().forEach(e => this.collapse_channels(e));
|
||||
else {
|
||||
root.collapsed = true;
|
||||
} else {
|
||||
root.setCollapsed(true);
|
||||
for(const child of root.children(false))
|
||||
this.collapse_channels(child);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import {ViewReasonId} from "../../../ConnectionHandler";
|
|||
import * as React from "react";
|
||||
import {ServerEventLog} from "../../../ui/frames/log/ServerEventLog";
|
||||
|
||||
/* FIXME: Remove this! */
|
||||
export enum EventType {
|
||||
CONNECTION_BEGIN = "connection.begin",
|
||||
CONNECTION_HOSTNAME_RESOLVE = "connection.hostname.resolve",
|
||||
|
@ -55,9 +56,6 @@ export enum EventType {
|
|||
CHANNEL_CREATE = "channel.create",
|
||||
CHANNEL_DELETE = "channel.delete",
|
||||
|
||||
CHANNEL_CREATE_OWN = "channel.create.own",
|
||||
CHANNEL_DELETE_OWN = "channel.delete.own",
|
||||
|
||||
ERROR_CUSTOM = "error.custom",
|
||||
ERROR_PERMISSION = "error.permission",
|
||||
|
||||
|
@ -165,13 +163,19 @@ export namespace event {
|
|||
}
|
||||
|
||||
export type EventChannelCreate = {
|
||||
creator: EventClient;
|
||||
channel: EventChannelData;
|
||||
creator: EventClient,
|
||||
channel: EventChannelData,
|
||||
ownAction: boolean
|
||||
}
|
||||
|
||||
export type EventChannelToggle = {
|
||||
channel: EventChannelData
|
||||
}
|
||||
|
||||
export type EventChannelDelete = {
|
||||
deleter: EventClient;
|
||||
channel: EventChannelData;
|
||||
deleter: EventClient,
|
||||
channel: EventChannelData,
|
||||
ownAction: boolean
|
||||
}
|
||||
|
||||
export type EventConnectionConnected = {
|
||||
|
@ -310,11 +314,10 @@ export interface TypeInfo {
|
|||
"client.nickname.changed": event.EventClientNicknameChanged,
|
||||
"client.nickname.changed.own": event.EventClientNicknameChanged,
|
||||
|
||||
"channel.create": event.EventChannelCreate;
|
||||
"channel.delete": event.EventChannelDelete;
|
||||
|
||||
"channel.create.own": event.EventChannelCreate;
|
||||
"channel.delete.own": event.EventChannelDelete;
|
||||
"channel.create": event.EventChannelCreate,
|
||||
"channel.show": event.EventChannelToggle,
|
||||
"channel.hide": event.EventChannelToggle,
|
||||
"channel.delete": event.EventChannelDelete,
|
||||
|
||||
"client.poke.received": event.EventClientPokeReceived,
|
||||
"client.poke.send": event.EventClientPokeSend,
|
||||
|
|
|
@ -30,9 +30,9 @@ export function getRegisteredLogDispatchers() : TypeInfo[] {
|
|||
const ClientRenderer = (props: { client: EventClient, handlerId: string, braces?: boolean }) => (
|
||||
<ClientTag
|
||||
handlerId={props.handlerId}
|
||||
clientName={props.client.client_name}
|
||||
clientId={props.client.client_id}
|
||||
clientUniqueId={props.client.client_unique_id}
|
||||
clientName={props.client?.client_name || tr("Unknown")}
|
||||
clientId={props.client?.client_id || 0}
|
||||
clientUniqueId={props.client?.client_unique_id || "unknown"}
|
||||
className={cssStyle.clientEntry}
|
||||
/>
|
||||
);
|
||||
|
@ -40,8 +40,8 @@ const ClientRenderer = (props: { client: EventClient, handlerId: string, braces?
|
|||
const ChannelRenderer = (props: { channel: EventChannelData, handlerId: string, braces?: boolean }) => (
|
||||
<ChannelTag
|
||||
handlerId={props.handlerId}
|
||||
channelName={props.channel.channel_name}
|
||||
channelId={props.channel.channel_id}
|
||||
channelName={props.channel?.channel_name || tr("Unknown")}
|
||||
channelId={props.channel?.channel_id || 0}
|
||||
className={cssStyle.channelEntry}
|
||||
/>
|
||||
);
|
||||
|
@ -576,34 +576,52 @@ registerDispatcher(EventType.CONNECTION_COMMAND_ERROR,data => {
|
|||
)
|
||||
});
|
||||
|
||||
|
||||
registerDispatcher(EventType.CHANNEL_CREATE,(data, handlerId) => (
|
||||
registerDispatcher(EventType.CHANNEL_CREATE,(data, handlerId) => {
|
||||
if(data.ownAction) {
|
||||
return (
|
||||
<VariadicTranslatable text={"Channel {} has been created."}>
|
||||
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
|
||||
</VariadicTranslatable>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<VariadicTranslatable text={"Channel {} has been created by {}."}>
|
||||
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
|
||||
<ClientRenderer client={data.creator} handlerId={handlerId} />
|
||||
</VariadicTranslatable>
|
||||
));
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
registerDispatcher(EventType.CHANNEL_CREATE_OWN,(data, handlerId) => (
|
||||
<VariadicTranslatable text={"Channel {} has been created."}>
|
||||
registerDispatcher("channel.show",(data, handlerId) => (
|
||||
<VariadicTranslatable text={"Channel {} has appeared."}>
|
||||
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
|
||||
</VariadicTranslatable>
|
||||
));
|
||||
|
||||
registerDispatcher(EventType.CHANNEL_DELETE,(data, handlerId) => (
|
||||
registerDispatcher(EventType.CHANNEL_DELETE,(data, handlerId) => {
|
||||
if(data.ownAction) {
|
||||
return (
|
||||
<VariadicTranslatable text={"Channel {} has been deleted."}>
|
||||
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
|
||||
</VariadicTranslatable>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<VariadicTranslatable text={"Channel {} has been deleted by {}."}>
|
||||
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
|
||||
<ClientRenderer client={data.deleter} handlerId={handlerId} />
|
||||
</VariadicTranslatable>
|
||||
));
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
registerDispatcher(EventType.CHANNEL_DELETE_OWN,(data, handlerId) => (
|
||||
<VariadicTranslatable text={"Channel {} has been deleted."}>
|
||||
registerDispatcher("channel.hide",(data, handlerId) => (
|
||||
<VariadicTranslatable text={"Channel {} has disappeared."}>
|
||||
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
|
||||
</VariadicTranslatable>
|
||||
));
|
||||
|
||||
|
||||
registerDispatcher(EventType.CLIENT_POKE_SEND,(data, handlerId) => (
|
||||
<VariadicTranslatable text={"You poked {}."}>
|
||||
<ClientRenderer client={data.target} handlerId={handlerId} />
|
||||
|
|
|
@ -102,7 +102,7 @@ function apply_general(container: JQuery, channel: ChannelEntry) {
|
|||
{
|
||||
const tag = container.find(".current-clients .value").empty();
|
||||
|
||||
if (channel.flag_subscribed) {
|
||||
if (channel.isSubscribed()) {
|
||||
const current = channel.clients().length;
|
||||
let channel_limit = tr("Unlimited");
|
||||
if (!channel.properties.channel_flag_maxclients_unlimited)
|
||||
|
|
|
@ -369,7 +369,7 @@ class ChannelTreeController {
|
|||
|
||||
const buildSubTree = (channel: ChannelEntry, depth: number) => {
|
||||
entries.push({ type: "channel", entryId: channel.uniqueEntryId, depth: depth });
|
||||
if(channel.collapsed) {
|
||||
if(channel.isCollapsed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ class ChannelTreeController {
|
|||
this.events.fire_react("notify_channel_info", {
|
||||
treeEntryId: channel.uniqueEntryId,
|
||||
info: {
|
||||
collapsedState: channel.child_channel_head || channel.channelClientsOrdered().length > 0 ? channel.collapsed ? "collapsed" : "expended" : "unset",
|
||||
collapsedState: channel.child_channel_head || channel.channelClientsOrdered().length > 0 ? channel.isCollapsed() ? "collapsed" : "expended" : "unset",
|
||||
name: channel.parsed_channel_name.text,
|
||||
nameStyle: channel.parsed_channel_name.alignment
|
||||
}
|
||||
|
@ -658,7 +658,7 @@ export function initializeChannelTreeController(events: Registry<ChannelTreeUIEv
|
|||
return;
|
||||
}
|
||||
|
||||
entry.collapsed = event.state === "collapsed";
|
||||
entry.setCollapsed(event.state === "collapsed");
|
||||
});
|
||||
|
||||
events.on("action_select", event => {
|
||||
|
|
Loading…
Reference in New Issue