Globally rendering the app via React
This commit is contained in:
parent
0dbf991e36
commit
2211da243d
22 changed files with 447 additions and 333 deletions
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
/* FIXME: Resolve variable usage! */
|
/* FIXME: Resolve variable usage! */
|
||||||
html:root {
|
html:root {
|
||||||
|
--side-background: #353535;
|
||||||
--side-info-background: #2e2e2e;
|
--side-info-background: #2e2e2e;
|
||||||
--side-info-shadow: rgba(0, 0, 0, 0.25);
|
--side-info-shadow: rgba(0, 0, 0, 0.25);
|
||||||
--side-info-title: #8b8b8b;
|
--side-info-title: #8b8b8b;
|
||||||
|
|
|
@ -7,8 +7,6 @@ $animation_length: .5s;
|
||||||
html:root {
|
html:root {
|
||||||
--app-background: #1e1e1e;
|
--app-background: #1e1e1e;
|
||||||
|
|
||||||
--control-bar-background: #454545;
|
|
||||||
|
|
||||||
--chat-background: #353535;
|
--chat-background: #353535;
|
||||||
--channel-tree-background: #353535;
|
--channel-tree-background: #353535;
|
||||||
--server-log-background: #353535;
|
--server-log-background: #353535;
|
||||||
|
@ -20,201 +18,16 @@ html:root {
|
||||||
--channel-chat-seperator-selected: #707070;
|
--channel-chat-seperator-selected: #707070;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app {
|
.hide-small {
|
||||||
min-width: 600px;
|
|
||||||
min-height: 330px;
|
|
||||||
|
|
||||||
padding: 5px;
|
|
||||||
|
|
||||||
.container-app-main {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
min-height: 500px;
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
|
|
||||||
.container-channel-chat {
|
|
||||||
height: 80%; /* "default" settings */
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
min-height: 27em; /* fits with the music bot interface */
|
|
||||||
min-width: 100px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
height: 100%;
|
|
||||||
min-height: 250px;
|
|
||||||
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .container-channel-tree {
|
|
||||||
width: 50%; /* "default" settings */
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
background: var(--channel-tree-background);
|
|
||||||
min-width: 200px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
min-height: 100px;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
> .hostbanner {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
max-height: 9em; /* same size as the info pannel */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .channel-tree {
|
|
||||||
min-height: 5em;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
.channel-tree-container {
|
|
||||||
height: 100%;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .container-chat {
|
|
||||||
width: 50%; /* "default" settings */
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
background: var(--chat-background);
|
|
||||||
min-width: 350px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
> .container-bottom {
|
|
||||||
height: 20%;
|
|
||||||
|
|
||||||
min-height: 1.5em;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
> .container-server-log {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-height: 0;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
border-radius: 5px 5px 0 0;
|
|
||||||
|
|
||||||
padding-right: 5px;
|
|
||||||
padding-left: 5px;
|
|
||||||
|
|
||||||
background: var(--server-log-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
> .container-footer {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
height: 1.5em;
|
|
||||||
|
|
||||||
background: var(--footer-background);
|
|
||||||
color: var(--footer-text);
|
|
||||||
|
|
||||||
border-radius: 0 0 5px 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-top: 2px;
|
|
||||||
|
|
||||||
-webkit-box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
|
|
||||||
-moz-box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
|
|
||||||
box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
> span {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
margin-right: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a[href], a[href]:visited {
|
|
||||||
color: var(--footer-text)!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-control-bar {
|
|
||||||
z-index: 200;
|
|
||||||
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
height: 2em;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
background-color: var(--control-bar-background);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide-small {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity $animation_length linear;
|
transition: opacity $animation_length linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-small {
|
.show-small {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity $animation_length linear;
|
transition: opacity $animation_length linear;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-container {
|
.app-container {
|
||||||
|
|
|
@ -7,36 +7,6 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script class="jsrender-template" id="tmpl_main" type="text/html">
|
<script class="jsrender-template" id="tmpl_main" type="text/html">
|
||||||
<div class="app-container">
|
|
||||||
<div class="app">
|
|
||||||
<!-- navigation bar -->
|
|
||||||
<div class="container-control-bar">
|
|
||||||
<div id="control_bar" class="control_bar">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="container-connection-handlers" id="connection-handler-list"></div>
|
|
||||||
<div class="container-app-main">
|
|
||||||
<div class="container-channel-video" id="channel-video"></div>
|
|
||||||
<div class="container-channel-chat">
|
|
||||||
<!-- Channel tree -->
|
|
||||||
<div class="container-channel-tree">
|
|
||||||
<div class="hostbanner" id="hostbanner"></div>
|
|
||||||
<div class="channel-tree" id="channelTree"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container-seperator vertical" seperator-id="seperator-channel-chat"></div>
|
|
||||||
<!-- Chat window -->
|
|
||||||
<div class="container-chat" id="chat"></div>
|
|
||||||
</div>
|
|
||||||
<div class="container-seperator horizontal" seperator-id="seperator-main-log"></div>
|
|
||||||
<div class="container-bottom">
|
|
||||||
<div class="container-server-log" id="server-log"></div>
|
|
||||||
<div class="container-footer" id="container-footer">
|
|
||||||
</div>
|
|
||||||
</div> <!-- Selection info -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="contextMenu" class="context-menu"></div>
|
<div id="contextMenu" class="context-menu"></div>
|
||||||
<div class="overlay-image-preview hidden" id="overlay-image-preview">
|
<div class="overlay-image-preview hidden" id="overlay-image-preview">
|
||||||
<div class="container-menu-bar">
|
<div class="container-menu-bar">
|
||||||
|
|
|
@ -133,7 +133,7 @@ export interface ConnectParameters {
|
||||||
export class ConnectionHandler {
|
export class ConnectionHandler {
|
||||||
readonly handlerId: string;
|
readonly handlerId: string;
|
||||||
|
|
||||||
private readonly event_registry: Registry<ConnectionEvents>;
|
private readonly events_: Registry<ConnectionEvents>;
|
||||||
channelTree: ChannelTree;
|
channelTree: ChannelTree;
|
||||||
|
|
||||||
connection_state: ConnectionState = ConnectionState.UNCONNECTED;
|
connection_state: ConnectionState = ConnectionState.UNCONNECTED;
|
||||||
|
@ -159,13 +159,13 @@ export class ConnectionHandler {
|
||||||
|
|
||||||
private clientInfoManager: SelectedClientInfo;
|
private clientInfoManager: SelectedClientInfo;
|
||||||
|
|
||||||
private _clientId: number = 0;
|
private localClientId: number = 0;
|
||||||
private localClient: LocalClientEntry;
|
private localClient: LocalClientEntry;
|
||||||
|
|
||||||
private _reconnect_timer: number;
|
private autoReconnectTimer: number;
|
||||||
private _reconnect_attempt: boolean = false;
|
private autoReconnectAttempt: boolean = false;
|
||||||
|
|
||||||
private _connect_initialize_id: number = 1;
|
private connectAttemptId: number = 1;
|
||||||
private echoTestRunning = false;
|
private echoTestRunning = false;
|
||||||
|
|
||||||
private pluginCmdRegistry: PluginCmdRegistry;
|
private pluginCmdRegistry: PluginCmdRegistry;
|
||||||
|
@ -188,8 +188,8 @@ export class ConnectionHandler {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.handlerId = guid();
|
this.handlerId = guid();
|
||||||
this.event_registry = new Registry<ConnectionEvents>();
|
this.events_ = new Registry<ConnectionEvents>();
|
||||||
this.event_registry.enableDebug("connection-handler");
|
this.events_.enableDebug("connection-handler");
|
||||||
|
|
||||||
this.settings = new ServerSettings();
|
this.settings = new ServerSettings();
|
||||||
|
|
||||||
|
@ -225,10 +225,10 @@ export class ConnectionHandler {
|
||||||
this.localClient = new LocalClientEntry(this);
|
this.localClient = new LocalClientEntry(this);
|
||||||
this.localClient.channelTree = this.channelTree;
|
this.localClient.channelTree = this.channelTree;
|
||||||
|
|
||||||
this.event_registry.register_handler(this);
|
this.events_.register_handler(this);
|
||||||
this.pluginCmdRegistry.registerHandler(new W2GPluginCmdHandler());
|
this.pluginCmdRegistry.registerHandler(new W2GPluginCmdHandler());
|
||||||
|
|
||||||
this.events().fire("notify_handler_initialized");
|
this.events_.fire("notify_handler_initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize_client_state(source?: ConnectionHandler) {
|
initialize_client_state(source?: ConnectionHandler) {
|
||||||
|
@ -242,12 +242,12 @@ export class ConnectionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
events() : Registry<ConnectionEvents> {
|
events() : Registry<ConnectionEvents> {
|
||||||
return this.event_registry;
|
return this.events_;
|
||||||
}
|
}
|
||||||
|
|
||||||
async startConnection(addr: string, profile: ConnectionProfile, user_action: boolean, parameters: ConnectParameters) {
|
async startConnection(addr: string, profile: ConnectionProfile, user_action: boolean, parameters: ConnectParameters) {
|
||||||
this.cancel_reconnect(false);
|
this.cancel_reconnect(false);
|
||||||
this._reconnect_attempt = parameters.auto_reconnect_attempt || false;
|
this.autoReconnectAttempt = parameters.auto_reconnect_attempt || false;
|
||||||
this.handleDisconnect(DisconnectReason.REQUESTED);
|
this.handleDisconnect(DisconnectReason.REQUESTED);
|
||||||
|
|
||||||
let server_address: ServerAddress = {
|
let server_address: ServerAddress = {
|
||||||
|
@ -298,11 +298,11 @@ export class ConnectionHandler {
|
||||||
if(server_address.host === "localhost") {
|
if(server_address.host === "localhost") {
|
||||||
server_address.host = "127.0.0.1";
|
server_address.host = "127.0.0.1";
|
||||||
} else if(dns.supported() && !server_address.host.match(Regex.IP_V4) && !server_address.host.match(Regex.IP_V6)) {
|
} else if(dns.supported() && !server_address.host.match(Regex.IP_V4) && !server_address.host.match(Regex.IP_V6)) {
|
||||||
const id = ++this._connect_initialize_id;
|
const id = ++this.connectAttemptId;
|
||||||
this.log.log("connection.hostname.resolve", {});
|
this.log.log("connection.hostname.resolve", {});
|
||||||
try {
|
try {
|
||||||
const resolved = await dns.resolve_address(server_address, { timeout: 5000 }) || {} as any;
|
const resolved = await dns.resolve_address(server_address, { timeout: 5000 }) || {} as any;
|
||||||
if(id != this._connect_initialize_id)
|
if(id != this.connectAttemptId)
|
||||||
return; /* we're old */
|
return; /* we're old */
|
||||||
|
|
||||||
server_address.host = typeof(resolved.target_ip) === "string" ? resolved.target_ip : server_address.host;
|
server_address.host = typeof(resolved.target_ip) === "string" ? resolved.target_ip : server_address.host;
|
||||||
|
@ -314,7 +314,7 @@ export class ConnectionHandler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
if(id != this._connect_initialize_id)
|
if(id != this.connectAttemptId)
|
||||||
return; /* we're old */
|
return; /* we're old */
|
||||||
|
|
||||||
this.handleDisconnect(DisconnectReason.DNS_FAILED, error);
|
this.handleDisconnect(DisconnectReason.DNS_FAILED, error);
|
||||||
|
@ -348,7 +348,7 @@ export class ConnectionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
getClient() : LocalClientEntry { return this.localClient; }
|
getClient() : LocalClientEntry { return this.localClient; }
|
||||||
getClientId() { return this._clientId; }
|
getClientId() { return this.localClientId; }
|
||||||
|
|
||||||
getPrivateConversations() : PrivateConversationManager {
|
getPrivateConversations() : PrivateConversationManager {
|
||||||
return this.privateConversations;
|
return this.privateConversations;
|
||||||
|
@ -371,7 +371,7 @@ export class ConnectionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeLocalClient(clientId: number, acceptedName: string) {
|
initializeLocalClient(clientId: number, acceptedName: string) {
|
||||||
this._clientId = clientId;
|
this.localClientId = clientId;
|
||||||
this.localClient["_clientId"] = clientId;
|
this.localClient["_clientId"] = clientId;
|
||||||
|
|
||||||
this.channelTree.registerClient(this.localClient);
|
this.channelTree.registerClient(this.localClient);
|
||||||
|
@ -477,7 +477,7 @@ export class ConnectionHandler {
|
||||||
|
|
||||||
private _certificate_modal: Modal;
|
private _certificate_modal: Modal;
|
||||||
handleDisconnect(type: DisconnectReason, data: any = {}) {
|
handleDisconnect(type: DisconnectReason, data: any = {}) {
|
||||||
this._connect_initialize_id++;
|
this.connectAttemptId++;
|
||||||
|
|
||||||
let auto_reconnect = false;
|
let auto_reconnect = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -498,7 +498,7 @@ export class ConnectionHandler {
|
||||||
this.sound.play(Sound.CONNECTION_REFUSED);
|
this.sound.play(Sound.CONNECTION_REFUSED);
|
||||||
break;
|
break;
|
||||||
case DisconnectReason.CONNECT_FAILURE:
|
case DisconnectReason.CONNECT_FAILURE:
|
||||||
if(this._reconnect_attempt) {
|
if(this.autoReconnectAttempt) {
|
||||||
auto_reconnect = true;
|
auto_reconnect = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -574,7 +574,7 @@ export class ConnectionHandler {
|
||||||
break;
|
break;
|
||||||
case DisconnectReason.CONNECTION_CLOSED:
|
case DisconnectReason.CONNECTION_CLOSED:
|
||||||
log.error(LogCategory.CLIENT, tr("Lost connection to remote server!"));
|
log.error(LogCategory.CLIENT, tr("Lost connection to remote server!"));
|
||||||
if(!this._reconnect_attempt) {
|
if(!this.autoReconnectAttempt) {
|
||||||
createErrorModal(
|
createErrorModal(
|
||||||
tr("Connection closed"),
|
tr("Connection closed"),
|
||||||
tr("The connection was closed by remote host")
|
tr("The connection was closed by remote host")
|
||||||
|
@ -683,8 +683,8 @@ export class ConnectionHandler {
|
||||||
const server_address = this.serverConnection.remote_address();
|
const server_address = this.serverConnection.remote_address();
|
||||||
const profile = this.serverConnection.handshake_handler().profile;
|
const profile = this.serverConnection.handshake_handler().profile;
|
||||||
|
|
||||||
this._reconnect_timer = setTimeout(() => {
|
this.autoReconnectTimer = setTimeout(() => {
|
||||||
this._reconnect_timer = undefined;
|
this.autoReconnectTimer = undefined;
|
||||||
this.log.log("reconnect.execute", {});
|
this.log.log("reconnect.execute", {});
|
||||||
log.info(LogCategory.NETWORKING, tr("Reconnecting..."));
|
log.info(LogCategory.NETWORKING, tr("Reconnecting..."));
|
||||||
|
|
||||||
|
@ -696,16 +696,16 @@ export class ConnectionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel_reconnect(log_event: boolean) {
|
cancel_reconnect(log_event: boolean) {
|
||||||
if(this._reconnect_timer) {
|
if(this.autoReconnectTimer) {
|
||||||
if(log_event) this.log.log("reconnect.canceled", {});
|
if(log_event) this.log.log("reconnect.canceled", {});
|
||||||
clearTimeout(this._reconnect_timer);
|
clearTimeout(this.autoReconnectTimer);
|
||||||
this._reconnect_timer = undefined;
|
this.autoReconnectTimer = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private on_connection_state_changed(old_state: ConnectionState, new_state: ConnectionState) {
|
private on_connection_state_changed(old_state: ConnectionState, new_state: ConnectionState) {
|
||||||
console.log("From %s to %s", ConnectionState[old_state], ConnectionState[new_state]);
|
console.log("From %s to %s", ConnectionState[old_state], ConnectionState[new_state]);
|
||||||
this.event_registry.fire("notify_connection_state_changed", {
|
this.events_.fire("notify_connection_state_changed", {
|
||||||
oldState: old_state,
|
oldState: old_state,
|
||||||
newState: new_state
|
newState: new_state
|
||||||
});
|
});
|
||||||
|
@ -805,14 +805,14 @@ export class ConnectionHandler {
|
||||||
if(shouldRecord || this.echoTestRunning) {
|
if(shouldRecord || this.echoTestRunning) {
|
||||||
if(this.getInputHardwareState() !== InputHardwareState.START_FAILED) {
|
if(this.getInputHardwareState() !== InputHardwareState.START_FAILED) {
|
||||||
this.startVoiceRecorder(Date.now() - this._last_record_error_popup > 10 * 1000).then(() => {
|
this.startVoiceRecorder(Date.now() - this._last_record_error_popup > 10 * 1000).then(() => {
|
||||||
this.event_registry.fire("notify_state_updated", { state: "microphone" });
|
this.events_.fire("notify_state_updated", { state: "microphone" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentInput.stop().catch(error => {
|
currentInput.stop().catch(error => {
|
||||||
logWarn(LogCategory.AUDIO, tr("Failed to stop the microphone input recorder: %o"), error);
|
logWarn(LogCategory.AUDIO, tr("Failed to stop the microphone input recorder: %o"), error);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.event_registry.fire("notify_state_updated", { state: "microphone" });
|
this.events_.fire("notify_state_updated", { state: "microphone" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1017,7 +1017,7 @@ export class ConnectionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
this.event_registry.unregister_handler(this);
|
this.events_.unregister_handler(this);
|
||||||
this.cancel_reconnect(true);
|
this.cancel_reconnect(true);
|
||||||
|
|
||||||
this.pluginCmdRegistry?.destroy();
|
this.pluginCmdRegistry?.destroy();
|
||||||
|
@ -1093,7 +1093,7 @@ export class ConnectionHandler {
|
||||||
this.sound.play(muted ? Sound.MICROPHONE_MUTED : Sound.MICROPHONE_ACTIVATED);
|
this.sound.play(muted ? Sound.MICROPHONE_MUTED : Sound.MICROPHONE_ACTIVATED);
|
||||||
}
|
}
|
||||||
this.update_voice_status();
|
this.update_voice_status();
|
||||||
this.event_registry.fire("notify_state_updated", { state: "microphone" });
|
this.events_.fire("notify_state_updated", { state: "microphone" });
|
||||||
}
|
}
|
||||||
toggleMicrophone() { this.setMicrophoneMuted(!this.isMicrophoneMuted()); }
|
toggleMicrophone() { this.setMicrophoneMuted(!this.isMicrophoneMuted()); }
|
||||||
|
|
||||||
|
@ -1104,7 +1104,7 @@ export class ConnectionHandler {
|
||||||
if(this.client_status.output_muted === muted) return;
|
if(this.client_status.output_muted === muted) return;
|
||||||
if(muted && !dontPlaySound) this.sound.play(Sound.SOUND_MUTED); /* play the sound *before* we're setting the muted state */
|
if(muted && !dontPlaySound) this.sound.play(Sound.SOUND_MUTED); /* play the sound *before* we're setting the muted state */
|
||||||
this.client_status.output_muted = muted;
|
this.client_status.output_muted = muted;
|
||||||
this.event_registry.fire("notify_state_updated", { state: "speaker" });
|
this.events_.fire("notify_state_updated", { state: "speaker" });
|
||||||
if(!muted && !dontPlaySound) this.sound.play(Sound.SOUND_ACTIVATED); /* play the sound *after* we're setting we've unmuted the sound */
|
if(!muted && !dontPlaySound) this.sound.play(Sound.SOUND_ACTIVATED); /* play the sound *after* we're setting we've unmuted the sound */
|
||||||
this.update_voice_status();
|
this.update_voice_status();
|
||||||
this.serverConnection.getVoiceConnection().stopAllVoiceReplays();
|
this.serverConnection.getVoiceConnection().stopAllVoiceReplays();
|
||||||
|
@ -1129,7 +1129,7 @@ export class ConnectionHandler {
|
||||||
} else {
|
} else {
|
||||||
this.channelTree.unsubscribe_all_channels();
|
this.channelTree.unsubscribe_all_channels();
|
||||||
}
|
}
|
||||||
this.event_registry.fire("notify_state_updated", { state: "subscribe" });
|
this.events_.fire("notify_state_updated", { state: "subscribe" });
|
||||||
}
|
}
|
||||||
|
|
||||||
isSubscribeToAllChannels() : boolean { return this.client_status.channel_subscribe_all; }
|
isSubscribeToAllChannels() : boolean { return this.client_status.channel_subscribe_all; }
|
||||||
|
@ -1156,7 +1156,7 @@ export class ConnectionHandler {
|
||||||
this.log.log("error.custom", {message: tr("Failed to update away status.")});
|
this.log.log("error.custom", {message: tr("Failed to update away status.")});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.event_registry.fire("notify_state_updated", {
|
this.events_.fire("notify_state_updated", {
|
||||||
state: "away"
|
state: "away"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1168,7 +1168,7 @@ export class ConnectionHandler {
|
||||||
this.client_status.queries_visible = flag;
|
this.client_status.queries_visible = flag;
|
||||||
this.channelTree.toggle_server_queries(flag);
|
this.channelTree.toggle_server_queries(flag);
|
||||||
|
|
||||||
this.event_registry.fire("notify_state_updated", {
|
this.events_.fire("notify_state_updated", {
|
||||||
state: "query"
|
state: "query"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1183,7 +1183,7 @@ export class ConnectionHandler {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.inputHardwareState = state;
|
this.inputHardwareState = state;
|
||||||
this.event_registry.fire("notify_state_updated", { state: "microphone" });
|
this.events_.fire("notify_state_updated", { state: "microphone" });
|
||||||
}
|
}
|
||||||
|
|
||||||
hasOutputHardware() : boolean { return true; }
|
hasOutputHardware() : boolean { return true; }
|
||||||
|
|
|
@ -10,6 +10,8 @@ import {ServerEventLogController} from "tc-shared/ui/frames/log/Controller";
|
||||||
import {ServerLogFrame} from "tc-shared/ui/frames/log/Renderer";
|
import {ServerLogFrame} from "tc-shared/ui/frames/log/Renderer";
|
||||||
import {HostBannerController} from "tc-shared/ui/frames/HostBannerController";
|
import {HostBannerController} from "tc-shared/ui/frames/HostBannerController";
|
||||||
import {HostBanner} from "tc-shared/ui/frames/HostBannerRenderer";
|
import {HostBanner} from "tc-shared/ui/frames/HostBannerRenderer";
|
||||||
|
import {ChannelTreeView} from "tc-shared/ui/tree/RendererView";
|
||||||
|
import {ChannelTreeRenderer} from "tc-shared/ui/tree/Renderer";
|
||||||
|
|
||||||
export let server_connections: ConnectionManager;
|
export let server_connections: ConnectionManager;
|
||||||
|
|
||||||
|
@ -34,15 +36,16 @@ export class ConnectionManager {
|
||||||
private connection_handlers: ConnectionHandler[] = [];
|
private connection_handlers: ConnectionHandler[] = [];
|
||||||
private active_handler: ConnectionHandler | undefined;
|
private active_handler: ConnectionHandler | undefined;
|
||||||
|
|
||||||
private _container_channel_tree: JQuery;
|
|
||||||
private containerChannelVideo: ReplaceableContainer;
|
private containerChannelVideo: ReplaceableContainer;
|
||||||
private containerFooter: HTMLDivElement;
|
private containerFooter: HTMLDivElement;
|
||||||
private containerServerLog: HTMLDivElement;
|
private containerServerLog: HTMLDivElement;
|
||||||
private containerHostBanner: HTMLDivElement;
|
private containerHostBanner: HTMLDivElement;
|
||||||
|
private containerChannelTree: HTMLDivElement;
|
||||||
|
|
||||||
private sideBarController: SideBarController;
|
/* FIXME: Move these controller out! */
|
||||||
private serverLogController: ServerEventLogController;
|
sideBarController: SideBarController;
|
||||||
private hostBannerController: HostBannerController;
|
serverLogController: ServerEventLogController;
|
||||||
|
hostBannerController: HostBannerController;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.event_registry = new Registry<ConnectionManagerEvents>();
|
this.event_registry = new Registry<ConnectionManagerEvents>();
|
||||||
|
@ -56,13 +59,14 @@ export class ConnectionManager {
|
||||||
this.containerServerLog = document.getElementById("server-log") as HTMLDivElement;
|
this.containerServerLog = document.getElementById("server-log") as HTMLDivElement;
|
||||||
this.containerFooter = document.getElementById("container-footer") as HTMLDivElement;
|
this.containerFooter = document.getElementById("container-footer") as HTMLDivElement;
|
||||||
this.containerHostBanner = document.getElementById("hostbanner") as HTMLDivElement;
|
this.containerHostBanner = document.getElementById("hostbanner") as HTMLDivElement;
|
||||||
this._container_channel_tree = $("#channelTree");
|
this.containerChannelTree = document.getElementById("channelTree") as HTMLDivElement;
|
||||||
|
|
||||||
this.sideBarController.renderInto(document.getElementById("chat") as HTMLDivElement);
|
this.sideBarController.renderInto(document.getElementById("chat") as HTMLDivElement);
|
||||||
this.set_active_connection(undefined);
|
this.set_active_connection(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeReactComponents() {
|
initializeReactComponents() {
|
||||||
|
return;
|
||||||
ReactDOM.render(React.createElement(FooterRenderer), this.containerFooter);
|
ReactDOM.render(React.createElement(FooterRenderer), this.containerFooter);
|
||||||
ReactDOM.render(React.createElement(ServerLogFrame, { events: this.serverLogController.events }), this.containerServerLog);
|
ReactDOM.render(React.createElement(ServerLogFrame, { events: this.serverLogController.events }), this.containerServerLog);
|
||||||
ReactDOM.render(React.createElement(HostBanner, { events: this.hostBannerController.uiEvents }), this.containerHostBanner);
|
ReactDOM.render(React.createElement(HostBanner, { events: this.hostBannerController.uiEvents }), this.containerHostBanner);
|
||||||
|
@ -129,12 +133,15 @@ export class ConnectionManager {
|
||||||
this.serverLogController.setConnectionHandler(handler);
|
this.serverLogController.setConnectionHandler(handler);
|
||||||
this.hostBannerController.setConnectionHandler(handler);
|
this.hostBannerController.setConnectionHandler(handler);
|
||||||
|
|
||||||
this._container_channel_tree.children().detach();
|
/*
|
||||||
this.containerChannelVideo.replaceWith(handler?.video_frame.getContainer());
|
this.containerChannelVideo.replaceWith(handler?.video_frame.getContainer());
|
||||||
|
|
||||||
if(handler) {
|
if(handler) {
|
||||||
this._container_channel_tree.append(handler.channelTree.tag_tree());
|
ReactDOM.render(React.createElement(ChannelTreeRenderer, { handlerId: handler.handlerId, events: handler.channelTree.mainTreeUiEvents }), this.containerChannelTree);
|
||||||
|
} else {
|
||||||
|
ReactDOM.render(undefined, this.containerChannelTree);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const old_handler = this.active_handler;
|
const old_handler = this.active_handler;
|
||||||
this.active_handler = handler;
|
this.active_handler = handler;
|
||||||
|
|
|
@ -47,15 +47,11 @@ import "./connection/rtc/Connection";
|
||||||
import "./connection/rtc/video/Connection";
|
import "./connection/rtc/video/Connection";
|
||||||
import "./video/VideoSource";
|
import "./video/VideoSource";
|
||||||
import "./media/Video";
|
import "./media/Video";
|
||||||
|
import "./ui/AppController";
|
||||||
|
|
||||||
import {defaultConnectProfile, findConnectProfile} from "tc-shared/profiles/ConnectionProfile";
|
import {defaultConnectProfile, findConnectProfile} from "tc-shared/profiles/ConnectionProfile";
|
||||||
import {server_connections} from "tc-shared/ConnectionManager";
|
import {server_connections} from "tc-shared/ConnectionManager";
|
||||||
import {initializeConnectionUIList} from "tc-shared/ui/frames/connection-handler-list/Controller";
|
|
||||||
import ContextMenuEvent = JQuery.ContextMenuEvent;
|
import ContextMenuEvent = JQuery.ContextMenuEvent;
|
||||||
import {Registry} from "tc-shared/events";
|
|
||||||
import {ControlBarEvents} from "tc-shared/ui/frames/control-bar/Definitions";
|
|
||||||
import {ControlBar2} from "tc-shared/ui/frames/control-bar/Renderer";
|
|
||||||
import {initializeControlBarController} from "tc-shared/ui/frames/control-bar/Controller";
|
|
||||||
|
|
||||||
let preventWelcomeUI = false;
|
let preventWelcomeUI = false;
|
||||||
async function initialize() {
|
async function initialize() {
|
||||||
|
@ -71,15 +67,7 @@ async function initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initialize_app() {
|
async function initialize_app() {
|
||||||
initializeConnectionUIList();
|
|
||||||
|
|
||||||
global_ev_handler.initialize(global_client_actions);
|
global_ev_handler.initialize(global_client_actions);
|
||||||
{
|
|
||||||
const events = new Registry<ControlBarEvents>()
|
|
||||||
initializeControlBarController(events, "main");
|
|
||||||
ReactDOM.render(<ControlBar2 events={events} />, $(".container-control-bar")[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
name: "settings init",
|
name: "settings init",
|
||||||
|
@ -88,8 +76,9 @@ async function initialize_app() {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(!aplayer.initialize())
|
if(!aplayer.initialize()) {
|
||||||
console.warn(tr("Failed to initialize audio controller!"));
|
console.warn(tr("Failed to initialize audio controller!"));
|
||||||
|
}
|
||||||
|
|
||||||
aplayer.on_ready(() => {
|
aplayer.on_ready(() => {
|
||||||
if(aplayer.set_master_volume)
|
if(aplayer.set_master_volume)
|
||||||
|
|
|
@ -20,13 +20,14 @@ import {spawnBanClient} from "tc-shared/ui/modal/ModalBanClient";
|
||||||
import {formatMessage} from "tc-shared/ui/frames/chat";
|
import {formatMessage} from "tc-shared/ui/frames/chat";
|
||||||
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
||||||
import {tr, tra} from "tc-shared/i18n/localize";
|
import {tr, tra} from "tc-shared/i18n/localize";
|
||||||
import {renderChannelTree} from "tc-shared/ui/tree/Controller";
|
import {initializeChannelTreeUiEvents, renderChannelTree} from "tc-shared/ui/tree/Controller";
|
||||||
import {ChannelTreePopoutController} from "tc-shared/ui/tree/popout/Controller";
|
import {ChannelTreePopoutController} from "tc-shared/ui/tree/popout/Controller";
|
||||||
import {Settings, settings} from "tc-shared/settings";
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
import {ClientIcon} from "svg-sprites/client-icons";
|
import {ClientIcon} from "svg-sprites/client-icons";
|
||||||
|
|
||||||
import "./EntryTagsHandler";
|
import "./EntryTagsHandler";
|
||||||
import {spawnChannelEditNew} from "tc-shared/ui/modal/channel-edit/Controller";
|
import {spawnChannelEditNew} from "tc-shared/ui/modal/channel-edit/Controller";
|
||||||
|
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
|
||||||
|
|
||||||
export interface ChannelTreeEvents {
|
export interface ChannelTreeEvents {
|
||||||
/* general tree notified */
|
/* general tree notified */
|
||||||
|
@ -96,7 +97,11 @@ export class ChannelTree {
|
||||||
|
|
||||||
readonly popoutController: ChannelTreePopoutController;
|
readonly popoutController: ChannelTreePopoutController;
|
||||||
|
|
||||||
private readonly tagContainer: JQuery;
|
/*
|
||||||
|
* We're constantly keeping the UI controller used (IDK yet how fast event attachment/detachment is)
|
||||||
|
* The main background is to speed up server tab switching.
|
||||||
|
*/
|
||||||
|
mainTreeUiEvents: Registry<ChannelTreeUIEvents>;
|
||||||
|
|
||||||
private selectedEntry: ChannelTreeEntry<any> | undefined;
|
private selectedEntry: ChannelTreeEntry<any> | undefined;
|
||||||
private showQueries: boolean;
|
private showQueries: boolean;
|
||||||
|
@ -112,8 +117,7 @@ export class ChannelTree {
|
||||||
this.server = new ServerEntry(this, "undefined", undefined);
|
this.server = new ServerEntry(this, "undefined", undefined);
|
||||||
this.popoutController = new ChannelTreePopoutController(this);
|
this.popoutController = new ChannelTreePopoutController(this);
|
||||||
|
|
||||||
this.tagContainer = $.spawn("div").addClass("channel-tree-container");
|
this.mainTreeUiEvents = initializeChannelTreeUiEvents(this, { popoutButton: true });
|
||||||
renderChannelTree(this, this.tagContainer[0], { popoutButton: true });
|
|
||||||
|
|
||||||
this.events.on("notify_channel_list_received", () => {
|
this.events.on("notify_channel_list_received", () => {
|
||||||
if(!this.selectedEntry) {
|
if(!this.selectedEntry) {
|
||||||
|
@ -124,10 +128,6 @@ export class ChannelTree {
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_tree() : HTMLDivElement {
|
|
||||||
return this.tagContainer[0] as HTMLDivElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
channelsOrdered() : ChannelEntry[] {
|
channelsOrdered() : ChannelEntry[] {
|
||||||
const result = [];
|
const result = [];
|
||||||
|
|
||||||
|
@ -195,7 +195,9 @@ export class ChannelTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
ReactDOM.unmountComponentAtNode(this.tagContainer[0]);
|
this.mainTreeUiEvents?.fire("notify_destroy");
|
||||||
|
this.mainTreeUiEvents?.destroy();
|
||||||
|
this.mainTreeUiEvents = undefined;
|
||||||
|
|
||||||
if(this.server) {
|
if(this.server) {
|
||||||
this.server.destroy();
|
this.server.destroy();
|
||||||
|
@ -207,7 +209,6 @@ export class ChannelTree {
|
||||||
this.channelLast = undefined;
|
this.channelLast = undefined;
|
||||||
|
|
||||||
this.popoutController.destroy();
|
this.popoutController.destroy();
|
||||||
this.tagContainer.remove();
|
|
||||||
this.events.destroy();
|
this.events.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
115
shared/js/ui/AppController.ts
Normal file
115
shared/js/ui/AppController.ts
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import * as ReactDOM from "react-dom";
|
||||||
|
import {Registry} from "tc-shared/events";
|
||||||
|
import {ControlBarEvents} from "tc-shared/ui/frames/control-bar/Definitions";
|
||||||
|
import {initializeControlBarController} from "tc-shared/ui/frames/control-bar/Controller";
|
||||||
|
import {TeaAppMainView} from "tc-shared/ui/AppRenderer";
|
||||||
|
import {ConnectionListUIEvents} from "tc-shared/ui/frames/connection-handler-list/Definitions";
|
||||||
|
import {initializeConnectionListController} from "tc-shared/ui/frames/connection-handler-list/Controller";
|
||||||
|
import * as loader from "tc-loader";
|
||||||
|
import {Stage} from "tc-loader";
|
||||||
|
import {server_connections} from "tc-shared/ConnectionManager";
|
||||||
|
import {AppUiEvents} from "tc-shared/ui/AppDefinitions";
|
||||||
|
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
|
||||||
|
|
||||||
|
export class AppController {
|
||||||
|
private uiEvents: Registry<AppUiEvents>;
|
||||||
|
|
||||||
|
private listener: (() => void)[];
|
||||||
|
|
||||||
|
private currentConnection: ConnectionHandler;
|
||||||
|
private listenerConnection: (() => void)[];
|
||||||
|
|
||||||
|
private container: HTMLDivElement;
|
||||||
|
private controlBarEvents: Registry<ControlBarEvents>;
|
||||||
|
private connectionListEvents: Registry<ConnectionListUIEvents>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.uiEvents = new Registry<AppUiEvents>();
|
||||||
|
this.uiEvents.on("query_channel_tree", () => this.notifyChannelTree());
|
||||||
|
|
||||||
|
this.listener = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.listener?.forEach(callback => callback());
|
||||||
|
this.listener = [];
|
||||||
|
|
||||||
|
ReactDOM.unmountComponentAtNode(this.container);
|
||||||
|
this.container.remove();
|
||||||
|
this.container = undefined;
|
||||||
|
|
||||||
|
this.controlBarEvents?.fire("notify_destroy");
|
||||||
|
this.controlBarEvents?.destroy();
|
||||||
|
this.controlBarEvents = undefined;
|
||||||
|
|
||||||
|
this.connectionListEvents?.fire("notify_destroy");
|
||||||
|
this.connectionListEvents?.destroy();
|
||||||
|
this.connectionListEvents = undefined;
|
||||||
|
|
||||||
|
this.uiEvents?.destroy();
|
||||||
|
this.uiEvents = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
this.listener = [];
|
||||||
|
|
||||||
|
this.container = document.createElement("div");
|
||||||
|
this.container.classList.add("app-container");
|
||||||
|
document.body.append(this.container);
|
||||||
|
|
||||||
|
this.controlBarEvents = new Registry<ControlBarEvents>()
|
||||||
|
initializeControlBarController(this.controlBarEvents, "main");
|
||||||
|
|
||||||
|
this.connectionListEvents = new Registry<ConnectionListUIEvents>();
|
||||||
|
initializeConnectionListController(this.connectionListEvents);
|
||||||
|
|
||||||
|
this.listener.push(server_connections.events().on("notify_active_handler_changed", event => this.setConnectionHandler(event.newHandler)));
|
||||||
|
this.setConnectionHandler(server_connections.active_connection());
|
||||||
|
}
|
||||||
|
|
||||||
|
setConnectionHandler(connection: ConnectionHandler) {
|
||||||
|
if(this.currentConnection === connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.listenerConnection?.forEach(callback => callback());
|
||||||
|
this.listenerConnection = [];
|
||||||
|
this.currentConnection = connection;
|
||||||
|
|
||||||
|
this.notifyChannelTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderApp() {
|
||||||
|
ReactDOM.render(React.createElement(TeaAppMainView, {
|
||||||
|
controlBar: this.controlBarEvents,
|
||||||
|
connectionList: this.connectionListEvents,
|
||||||
|
sidebar: server_connections.getSidebarController().uiEvents,
|
||||||
|
sidebarHeader: server_connections.getSidebarController().getHeaderController().uiEvents,
|
||||||
|
log: server_connections.serverLogController.events,
|
||||||
|
events: this.uiEvents,
|
||||||
|
hostBanner: server_connections.hostBannerController.uiEvents
|
||||||
|
}), this.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
private notifyChannelTree() {
|
||||||
|
this.uiEvents.fire_react("notify_channel_tree", {
|
||||||
|
handlerId: this.currentConnection?.handlerId,
|
||||||
|
events: this.currentConnection?.channelTree.mainTreeUiEvents
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let appViewController: AppController;
|
||||||
|
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
name: "app view",
|
||||||
|
function: async () => {
|
||||||
|
appViewController = new AppController();
|
||||||
|
appViewController.initialize();
|
||||||
|
appViewController.renderApp();
|
||||||
|
|
||||||
|
(window as any).AppController = AppController;
|
||||||
|
(window as any).appViewController = appViewController;
|
||||||
|
},
|
||||||
|
priority: 0
|
||||||
|
});
|
11
shared/js/ui/AppDefinitions.ts
Normal file
11
shared/js/ui/AppDefinitions.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import {Registry} from "tc-shared/events";
|
||||||
|
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
|
||||||
|
|
||||||
|
export interface AppUiEvents {
|
||||||
|
query_channel_tree: {},
|
||||||
|
|
||||||
|
notify_channel_tree: {
|
||||||
|
events: Registry<ChannelTreeUIEvents> | undefined,
|
||||||
|
handlerId: string
|
||||||
|
}
|
||||||
|
}
|
68
shared/js/ui/AppRenderer.scss
Normal file
68
shared/js/ui/AppRenderer.scss
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
@import "../../css/static/properties";
|
||||||
|
@import "../../css/static/mixin";
|
||||||
|
|
||||||
|
.app {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
/* TODO: Move this into the control bar? */
|
||||||
|
.controlBar {
|
||||||
|
z-index: 200;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
height: 2em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelTreeAndSidebar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
margin-top: 5px;
|
||||||
|
min-height: 27em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelTree {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
background: var(--channel-tree-background);
|
||||||
|
min-width: 200px;
|
||||||
|
min-height: 100px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBar {
|
||||||
|
min-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.containerLog {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
}
|
114
shared/js/ui/AppRenderer.tsx
Normal file
114
shared/js/ui/AppRenderer.tsx
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import {ControlBar2} from "tc-shared/ui/frames/control-bar/Renderer";
|
||||||
|
import {Registry} from "tc-shared/events";
|
||||||
|
import {ControlBarEvents} from "tc-shared/ui/frames/control-bar/Definitions";
|
||||||
|
import {ConnectionListUIEvents} from "tc-shared/ui/frames/connection-handler-list/Definitions";
|
||||||
|
import {ConnectionHandlerList} from "tc-shared/ui/frames/connection-handler-list/Renderer";
|
||||||
|
import {ErrorBoundary} from "tc-shared/ui/react-elements/ErrorBoundary";
|
||||||
|
import {ContextDivider} from "tc-shared/ui/react-elements/ContextDivider";
|
||||||
|
import {SideBarRenderer} from "tc-shared/ui/frames/SideBarRenderer";
|
||||||
|
import {SideBarEvents} from "tc-shared/ui/frames/SideBarDefinitions";
|
||||||
|
import {SideHeaderEvents} from "tc-shared/ui/frames/side/HeaderDefinitions";
|
||||||
|
import {ServerLogFrame} from "tc-shared/ui/frames/log/Renderer";
|
||||||
|
import {ServerEventLogUiEvents} from "tc-shared/ui/frames/log/Definitions";
|
||||||
|
import {FooterRenderer} from "tc-shared/ui/frames/footer/Renderer";
|
||||||
|
import {HostBanner} from "tc-shared/ui/frames/HostBannerRenderer";
|
||||||
|
import {HostBannerUiEvents} from "tc-shared/ui/frames/HostBannerDefinitions";
|
||||||
|
import {AppUiEvents} from "tc-shared/ui/AppDefinitions";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {ChannelTreeRenderer} from "tc-shared/ui/tree/Renderer";
|
||||||
|
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
|
||||||
|
|
||||||
|
const cssStyle = require("./AppRenderer.scss");
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div class="app-container">
|
||||||
|
<div class="app">
|
||||||
|
<!-- navigation bar -->
|
||||||
|
<div class="container-control-bar">
|
||||||
|
<div id="control_bar" class="control_bar">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-connection-handlers" id="connection-handler-list"></div>
|
||||||
|
<div class="container-app-main">
|
||||||
|
<div class="container-channel-video" id="channel-video"></div>
|
||||||
|
<div class="container-channel-chat">
|
||||||
|
<!-- Channel tree -->
|
||||||
|
<div class="container-channel-tree">
|
||||||
|
<div class="hostbanner" id="hostbanner"></div>
|
||||||
|
<div class="channel-tree" id="channelTree"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-seperator vertical" seperator-id="seperator-channel-chat"></div>
|
||||||
|
<!-- Chat window -->
|
||||||
|
<div class="container-chat" id="chat"></div>
|
||||||
|
</div>
|
||||||
|
<div class="container-seperator horizontal" seperator-id="seperator-main-log"></div>
|
||||||
|
<div class="container-bottom">
|
||||||
|
<div class="container-server-log" id="server-log"></div>
|
||||||
|
<div class="container-footer" id="container-footer">
|
||||||
|
</div>
|
||||||
|
</div> <!-- Selection info -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ChannelTree = React.memo((props: { events: Registry<AppUiEvents> }) => {
|
||||||
|
const [ data, setData ] = useState<{ events: Registry<ChannelTreeUIEvents>, handlerId: string }>(() => {
|
||||||
|
props.events.fire("query_channel_tree");
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
props.events.reactUse("notify_channel_tree", event => {
|
||||||
|
setData({ events: event.events, handlerId: event.handlerId });
|
||||||
|
}, undefined, []);
|
||||||
|
|
||||||
|
if(!data?.events) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ChannelTreeRenderer handlerId={data.handlerId} events={data.events} />;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const TeaAppMainView = (props: {
|
||||||
|
events: Registry<AppUiEvents>
|
||||||
|
controlBar: Registry<ControlBarEvents>,
|
||||||
|
connectionList: Registry<ConnectionListUIEvents>,
|
||||||
|
sidebar: Registry<SideBarEvents>,
|
||||||
|
sidebarHeader: Registry<SideHeaderEvents>,
|
||||||
|
log: Registry<ServerEventLogUiEvents>,
|
||||||
|
hostBanner: Registry<HostBannerUiEvents>
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className={cssStyle.app}>
|
||||||
|
<ErrorBoundary>
|
||||||
|
<ControlBar2 events={props.controlBar} className={cssStyle.controlBar} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
<ErrorBoundary>
|
||||||
|
<ConnectionHandlerList events={props.connectionList} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
{/* TODO: The video! */}
|
||||||
|
|
||||||
|
<div className={cssStyle.channelTreeAndSidebar}>
|
||||||
|
<div className={cssStyle.channelTree}>
|
||||||
|
<ErrorBoundary>
|
||||||
|
<HostBanner events={props.hostBanner} />
|
||||||
|
<ChannelTree events={props.events} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
</div>
|
||||||
|
<ContextDivider id={"channel-chat"} direction={"horizontal"} defaultValue={25} />
|
||||||
|
<SideBarRenderer events={props.sidebar} eventsHeader={props.sidebarHeader} className={cssStyle.sideBar} />
|
||||||
|
</div>
|
||||||
|
<ContextDivider id={"main-log"} direction={"vertical"} defaultValue={75} />
|
||||||
|
<ErrorBoundary>
|
||||||
|
<div className={cssStyle.containerLog}>
|
||||||
|
<ServerLogFrame events={props.log} />
|
||||||
|
</div>
|
||||||
|
</ErrorBoundary>
|
||||||
|
<FooterRenderer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ConnectionHandlerList */
|
|
@ -13,6 +13,8 @@ html:root {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
.withBackground {
|
.withBackground {
|
||||||
background-color: var(--hostbanner-background);
|
background-color: var(--hostbanner-background);
|
||||||
border-top-left-radius: 5px;
|
border-top-left-radius: 5px;
|
||||||
|
|
|
@ -2,9 +2,6 @@ import {ConnectionHandler} from "../../ConnectionHandler";
|
||||||
import {PrivateConversationController} from "./side/PrivateConversationController";
|
import {PrivateConversationController} from "./side/PrivateConversationController";
|
||||||
import {ClientInfoController} from "tc-shared/ui/frames/side/ClientInfoController";
|
import {ClientInfoController} from "tc-shared/ui/frames/side/ClientInfoController";
|
||||||
import {SideHeaderController} from "tc-shared/ui/frames/side/HeaderController";
|
import {SideHeaderController} from "tc-shared/ui/frames/side/HeaderController";
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import {SideBarRenderer} from "tc-shared/ui/frames/SideBarRenderer";
|
|
||||||
import * as React from "react";
|
|
||||||
import {SideBarEvents, SideBarType} from "tc-shared/ui/frames/SideBarDefinitions";
|
import {SideBarEvents, SideBarType} from "tc-shared/ui/frames/SideBarDefinitions";
|
||||||
import {Registry} from "tc-shared/events";
|
import {Registry} from "tc-shared/events";
|
||||||
import {LogCategory, logWarn} from "tc-shared/log";
|
import {LogCategory, logWarn} from "tc-shared/log";
|
||||||
|
@ -12,7 +9,7 @@ import {ChannelBarController} from "tc-shared/ui/frames/side/ChannelBarControlle
|
||||||
import {MusicBotController} from "tc-shared/ui/frames/side/MusicBotController";
|
import {MusicBotController} from "tc-shared/ui/frames/side/MusicBotController";
|
||||||
|
|
||||||
export class SideBarController {
|
export class SideBarController {
|
||||||
private readonly uiEvents: Registry<SideBarEvents>;
|
readonly uiEvents: Registry<SideBarEvents>;
|
||||||
|
|
||||||
private currentConnection: ConnectionHandler;
|
private currentConnection: ConnectionHandler;
|
||||||
private listenerConnection: (() => void)[];
|
private listenerConnection: (() => void)[];
|
||||||
|
@ -77,16 +74,22 @@ export class SideBarController {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInto(container: HTMLDivElement) {
|
renderInto(container: HTMLDivElement) {
|
||||||
|
/*
|
||||||
ReactDOM.render(React.createElement(SideBarRenderer, {
|
ReactDOM.render(React.createElement(SideBarRenderer, {
|
||||||
events: this.uiEvents,
|
events: this.uiEvents,
|
||||||
eventsHeader: this.header["uiEvents"],
|
eventsHeader: this.header["uiEvents"],
|
||||||
}), container);
|
}), container);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
getMusicController() : MusicBotController {
|
getMusicController() : MusicBotController {
|
||||||
return this.musicPanel;
|
return this.musicPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHeaderController() : SideHeaderController {
|
||||||
|
return this.header;
|
||||||
|
}
|
||||||
|
|
||||||
private sendContent() {
|
private sendContent() {
|
||||||
if(this.currentConnection) {
|
if(this.currentConnection) {
|
||||||
this.uiEvents.fire("notify_content", { content: this.currentConnection.getSideBar().getSideBarContent() });
|
this.uiEvents.fire("notify_content", { content: this.currentConnection.getSideBar().getSideBarContent() });
|
||||||
|
|
|
@ -34,4 +34,6 @@
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
background: var(--side-background);
|
||||||
}
|
}
|
|
@ -169,7 +169,8 @@ const SideBarHeader = (props: { type: SideBarType, eventsHeader: Registry<SideHe
|
||||||
|
|
||||||
export const SideBarRenderer = (props: {
|
export const SideBarRenderer = (props: {
|
||||||
events: Registry<SideBarEvents>,
|
events: Registry<SideBarEvents>,
|
||||||
eventsHeader: Registry<SideHeaderEvents>
|
eventsHeader: Registry<SideHeaderEvents>,
|
||||||
|
className?: string
|
||||||
}) => {
|
}) => {
|
||||||
const [ content, setContent ] = useState<SideBarType>(() => {
|
const [ content, setContent ] = useState<SideBarType>(() => {
|
||||||
props.events.fire("query_content");
|
props.events.fire("query_content");
|
||||||
|
@ -179,7 +180,7 @@ export const SideBarRenderer = (props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EventContent.Provider value={props.events}>
|
<EventContent.Provider value={props.events}>
|
||||||
<div className={cssStyle.container}>
|
<div className={cssStyle.container + " " + props.className}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<SideBarHeader eventsHeader={props.eventsHeader} type={content} />
|
<SideBarHeader eventsHeader={props.eventsHeader} type={content} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|
|
@ -1,23 +1,11 @@
|
||||||
import {Registry} from "tc-shared/events";
|
import {Registry} from "tc-shared/events";
|
||||||
import {ConnectionListUIEvents, HandlerConnectionState} from "tc-shared/ui/frames/connection-handler-list/Definitions";
|
import {ConnectionListUIEvents, HandlerConnectionState} from "tc-shared/ui/frames/connection-handler-list/Definitions";
|
||||||
import * as React from "react";
|
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import {ConnectionHandlerList} from "tc-shared/ui/frames/connection-handler-list/Renderer";
|
|
||||||
import {server_connections} from "tc-shared/ConnectionManager";
|
import {server_connections} from "tc-shared/ConnectionManager";
|
||||||
import {LogCategory, logWarn} from "tc-shared/log";
|
import {LogCategory, logWarn} from "tc-shared/log";
|
||||||
import {ConnectionState} from "tc-shared/ConnectionHandler";
|
import {ConnectionState} from "tc-shared/ConnectionHandler";
|
||||||
import { tr } from "tc-shared/i18n/localize";
|
import { tr } from "tc-shared/i18n/localize";
|
||||||
|
|
||||||
export function initializeConnectionUIList() {
|
export function initializeConnectionListController(events: Registry<ConnectionListUIEvents>) {
|
||||||
const container = document.getElementById("connection-handler-list");
|
|
||||||
const events = new Registry<ConnectionListUIEvents>();
|
|
||||||
//events.enableDebug("Handler-List");
|
|
||||||
initializeController(events);
|
|
||||||
|
|
||||||
ReactDOM.render(React.createElement(ConnectionHandlerList, { events: events }), container);
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeController(events: Registry<ConnectionListUIEvents>) {
|
|
||||||
let registeredHandlerEvents: {[key: string]:(() => void)[]} = {};
|
let registeredHandlerEvents: {[key: string]:(() => void)[]} = {};
|
||||||
|
|
||||||
events.on("notify_destroy", () => {
|
events.on("notify_destroy", () => {
|
||||||
|
|
|
@ -467,7 +467,7 @@ export const ControlBar2 = (props: { events: Registry<ControlBarEvents>, classNa
|
||||||
return (
|
return (
|
||||||
<Events.Provider value={props.events}>
|
<Events.Provider value={props.events}>
|
||||||
<ModeContext.Provider value={mode}>
|
<ModeContext.Provider value={mode}>
|
||||||
<div className={cssStyle.controlBar + " " + cssStyle["mode-" + mode]}>
|
<div className={cssStyle.controlBar + " " + cssStyle["mode-" + mode] + " " + props.className}>
|
||||||
{items}
|
{items}
|
||||||
</div>
|
</div>
|
||||||
</ModeContext.Provider>
|
</ModeContext.Provider>
|
||||||
|
|
|
@ -11,12 +11,29 @@
|
||||||
@include user-select(none);
|
@include user-select(none);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.version {
|
flex-shrink: 0;
|
||||||
margin-right: .5em;
|
flex-grow: 0;
|
||||||
|
|
||||||
|
height: 1.5em;
|
||||||
|
|
||||||
|
background: var(--footer-background);
|
||||||
|
color: var(--footer-text);
|
||||||
|
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-top: 2px;
|
||||||
|
|
||||||
|
-webkit-box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
|
||||||
|
-moz-box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
|
||||||
|
box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
|
||||||
|
|
||||||
|
> * {
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.source {
|
a[href], a[href]:visited {
|
||||||
display: inline-block;
|
color: var(--footer-text)!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ const VersionsRenderer = () => (
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* FIXME: Outsource this! */
|
||||||
const RtcStatus = () => {
|
const RtcStatus = () => {
|
||||||
const statusController = useMemo(() => new StatusController(new Registry<ConnectionStatusEvents>()), []);
|
const statusController = useMemo(() => new StatusController(new Registry<ConnectionStatusEvents>()), []);
|
||||||
statusController.setConnectionHandler(server_connections.active_connection());
|
statusController.setConnectionHandler(server_connections.active_connection());
|
||||||
|
|
|
@ -10,14 +10,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.logContainer {
|
.logContainer {
|
||||||
flex-shrink: 1;
|
background: var(--server-log-background);
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
|
@ -21,7 +21,7 @@ const ChannelInfoUpdateProperties: (keyof ChannelProperties)[] = [
|
||||||
|
|
||||||
/* TODO: Remove the ping interval handler. It's currently still there since the clients are not emitting the event yet */
|
/* TODO: Remove the ping interval handler. It's currently still there since the clients are not emitting the event yet */
|
||||||
export class SideHeaderController {
|
export class SideHeaderController {
|
||||||
private readonly uiEvents: Registry<SideHeaderEvents>;
|
readonly uiEvents: Registry<SideHeaderEvents>;
|
||||||
|
|
||||||
private connection: ConnectionHandler;
|
private connection: ConnectionHandler;
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,15 @@ export interface ChannelTreeRendererOptions {
|
||||||
popoutButton: boolean;
|
popoutButton: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderChannelTree(channelTree: ChannelTree, target: HTMLElement, options: ChannelTreeRendererOptions) {
|
export function initializeChannelTreeUiEvents(channelTree: ChannelTree, options: ChannelTreeRendererOptions) : Registry<ChannelTreeUIEvents> {
|
||||||
const events = new Registry<ChannelTreeUIEvents>();
|
const events = new Registry<ChannelTreeUIEvents>();
|
||||||
events.enableDebug("channel-tree-view");
|
events.enableDebug("channel-tree-view");
|
||||||
initializeChannelTreeController(events, channelTree, options);
|
initializeChannelTreeController(events, channelTree, options);
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderChannelTree(channelTree: ChannelTree, target: HTMLElement, options: ChannelTreeRendererOptions) {
|
||||||
|
const events = initializeChannelTreeUiEvents(channelTree, options);
|
||||||
|
|
||||||
ReactDOM.render(<ChannelTreeRenderer handlerId={channelTree.client.handlerId} events={events} />, target);
|
ReactDOM.render(<ChannelTreeRenderer handlerId={channelTree.client.handlerId} events={events} />, target);
|
||||||
|
|
||||||
|
@ -89,7 +94,6 @@ class ChannelTreeController {
|
||||||
|
|
||||||
/* the key here is the unique entry id! */
|
/* the key here is the unique entry id! */
|
||||||
private eventListeners: {[key: number]: (() => void)[]} = {};
|
private eventListeners: {[key: number]: (() => void)[]} = {};
|
||||||
private channelTreeInitialized = false;
|
|
||||||
|
|
||||||
private readonly connectionStateListener;
|
private readonly connectionStateListener;
|
||||||
private readonly voiceConnectionStateListener;
|
private readonly voiceConnectionStateListener;
|
||||||
|
@ -135,7 +139,7 @@ class ChannelTreeController {
|
||||||
|
|
||||||
private handleConnectionStateChanged(event: ConnectionEvents["notify_connection_state_changed"]) {
|
private handleConnectionStateChanged(event: ConnectionEvents["notify_connection_state_changed"]) {
|
||||||
if(event.newState !== ConnectionState.CONNECTED) {
|
if(event.newState !== ConnectionState.CONNECTED) {
|
||||||
this.channelTreeInitialized = false;
|
this.channelTree.channelsInitialized = false;
|
||||||
this.sendChannelTreeEntries();
|
this.sendChannelTreeEntries();
|
||||||
}
|
}
|
||||||
this.sendServerStatus(this.channelTree.server);
|
this.sendServerStatus(this.channelTree.server);
|
||||||
|
@ -146,7 +150,7 @@ class ChannelTreeController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.channelTreeInitialized) {
|
if(!this.channelTree.channelsInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +158,7 @@ class ChannelTreeController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleGroupsUpdated(event: GroupManagerEvents["notify_groups_updated"]) {
|
private handleGroupsUpdated(event: GroupManagerEvents["notify_groups_updated"]) {
|
||||||
if(!this.channelTreeInitialized) {
|
if(!this.channelTree.channelsInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +180,7 @@ class ChannelTreeController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleGroupsReceived() {
|
private handleGroupsReceived() {
|
||||||
if(!this.channelTreeInitialized) {
|
if(!this.channelTree.channelsInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,13 +190,13 @@ class ChannelTreeController {
|
||||||
|
|
||||||
/* general channel tree event handlers */
|
/* general channel tree event handlers */
|
||||||
@EventHandler<ChannelTreeEvents>("notify_popout_state_changed")
|
@EventHandler<ChannelTreeEvents>("notify_popout_state_changed")
|
||||||
private handlePoputStateChanged() {
|
private handlePopoutStateChanged() {
|
||||||
this.sendPopoutState();
|
this.sendPopoutState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_channel_list_received")
|
@EventHandler<ChannelTreeEvents>("notify_channel_list_received")
|
||||||
private handleChannelListReceived() {
|
private handleChannelListReceived() {
|
||||||
this.channelTreeInitialized = true;
|
this.channelTree.channelsInitialized = true;
|
||||||
this.channelTree.channels.forEach(channel => this.initializeChannelEvents(channel));
|
this.channelTree.channels.forEach(channel => this.initializeChannelEvents(channel));
|
||||||
this.channelTree.clients.forEach(channel => this.initializeClientEvents(channel));
|
this.channelTree.clients.forEach(channel => this.initializeClientEvents(channel));
|
||||||
this.sendChannelTreeEntries();
|
this.sendChannelTreeEntries();
|
||||||
|
@ -201,14 +205,14 @@ class ChannelTreeController {
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_channel_created")
|
@EventHandler<ChannelTreeEvents>("notify_channel_created")
|
||||||
private handleChannelCreated(event: ChannelTreeEvents["notify_channel_created"]) {
|
private handleChannelCreated(event: ChannelTreeEvents["notify_channel_created"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
this.initializeChannelEvents(event.channel);
|
this.initializeChannelEvents(event.channel);
|
||||||
this.sendChannelTreeEntries();
|
this.sendChannelTreeEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_channel_moved")
|
@EventHandler<ChannelTreeEvents>("notify_channel_moved")
|
||||||
private handleChannelMoved(event: ChannelTreeEvents["notify_channel_moved"]) {
|
private handleChannelMoved(event: ChannelTreeEvents["notify_channel_moved"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
this.sendChannelTreeEntries();
|
this.sendChannelTreeEntries();
|
||||||
|
|
||||||
if(event.previousParent && !event.previousParent.child_channel_head) {
|
if(event.previousParent && !event.previousParent.child_channel_head) {
|
||||||
|
@ -223,14 +227,14 @@ class ChannelTreeController {
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_channel_deleted")
|
@EventHandler<ChannelTreeEvents>("notify_channel_deleted")
|
||||||
private handleChannelDeleted(event: ChannelTreeEvents["notify_channel_deleted"]) {
|
private handleChannelDeleted(event: ChannelTreeEvents["notify_channel_deleted"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
this.finalizeEvents(event.channel);
|
this.finalizeEvents(event.channel);
|
||||||
this.sendChannelTreeEntries();
|
this.sendChannelTreeEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_client_enter_view")
|
@EventHandler<ChannelTreeEvents>("notify_client_enter_view")
|
||||||
private handleClientEnter(event: ChannelTreeEvents["notify_client_enter_view"]) {
|
private handleClientEnter(event: ChannelTreeEvents["notify_client_enter_view"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
|
|
||||||
this.initializeClientEvents(event.client);
|
this.initializeClientEvents(event.client);
|
||||||
this.sendChannelInfo(event.targetChannel);
|
this.sendChannelInfo(event.targetChannel);
|
||||||
|
@ -240,7 +244,7 @@ class ChannelTreeController {
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_client_leave_view")
|
@EventHandler<ChannelTreeEvents>("notify_client_leave_view")
|
||||||
private handleClientLeave(event: ChannelTreeEvents["notify_client_leave_view"]) {
|
private handleClientLeave(event: ChannelTreeEvents["notify_client_leave_view"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
|
|
||||||
this.finalizeEvents(event.client);
|
this.finalizeEvents(event.client);
|
||||||
this.sendChannelInfo(event.sourceChannel);
|
this.sendChannelInfo(event.sourceChannel);
|
||||||
|
@ -250,7 +254,7 @@ class ChannelTreeController {
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_client_moved")
|
@EventHandler<ChannelTreeEvents>("notify_client_moved")
|
||||||
private handleClientMoved(event: ChannelTreeEvents["notify_client_moved"]) {
|
private handleClientMoved(event: ChannelTreeEvents["notify_client_moved"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
|
|
||||||
this.sendChannelInfo(event.oldChannel);
|
this.sendChannelInfo(event.oldChannel);
|
||||||
this.sendChannelStatusIcon(event.oldChannel);
|
this.sendChannelStatusIcon(event.oldChannel);
|
||||||
|
@ -264,7 +268,7 @@ class ChannelTreeController {
|
||||||
|
|
||||||
@EventHandler<ChannelTreeEvents>("notify_selected_entry_changed")
|
@EventHandler<ChannelTreeEvents>("notify_selected_entry_changed")
|
||||||
private handleSelectedEntryChanged(_event: ChannelTreeEvents["notify_selected_entry_changed"]) {
|
private handleSelectedEntryChanged(_event: ChannelTreeEvents["notify_selected_entry_changed"]) {
|
||||||
if(!this.channelTreeInitialized) { return; }
|
if(!this.channelTree.channelsInitialized) { return; }
|
||||||
|
|
||||||
this.sendSelectedEntry();
|
this.sendSelectedEntry();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue