Properly logging channel creations, deletions, shows and hides

canary
WolverinDEV 2020-12-04 13:36:34 +01:00
parent 409f7489c4
commit 92191b259b
9 changed files with 223 additions and 180 deletions

View File

@ -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

View File

@ -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" });
}

View File

@ -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,36 +292,37 @@ 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;
}
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 :)
}
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? */
}
}
const channel = tree.handleChannelCreated(previousChannel, parentChannel, channelId, channelName);
let updates: {
key: string,
value: 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,9 +1042,10 @@ 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 });
}
}
}

View File

@ -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;
}
if(unsubscribe) {
if(connection) {
await connection.send_command('channelunsubscribe', {
'cid': this.getChannelId()
});
} else {
this.flag_subscribed = false;
}
for(const client of this.clients(false)) {
this.channelTree.deleteClient(client, { serverLeave: false, reason: ViewReasonId.VREASON_SYSTEM });
}
}
this.setSubscriptionMode(inherited_subscription_mode ? ChannelSubscribeMode.INHERITED : ChannelSubscribeMode.UNSUBSCRIBED);
}
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;
isCollapsed() : boolean {
return this.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) {

View File

@ -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,15 +826,17 @@ 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) {
@ -859,8 +856,9 @@ 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) {
@ -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);
}

View File

@ -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,

View File

@ -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) => {
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,(data, handlerId) => (
<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) => (
<VariadicTranslatable text={"Channel {} has been deleted by {}."}>
<ChannelRenderer channel={data.channel} handlerId={handlerId} />
<ClientRenderer client={data.deleter} handlerId={handlerId} />
</VariadicTranslatable>
));
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} />

View File

@ -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)

View File

@ -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 => {