Added a lot of new things
parent
bfb7304606
commit
d9c0fa37f7
|
@ -6,7 +6,8 @@
|
||||||
"directories": {},
|
"directories": {},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile-sass": "sass --update .:.",
|
"compile-sass": "sass --update .:.",
|
||||||
"build-worker": "tsc -p shared/js/workers/tsconfig_worker_codec.json",
|
"build-worker-codec": "tsc -p shared/js/workers/tsconfig_worker_codec.json",
|
||||||
|
"build-worker-pow": "tsc -p shared/js/workers/tsconfig_worker_pow.json",
|
||||||
"dtsgen": "node tools/dtsgen/index.js",
|
"dtsgen": "node tools/dtsgen/index.js",
|
||||||
"trgen": "node tools/trgen/index.js",
|
"trgen": "node tools/trgen/index.js",
|
||||||
"ttsc": "ttsc",
|
"ttsc": "ttsc",
|
||||||
|
|
|
@ -28,9 +28,14 @@ if [[ $? -ne 0 ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Generating web workers"
|
echo "Generating web workers"
|
||||||
npm run build-worker
|
npm run build-worker-codec
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Failed to build web workers"
|
echo "Failed to build web worker codec"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
npm run build-worker-pow
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo "Failed to build web worker pow"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Setup the develop environment on windows
|
||||||
|
## 1.0 Requirements
|
||||||
|
The following tools or applications are required to develop the web client:
|
||||||
|
- [1.1 IDE](#11-ide)
|
||||||
|
- [1.2 XAMPP (apache & php)](#12-xampp-with-a-web-server-and-php)
|
||||||
|
- [1.3 NPM](#13-npm)
|
||||||
|
- [1.4 Git bash](#14-git-bash)
|
||||||
|
|
||||||
|
### 1.1 IDE
|
||||||
|
For developing TeaWeb you require and IDE.
|
||||||
|
Preferable is PHPStorm from Jetbrains because the've already build in compiling on changes.
|
||||||
|
Else you've to run the compiler to compile the TS or SCSS files to js e.g. css files.
|
||||||
|
|
||||||
|
### 1.2 XAMPP with a web server and PHP
|
||||||
|
You require PHP (grater than 5) to setup and manage the project files.
|
||||||
|
PHP is required for the index page as well.
|
||||||
|
The web server is required for browsing your final environment and watch your result.
|
||||||
|
The final environment will be found at `web/environemnt/development/`. More information about
|
||||||
|
the file structure could be found [here (TODO: link me!)]().
|
||||||
|
|
||||||
|
### 1.3 NPM
|
||||||
|
NPM min 6.X is required to develop this project.
|
||||||
|
With NPM you could easily download all required dependencies by just typing `npm install`.
|
||||||
|
IMPORTANT: NPM must be available within the PATH environment variable!
|
||||||
|
|
||||||
|
### 1.4 Git bash
|
||||||
|
For using the `.sh` build scripts you require Git Bash.
|
||||||
|
A minimum of 4.2 is recommend, but in general every version should work.
|
||||||
|
|
||||||
|
## 2.0 Development environment setup
|
||||||
|
### 2.1 Native code (codecs) (Not required)
|
||||||
|
If you dont want to develop the codec part or something related to the native
|
||||||
|
webassembly part of TeaWeb you could skip this step and follow the steps in [2.1-b](#21-b-skip-native-code-setup)
|
||||||
|
|
||||||
|
### 2.1-b Skip native code setup
|
|
@ -37,6 +37,7 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
|
||||||
.server_type {
|
.server_type {
|
||||||
|
@ -193,7 +194,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* all icons related to basic_icons */
|
/* all icons related to basic_icons */
|
||||||
.clicon {width:16px;height:16px;background:url('../../img/ts/basic_icons.png') no-repeat;background-size: 16px 608px;}
|
.clicon {
|
||||||
|
width:16px;
|
||||||
|
height:16px;
|
||||||
|
background:url('../../img/ts/basic_icons.png') no-repeat;
|
||||||
|
background-size: 16px 608px;
|
||||||
|
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.host {background-position: 0 -448px}
|
.host {background-position: 0 -448px}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
.select_info_table { }
|
.select_info_table { }
|
||||||
.select_info_table tr { }
|
.select_info_table tr { }
|
||||||
.select_info_table tr td { }
|
.select_info_table tr td {
|
||||||
|
&:nth-child(1) {
|
||||||
.select_info_table tr td:nth-child(1) {
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
min-width: 20%;
|
min-width: max(35%, 20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
min-width: max(75%, 40px);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.select_server {
|
.select_server {
|
||||||
|
@ -17,21 +22,18 @@
|
||||||
|
|
||||||
.button-update {
|
.button-update {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 23px;
|
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
color: red;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
&:not(:disabled) {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
padding-right: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
.hostbanner {
|
.hostbanner {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -39,18 +41,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
<div id="select_info" class="select_info" style="width: 100%; max-width: 100%">
|
|
||||||
<div class="container-banner"></div>
|
|
||||||
<div class="container-info"></div>
|
|
||||||
</div>
|
|
||||||
*/
|
|
||||||
.select_info {
|
.select_info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
> .close {
|
||||||
|
z-index: 500;
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,8 +228,11 @@ footer .container {
|
||||||
}
|
}
|
||||||
|
|
||||||
$separator_thickness: 4px;
|
$separator_thickness: 4px;
|
||||||
|
$small_device: 500px;
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
.container-app-main {
|
.container-app-main {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
@ -303,6 +306,38 @@ $separator_thickness: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: $small_device) {
|
||||||
|
.container-app-main {
|
||||||
|
.container-info {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
width: 100%!important; /* override the seperator property */
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
z-index: 1000;
|
||||||
|
|
||||||
|
&.shown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select_info {
|
||||||
|
> .close {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-channel-chat + .container-seperator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-channel-chat {
|
||||||
|
width: 100%!important; /* override the seperator property */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.container-seperator {
|
.container-seperator {
|
||||||
background: lightgray;
|
background: lightgray;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
@ -328,6 +363,7 @@ $separator_thickness: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
@ -354,8 +390,6 @@ $separator_thickness: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
min-height: 500px;
|
|
||||||
min-width: 500px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
background: url('../../../img/ts/country_icons.png'), url('../../img/ts/country_icons.png') no-repeat;
|
background: url('../../../img/ts/country_icons.png'), url('../../img/ts/country_icons.png') no-repeat;
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.country.flag-ad {
|
.country.flag-ad {
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
background: url('../../../img/client_icon_sprite.svg'), url('../../img/client_icon_sprite.svg') no-repeat;
|
background: url('../../../img/client_icon_sprite.svg'), url('../../img/client_icon_sprite.svg') no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="description" content="TeaSpeak Web Client, connect to any TeaSpeak server without installing anything." />
|
<meta name="description" content="TeaSpeak Web Client, connect to any TeaSpeak server without installing anything." />
|
||||||
|
<link rel="icon" href="img/favicon/teacup.png">
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if(!$WEB_CLIENT) {
|
if(!$WEB_CLIENT) {
|
||||||
|
@ -190,7 +191,7 @@
|
||||||
<footer style="<?php echo $footer_style; ?>">
|
<footer style="<?php echo $footer_style; ?>">
|
||||||
<div class="container" style="display: flex; flex-direction: row; align-content: space-between;">
|
<div class="container" style="display: flex; flex-direction: row; align-content: space-between;">
|
||||||
<div style="align-self: center; position: fixed; left: 5px;">Open source on <a href="https://github.com/TeaSpeak/TeaSpeak-Web" style="display: inline-block; position: relative">github.com</a></div>
|
<div style="align-self: center; position: fixed; left: 5px;">Open source on <a href="https://github.com/TeaSpeak/TeaSpeak-Web" style="display: inline-block; position: relative">github.com</a></div>
|
||||||
<div style="align-self: center;">TeaSpeak Web client (<?php echo $version; ?>) by WolverinDEV</div>
|
<div style="align-self: center;">TeaSpeak Web (<?php echo $version; ?>) by WolverinDEV</div>
|
||||||
<div style="align-self: center; position: fixed; right: 5px;"><?php echo $footer_forum; ?></div>
|
<div style="align-self: center; position: fixed; right: 5px;"><?php echo $footer_forum; ?></div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -133,8 +133,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-seperator vertical" seperator-id="seperator-main-info"></div>
|
<div class="container-seperator vertical" seperator-id="seperator-main-info"></div>
|
||||||
<div class="main_container container-info">
|
<div id="select_info" class="main_container container-info">
|
||||||
<div id="select_info" class="select_info" style="width: 100%; max-width: 100%">
|
<div class="select_info" style="width: 100%; max-width: 100%">
|
||||||
|
<button type="button" class="close" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
<div class="container-banner"></div>
|
<div class="container-banner"></div>
|
||||||
<!-- <div class="container-seperator horizontal" seperator-id="seperator-hostbanner-info"></div> -->
|
<!-- <div class="container-seperator horizontal" seperator-id="seperator-hostbanner-info"></div> -->
|
||||||
<div class="container-select-info"></div>
|
<div class="container-select-info"></div>
|
||||||
|
@ -1029,7 +1032,8 @@
|
||||||
|
|
||||||
<div class="group_box">
|
<div class="group_box">
|
||||||
<div class="header">{{tr "Microphone" /}}</div>
|
<div class="header">{{tr "Microphone" /}}</div>
|
||||||
<div class="content settings-microphone">
|
<div class="content settings-microphone {{if !voice_available}}disabled{{/if}}">
|
||||||
|
{{if voice_available}}
|
||||||
<div class="form-row settings-device settings-device-microphone">
|
<div class="form-row settings-device settings-device-microphone">
|
||||||
<div class="form-group settings-device-select">
|
<div class="form-group settings-device-select">
|
||||||
<label for="select-settings-microphone-device" class="bmd-label-static">{{tr "Device:" /}}</label>
|
<label for="select-settings-microphone-device" class="bmd-label-static">{{tr "Device:" /}}</label>
|
||||||
|
@ -1088,6 +1092,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div>{{tr "Voice had been disabled" /}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="group_box">
|
<div class="group_box">
|
||||||
|
@ -2058,7 +2065,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{tr "Name:" /}}</td>
|
<td>{{tr "Name:" /}}</td>
|
||||||
<td style="display: flex; flex-direction: row">
|
<td style="display: flex; flex-direction: row">
|
||||||
<div style="margin-right: 3px" class="country flag-{{*:(data.property_client_country || 'xx').toLowerCase()}}"></div>
|
<div style="margin-right: 3px" class="country flag-{{*:(data.property_client_country || 'xx').toLowerCase()}}" title="{{*:i18n.country_name(data.property_client_country || 'XX')}}"></div>
|
||||||
<node key="client_name"/>
|
<node key="client_name"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -2315,7 +2322,7 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="button-update btn_update">{{tr "Update info"/}}</button>
|
<button class="button-update btn btn-success">{{tr "Update info"/}}</button>
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
<script class="jsrender-template" id="tmpl_selected_channel" type="text/html">
|
<script class="jsrender-template" id="tmpl_selected_channel" type="text/html">
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 75 KiB |
|
@ -50,7 +50,7 @@ enum ViewReasonId {
|
||||||
class TSClient {
|
class TSClient {
|
||||||
channelTree: ChannelTree;
|
channelTree: ChannelTree;
|
||||||
serverConnection: connection.ServerConnection;
|
serverConnection: connection.ServerConnection;
|
||||||
voiceConnection: VoiceConnection;
|
voiceConnection: VoiceConnection | undefined;
|
||||||
fileManager: FileManager;
|
fileManager: FileManager;
|
||||||
selectInfo: InfoBar;
|
selectInfo: InfoBar;
|
||||||
permissions: PermissionManager;
|
permissions: PermissionManager;
|
||||||
|
@ -69,10 +69,12 @@ class TSClient {
|
||||||
this.fileManager = new FileManager(this);
|
this.fileManager = new FileManager(this);
|
||||||
this.permissions = new PermissionManager(this);
|
this.permissions = new PermissionManager(this);
|
||||||
this.groups = new GroupManager(this);
|
this.groups = new GroupManager(this);
|
||||||
this.voiceConnection = new VoiceConnection(this);
|
|
||||||
this._ownEntry = new LocalClientEntry(this);
|
this._ownEntry = new LocalClientEntry(this);
|
||||||
this.controlBar = new ControlBar(this, $("#control_bar"));
|
this.controlBar = new ControlBar(this, $("#control_bar"));
|
||||||
this.channelTree.registerClient(this._ownEntry);
|
this.channelTree.registerClient(this._ownEntry);
|
||||||
|
|
||||||
|
if(!settings.static_global(Settings.KEY_DISABLE_VOICE, false))
|
||||||
|
this.voiceConnection = new VoiceConnection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
@ -140,7 +142,8 @@ class TSClient {
|
||||||
if(this.groups.serverGroups.length == 0)
|
if(this.groups.serverGroups.length == 0)
|
||||||
this.groups.requestGroups();
|
this.groups.requestGroups();
|
||||||
this.controlBar.updateProperties();
|
this.controlBar.updateProperties();
|
||||||
if(!this.voiceConnection.current_encoding_supported())
|
|
||||||
|
if(this.voiceConnection && !this.voiceConnection.current_encoding_supported())
|
||||||
createErrorModal(tr("Codec encode type not supported!"), tr("Codec encode type " + VoiceConnectionType[this.voiceConnection.type] + " not supported by this browser!<br>Choose another one!")).open(); //TODO tr
|
createErrorModal(tr("Codec encode type not supported!"), tr("Codec encode type " + VoiceConnectionType[this.voiceConnection.type] + " not supported by this browser!<br>Choose another one!")).open(); //TODO tr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +273,7 @@ class TSClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.channelTree.reset();
|
this.channelTree.reset();
|
||||||
|
if(this.voiceConnection)
|
||||||
this.voiceConnection.dropSession();
|
this.voiceConnection.dropSession();
|
||||||
if(this.serverConnection) this.serverConnection.disconnect();
|
if(this.serverConnection) this.serverConnection.disconnect();
|
||||||
this.controlBar.update_connection_state();
|
this.controlBar.update_connection_state();
|
||||||
|
|
|
@ -81,8 +81,12 @@ namespace connection {
|
||||||
|
|
||||||
handleCommandServerInit(json){
|
handleCommandServerInit(json){
|
||||||
//We could setup the voice channel
|
//We could setup the voice channel
|
||||||
|
if( this.connection.client.voiceConnection) {
|
||||||
console.log(tr("Setting up voice"));
|
console.log(tr("Setting up voice"));
|
||||||
this.connection.client.voiceConnection.createSession();
|
this.connection.client.voiceConnection.createSession();
|
||||||
|
} else {
|
||||||
|
console.log(tr("Skipping voice setup (No voice bridge available)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
json = json[0]; //Only one bulk
|
json = json[0]; //Only one bulk
|
||||||
|
|
|
@ -28,12 +28,24 @@ namespace connection {
|
||||||
abstract disconnect(reason?: string) : Promise<void>;
|
abstract disconnect(reason?: string) : Promise<void>;
|
||||||
|
|
||||||
abstract support_voice() : boolean;
|
abstract support_voice() : boolean;
|
||||||
abstract voice_connection() : AbstractVoiceConnection | undefined;
|
abstract voice_connection() : voice.AbstractVoiceConnection | undefined;
|
||||||
|
|
||||||
abstract command_handler_boss() : AbstractCommandHandlerBoss;
|
abstract command_handler_boss() : AbstractCommandHandlerBoss;
|
||||||
abstract send_command(command: string, data?: any | any[], options?: CommandOptions) : Promise<CommandResult>;
|
abstract send_command(command: string, data?: any | any[], options?: CommandOptions) : Promise<CommandResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace voice {
|
||||||
|
export interface VoiceClient {
|
||||||
|
client_id: number;
|
||||||
|
|
||||||
|
callback_playback: () => any;
|
||||||
|
callback_timeout: () => any;
|
||||||
|
callback_stopped: () => any;
|
||||||
|
|
||||||
|
get_volume() : number;
|
||||||
|
set_volume(volume: number) : Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class AbstractVoiceConnection {
|
export abstract class AbstractVoiceConnection {
|
||||||
readonly connection: AbstractServerConnection;
|
readonly connection: AbstractServerConnection;
|
||||||
|
|
||||||
|
@ -42,6 +54,11 @@ namespace connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract connected() : boolean;
|
abstract connected() : boolean;
|
||||||
|
|
||||||
|
abstract register_client(client_id: number) : VoiceClient;
|
||||||
|
abstract availible_clients() : VoiceClient[];
|
||||||
|
abstract unregister_client(client: VoiceClient) : Promise<void>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ServerCommand {
|
export class ServerCommand {
|
||||||
|
|
|
@ -202,7 +202,12 @@ namespace connection {
|
||||||
arguments: json["data"]
|
arguments: json["data"]
|
||||||
});
|
});
|
||||||
group.end();
|
group.end();
|
||||||
} else if(json["type"] === "WebRTC") this.client.voiceConnection.handleControlPacket(json);
|
} else if(json["type"] === "WebRTC") {
|
||||||
|
if(this.client.voiceConnection)
|
||||||
|
this.client.voiceConnection.handleControlPacket(json);
|
||||||
|
else
|
||||||
|
console.log(tr("Dropping WebRTC command packet, because we havent a bridge."))
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
console.log(tr("Unknown command type %o"), json["type"]);
|
console.log(tr("Unknown command type %o"), json["type"]);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +304,7 @@ namespace connection {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
voice_connection(): connection.AbstractVoiceConnection | undefined {
|
voice_connection(): connection.voice.AbstractVoiceConnection | undefined {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,9 @@ interface ContextMenuEntry {
|
||||||
name: (() => string) | string;
|
name: (() => string) | string;
|
||||||
icon?: (() => string) | string | JQuery;
|
icon?: (() => string) | string | JQuery;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
invalidPermission?: boolean;
|
visible?: boolean;
|
||||||
|
|
||||||
|
invalidPermission?: boolean;
|
||||||
sub_menu?: ContextMenuEntry[];
|
sub_menu?: ContextMenuEntry[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +97,11 @@ function generate_tag(entry: ContextMenuEntry) : JQuery {
|
||||||
if(entry.disabled || entry.invalidPermission) tag.addClass("disabled");
|
if(entry.disabled || entry.invalidPermission) tag.addClass("disabled");
|
||||||
else {
|
else {
|
||||||
let menu = $.spawn("div").addClass("sub-menu").addClass("context-menu");
|
let menu = $.spawn("div").addClass("sub-menu").addClass("context-menu");
|
||||||
for(let e of entry.sub_menu)
|
for(const e of entry.sub_menu) {
|
||||||
|
if(typeof(entry.visible) === 'boolean' && !entry.visible)
|
||||||
|
continue;
|
||||||
menu.append(generate_tag(e));
|
menu.append(generate_tag(e));
|
||||||
|
}
|
||||||
menu.appendTo(tag);
|
menu.appendTo(tag);
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
|
@ -111,7 +115,10 @@ function spawn_context_menu(x, y, ...entries: ContextMenuEntry[]) {
|
||||||
|
|
||||||
contextMenuCloseFn = undefined;
|
contextMenuCloseFn = undefined;
|
||||||
|
|
||||||
for(let entry of entries){
|
for(const entry of entries){
|
||||||
|
if(typeof(entry.visible) === 'boolean' && !entry.visible)
|
||||||
|
continue;
|
||||||
|
|
||||||
if(entry.type == MenuEntryType.CLOSE) {
|
if(entry.type == MenuEntryType.CLOSE) {
|
||||||
contextMenuCloseFn = entry.callback;
|
contextMenuCloseFn = entry.callback;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace loader {
|
||||||
DONE
|
DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
export let allow_cached_files: boolean = false;
|
export let cache_tag: string | undefined;
|
||||||
let current_stage: Stage = Stage.INITIALIZING;
|
let current_stage: Stage = Stage.INITIALIZING;
|
||||||
const tasks: {[key:number]:Task[]} = {};
|
const tasks: {[key:number]:Task[]} = {};
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ namespace loader {
|
||||||
|
|
||||||
document.getElementById("scripts").appendChild(tag);
|
document.getElementById("scripts").appendChild(tag);
|
||||||
|
|
||||||
tag.src = path + (allow_cached_files ? "" : "?_ts=" + Date.now());
|
tag.src = path + (cache_tag || "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ namespace loader {
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementById("style").appendChild(tag);
|
document.getElementById("style").appendChild(tag);
|
||||||
tag.href = path + (allow_cached_files ? "" : "?_ts=" + Date.now());
|
tag.href = path + (cache_tag || "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -708,12 +708,11 @@ async function check_updates() {
|
||||||
|
|
||||||
if(!app_version) {
|
if(!app_version) {
|
||||||
/* TODO add warning */
|
/* TODO add warning */
|
||||||
loader.allow_cached_files = false;
|
loader.cache_tag = "?_ts=" + Date.now();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cached_version = localStorage.getItem("cached_version");
|
const cached_version = localStorage.getItem("cached_version");
|
||||||
if(!cached_version || cached_version != app_version) {
|
if(!cached_version || cached_version != app_version) {
|
||||||
loader.allow_cached_files = false;
|
|
||||||
loader.register_task(loader.Stage.LOADED, {
|
loader.register_task(loader.Stage.LOADED, {
|
||||||
priority: 0,
|
priority: 0,
|
||||||
name: "cached version updater",
|
name: "cached version updater",
|
||||||
|
@ -721,11 +720,8 @@ async function check_updates() {
|
||||||
localStorage.setItem("cached_version", app_version);
|
localStorage.setItem("cached_version", app_version);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
/* loading screen */
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
loader.cache_tag = "?_version=" + app_version;
|
||||||
loader.allow_cached_files = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
|
|
|
@ -270,6 +270,7 @@ function main() {
|
||||||
clearTimeout(_resize_timeout);
|
clearTimeout(_resize_timeout);
|
||||||
_resize_timeout = setTimeout(() => {
|
_resize_timeout = setTimeout(() => {
|
||||||
globalClient.channelTree.handle_resized();
|
globalClient.channelTree.handle_resized();
|
||||||
|
globalClient.selectInfo.handle_resize();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ class StaticSettings {
|
||||||
class Settings extends StaticSettings {
|
class Settings extends StaticSettings {
|
||||||
static readonly KEY_DISABLE_CONTEXT_MENU = "disableContextMenu";
|
static readonly KEY_DISABLE_CONTEXT_MENU = "disableContextMenu";
|
||||||
static readonly KEY_DISABLE_UNLOAD_DIALOG = "disableUnloadDialog";
|
static readonly KEY_DISABLE_UNLOAD_DIALOG = "disableUnloadDialog";
|
||||||
|
static readonly KEY_DISABLE_VOICE = "disableVoice";
|
||||||
|
|
||||||
private static readonly UPDATE_DIRECT: boolean = true;
|
private static readonly UPDATE_DIRECT: boolean = true;
|
||||||
private cacheGlobal = {};
|
private cacheGlobal = {};
|
||||||
|
|
|
@ -442,7 +442,21 @@ class ChannelEntry {
|
||||||
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_TEMPORARY).granted(1);
|
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_TEMPORARY).granted(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let trigger_close = true;
|
||||||
spawn_context_menu(x, y, {
|
spawn_context_menu(x, y, {
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Show channel info"),
|
||||||
|
callback: () => {
|
||||||
|
trigger_close = false;
|
||||||
|
this.channelTree.client.selectInfo.open_popover()
|
||||||
|
},
|
||||||
|
icon: "client-about",
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover()
|
||||||
|
}, {
|
||||||
|
type: MenuEntryType.HR,
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover(),
|
||||||
|
name: ''
|
||||||
|
}, {
|
||||||
type: MenuEntryType.ENTRY,
|
type: MenuEntryType.ENTRY,
|
||||||
icon: "client-channel_switch",
|
icon: "client-channel_switch",
|
||||||
name: tr("<b>Switch to channel</b>"),
|
name: tr("<b>Switch to channel</b>"),
|
||||||
|
@ -525,7 +539,7 @@ class ChannelEntry {
|
||||||
invalidPermission: !channelCreate,
|
invalidPermission: !channelCreate,
|
||||||
callback: () => this.channelTree.spawnCreateChannel()
|
callback: () => this.channelTree.spawnCreateChannel()
|
||||||
},
|
},
|
||||||
MenuEntry.CLOSE(on_close)
|
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +653,10 @@ class ChannelEntry {
|
||||||
}
|
}
|
||||||
} else if(key == "channel_codec") {
|
} else if(key == "channel_codec") {
|
||||||
(this.properties.channel_codec == 5 || this.properties.channel_codec == 3 ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_music"));
|
(this.properties.channel_codec == 5 || this.properties.channel_codec == 3 ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_music"));
|
||||||
(this.channelTree.client.voiceConnection.codecSupported(this.properties.channel_codec) ? $.fn.hide : $.fn.show).apply(this.channelTag().find(".icons .icon_no_sound"));
|
this.channelTag().find(".icons .icon_no_sound").toggle(!(
|
||||||
|
this.channelTree.client.voiceConnection &&
|
||||||
|
this.channelTree.client.voiceConnection.codecSupported(this.properties.channel_codec)
|
||||||
|
));
|
||||||
} else if(key == "channel_flag_default") {
|
} else if(key == "channel_flag_default") {
|
||||||
(this.properties.channel_flag_default ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_default"));
|
(this.properties.channel_flag_default ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_default"));
|
||||||
} else if(key == "channel_flag_password")
|
} else if(key == "channel_flag_password")
|
||||||
|
|
|
@ -266,28 +266,40 @@ class ClientEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
showContextMenu(x: number, y: number, on_close: () => void = undefined) {
|
showContextMenu(x: number, y: number, on_close: () => void = undefined) {
|
||||||
const _this = this;
|
let trigger_close = true;
|
||||||
|
|
||||||
spawn_context_menu(x, y,
|
spawn_context_menu(x, y,
|
||||||
{
|
{
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Show client info"),
|
||||||
|
callback: () => {
|
||||||
|
trigger_close = false;
|
||||||
|
this.channelTree.client.selectInfo.open_popover()
|
||||||
|
},
|
||||||
|
icon: "client-about",
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover()
|
||||||
|
}, {
|
||||||
|
type: MenuEntryType.HR,
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover(),
|
||||||
|
name: ''
|
||||||
|
}, {
|
||||||
type: MenuEntryType.ENTRY,
|
type: MenuEntryType.ENTRY,
|
||||||
icon: "client-change_nickname",
|
icon: "client-change_nickname",
|
||||||
name: tr("<b>Open text chat</b>"),
|
name: tr("<b>Open text chat</b>"),
|
||||||
callback: function () {
|
callback: () => {
|
||||||
chat.activeChat = _this.chat(true);
|
chat.activeChat = this.chat(true);
|
||||||
chat.focus();
|
chat.focus();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
type: MenuEntryType.ENTRY,
|
type: MenuEntryType.ENTRY,
|
||||||
icon: "client-poke",
|
icon: "client-poke",
|
||||||
name: tr("Poke client"),
|
name: tr("Poke client"),
|
||||||
callback: function () {
|
callback: () => {
|
||||||
createInputModal(tr("Poke client"), tr("Poke message:<br>"), text => true, result => {
|
createInputModal(tr("Poke client"), tr("Poke message:<br>"), text => true, result => {
|
||||||
if(typeof(result) === "string") {
|
if(typeof(result) === "string") {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Poking client " + _this.clientNickName() + " with message " + result);
|
console.log("Poking client " + this.clientNickName() + " with message " + result);
|
||||||
_this.channelTree.client.serverConnection.send_command("clientpoke", {
|
this.channelTree.client.serverConnection.send_command("clientpoke", {
|
||||||
clid: _this.clientId(),
|
clid: this.clientId(),
|
||||||
msg: result
|
msg: result
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -298,13 +310,13 @@ class ClientEntry {
|
||||||
type: MenuEntryType.ENTRY,
|
type: MenuEntryType.ENTRY,
|
||||||
icon: "client-edit",
|
icon: "client-edit",
|
||||||
name: tr("Change description"),
|
name: tr("Change description"),
|
||||||
callback: function () {
|
callback: () => {
|
||||||
createInputModal(tr("Change client description"), tr("New description:<br>"), text => true, result => {
|
createInputModal(tr("Change client description"), tr("New description:<br>"), text => true, result => {
|
||||||
if(typeof(result) === "string") {
|
if(typeof(result) === "string") {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Changing " + _this.clientNickName() + "'s description to " + result);
|
console.log("Changing " + this.clientNickName() + "'s description to " + result);
|
||||||
_this.channelTree.client.serverConnection.send_command("clientedit", {
|
this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||||
clid: _this.clientId(),
|
clid: this.clientId(),
|
||||||
client_description: result
|
client_description: result
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -332,9 +344,9 @@ class ClientEntry {
|
||||||
createInputModal(tr("Kick client from channel"), tr("Kick reason:<br>"), text => true, result => {
|
createInputModal(tr("Kick client from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Kicking client " + _this.clientNickName() + " from channel with reason " + result);
|
console.log("Kicking client " + this.clientNickName() + " from channel with reason " + result);
|
||||||
_this.channelTree.client.serverConnection.send_command("clientkick", {
|
this.channelTree.client.serverConnection.send_command("clientkick", {
|
||||||
clid: _this.clientId(),
|
clid: this.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
});
|
});
|
||||||
|
@ -350,9 +362,9 @@ class ClientEntry {
|
||||||
createInputModal(tr("Kick client from server"), tr("Kick reason:<br>"), text => true, result => {
|
createInputModal(tr("Kick client from server"), tr("Kick reason:<br>"), text => true, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Kicking client " + _this.clientNickName() + " from server with reason " + result);
|
console.log("Kicking client " + this.clientNickName() + " from server with reason " + result);
|
||||||
_this.channelTree.client.serverConnection.send_command("clientkick", {
|
this.channelTree.client.serverConnection.send_command("clientkick", {
|
||||||
clid: _this.clientId(),
|
clid: this.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
});
|
});
|
||||||
|
@ -411,7 +423,7 @@ class ClientEntry {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MenuEntry.CLOSE(on_close)
|
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,8 +920,22 @@ class MusicClientEntry extends ClientEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
showContextMenu(x: number, y: number, on_close: () => void = undefined): void {
|
showContextMenu(x: number, y: number, on_close: () => void = undefined): void {
|
||||||
|
let trigger_close = true;
|
||||||
spawn_context_menu(x, y,
|
spawn_context_menu(x, y,
|
||||||
{
|
{
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Show bot info"),
|
||||||
|
callback: () => {
|
||||||
|
trigger_close = false;
|
||||||
|
this.channelTree.client.selectInfo.open_popover()
|
||||||
|
},
|
||||||
|
icon: "client-about",
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover()
|
||||||
|
}, {
|
||||||
|
type: MenuEntryType.HR,
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover(),
|
||||||
|
name: ''
|
||||||
|
}, {
|
||||||
name: tr("<b>Change bot name</b>"),
|
name: tr("<b>Change bot name</b>"),
|
||||||
icon: "client-change_nickname",
|
icon: "client-change_nickname",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
@ -1073,7 +1099,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
},
|
},
|
||||||
type: MenuEntryType.ENTRY
|
type: MenuEntryType.ENTRY
|
||||||
},
|
},
|
||||||
MenuEntry.CLOSE(on_close)
|
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ class ControlBar {
|
||||||
|
|
||||||
private updateMicrophoneRecordState() {
|
private updateMicrophoneRecordState() {
|
||||||
let enabled = !this._muteInput && !this._muteOutput && !this._away;
|
let enabled = !this._muteInput && !this._muteOutput && !this._away;
|
||||||
|
if(this.handle.voiceConnection)
|
||||||
this.handle.voiceConnection.voiceRecorder.update(enabled);
|
this.handle.voiceConnection.voiceRecorder.update(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,12 +213,13 @@ class ControlBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVoice(targetChannel?: ChannelEntry) {
|
updateVoice(targetChannel?: ChannelEntry) {
|
||||||
if(!targetChannel) targetChannel = this.handle.getClient().currentChannel();
|
if(!targetChannel)
|
||||||
|
targetChannel = this.handle.getClient().currentChannel();
|
||||||
let client = this.handle.getClient();
|
let client = this.handle.getClient();
|
||||||
|
|
||||||
this.codec_supported = targetChannel ? this.handle.voiceConnection.codecSupported(targetChannel.properties.channel_codec) : true;
|
this.codec_supported = targetChannel ? this.handle.voiceConnection && this.handle.voiceConnection.codecSupported(targetChannel.properties.channel_codec) : true;
|
||||||
this.support_record = this.handle.voiceConnection.voice_send_support();
|
this.support_record = this.handle.voiceConnection && this.handle.voiceConnection.voice_send_support();
|
||||||
this.support_playback = this.handle.voiceConnection.voice_playback_support();
|
this.support_playback = this.handle.voiceConnection && this.handle.voiceConnection.voice_playback_support();
|
||||||
|
|
||||||
this.htmlTag.find(".btn_mute_input").prop("disabled", !this.codec_supported|| !this.support_playback || !this.support_record);
|
this.htmlTag.find(".btn_mute_input").prop("disabled", !this.codec_supported|| !this.support_playback || !this.support_record);
|
||||||
this.htmlTag.find(".btn_mute_output").prop("disabled", !this.codec_supported || !this.support_playback);
|
this.htmlTag.find(".btn_mute_output").prop("disabled", !this.codec_supported || !this.support_playback);
|
||||||
|
|
|
@ -53,7 +53,8 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
readonly handle: TSClient;
|
readonly handle: TSClient;
|
||||||
|
|
||||||
private current_selected?: AvailableTypes;
|
private current_selected?: AvailableTypes;
|
||||||
private _htmlTag: JQuery<HTMLElement>;
|
private _tag: JQuery<HTMLElement>;
|
||||||
|
private _tag_content: JQuery<HTMLElement>;
|
||||||
private _tag_info: JQuery<HTMLElement>;
|
private _tag_info: JQuery<HTMLElement>;
|
||||||
private _tag_banner: JQuery<HTMLElement>;
|
private _tag_banner: JQuery<HTMLElement>;
|
||||||
|
|
||||||
|
@ -63,9 +64,10 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
|
|
||||||
constructor(client: TSClient, htmlTag: JQuery<HTMLElement>) {
|
constructor(client: TSClient, htmlTag: JQuery<HTMLElement>) {
|
||||||
this.handle = client;
|
this.handle = client;
|
||||||
this._htmlTag = htmlTag;
|
this._tag = htmlTag;
|
||||||
this._tag_info = htmlTag.find(".container-select-info");
|
this._tag_content = htmlTag.find("> .select_info");
|
||||||
this._tag_banner = htmlTag.find(".container-banner");
|
this._tag_info = this._tag_content.find(".container-select-info");
|
||||||
|
this._tag_banner = this._tag_content.find(".container-banner");
|
||||||
|
|
||||||
this.managers.push(new MusicInfoManager());
|
this.managers.push(new MusicInfoManager());
|
||||||
this.managers.push(new ClientInfoManager());
|
this.managers.push(new ClientInfoManager());
|
||||||
|
@ -73,10 +75,24 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
this.managers.push(new ServerInfoManager());
|
this.managers.push(new ServerInfoManager());
|
||||||
|
|
||||||
this.banner_manager = new Hostbanner(client, this._tag_banner);
|
this.banner_manager = new Hostbanner(client, this._tag_banner);
|
||||||
|
|
||||||
|
this._tag.find("button.close").on('click', () => {
|
||||||
|
this._tag.toggleClass('shown', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_resize() {
|
||||||
|
/* test if the popover isn't a popover anymore */
|
||||||
|
if(this._tag.hasClass('shown')) {
|
||||||
|
this._tag.removeClass('shown');
|
||||||
|
if(this.is_popover())
|
||||||
|
this._tag.addClass('shown');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentSelected(entry: AvailableTypes) {
|
setCurrentSelected(entry: AvailableTypes) {
|
||||||
if(this.current_selected == entry) return;
|
if(this.current_selected == entry) return;
|
||||||
|
|
||||||
if(this._current_manager) {
|
if(this._current_manager) {
|
||||||
(this._current_manager as InfoManager<AvailableTypes>).finalizeFrame(this.current_selected, this._tag_info);
|
(this._current_manager as InfoManager<AvailableTypes>).finalizeFrame(this.current_selected, this._tag_info);
|
||||||
this._current_manager = null;
|
this._current_manager = null;
|
||||||
|
@ -112,7 +128,15 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
|
|
||||||
current_manager() { return this._current_manager; }
|
current_manager() { return this._current_manager; }
|
||||||
|
|
||||||
html_tag() { return this._htmlTag; }
|
html_tag() { return this._tag_content; }
|
||||||
|
|
||||||
|
is_popover() : boolean {
|
||||||
|
return !this._tag.is(':visible') || this._tag.hasClass('shown');
|
||||||
|
}
|
||||||
|
|
||||||
|
open_popover() {
|
||||||
|
this._tag.toggleClass('shown', true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Hostbanner {
|
class Hostbanner {
|
||||||
|
@ -299,8 +323,12 @@ class ServerInfoManager extends InfoManager<ServerEntry> {
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let requestUpdate = rendered.find(".btn_update");
|
const disabled = !server.shouldUpdateProperties();
|
||||||
requestUpdate.prop("disabled", !server.shouldUpdateProperties());
|
let requestUpdate = rendered.find(".button-update");
|
||||||
|
requestUpdate
|
||||||
|
.prop("disabled", disabled)
|
||||||
|
.toggleClass('btn-success', !disabled)
|
||||||
|
.toggleClass('btn-danger', disabled);
|
||||||
|
|
||||||
requestUpdate.click(() => {
|
requestUpdate.click(() => {
|
||||||
server.updateProperties();
|
server.updateProperties();
|
||||||
|
@ -308,7 +336,10 @@ class ServerInfoManager extends InfoManager<ServerEntry> {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerTimer(setTimeout(function () {
|
this.registerTimer(setTimeout(function () {
|
||||||
requestUpdate.prop("disabled", false);
|
requestUpdate
|
||||||
|
.prop("disabled", false)
|
||||||
|
.toggleClass('btn-success', true)
|
||||||
|
.toggleClass('btn-danger', false);
|
||||||
}, server.nextInfoRequest - Date.now()));
|
}, server.nextInfoRequest - Date.now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
/// <reference path="../../profiles/Identity.ts" />
|
/// <reference path="../../profiles/Identity.ts" />
|
||||||
|
|
||||||
namespace Modals {
|
namespace Modals {
|
||||||
function spawnTeamSpeakIdentityImprove(identity: profiles.identities.TeaSpeakIdentity) : Modal {
|
function spawnTeamSpeakIdentityImprove(identity: profiles.identities.TeaSpeakIdentity): Modal {
|
||||||
let modal: Modal;
|
let modal: Modal;
|
||||||
let elapsed_timer: NodeJS.Timer;
|
let elapsed_timer: NodeJS.Timer;
|
||||||
|
|
||||||
|
@ -25,10 +25,10 @@ namespace Modals {
|
||||||
const input_elapsed = template.find(".time-elapsed input");
|
const input_elapsed = template.find(".time-elapsed input");
|
||||||
|
|
||||||
button_close.on('click', event => {
|
button_close.on('click', event => {
|
||||||
if(active)
|
if (active)
|
||||||
button_start_stop.trigger('click');
|
button_start_stop.trigger('click');
|
||||||
|
|
||||||
if(modal.shown)
|
if (modal.shown)
|
||||||
modal.close();
|
modal.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace Modals {
|
||||||
|
|
||||||
input_threads.prop("disabled", !active);
|
input_threads.prop("disabled", !active);
|
||||||
input_target_level.prop("disabled", !active);
|
input_target_level.prop("disabled", !active);
|
||||||
if(active) {
|
if (active) {
|
||||||
input_hash_rate.val(0);
|
input_hash_rate.val(0);
|
||||||
clearInterval(elapsed_timer);
|
clearInterval(elapsed_timer);
|
||||||
active = false;
|
active = false;
|
||||||
|
@ -51,7 +51,7 @@ namespace Modals {
|
||||||
|
|
||||||
const threads = parseInt(input_threads.val() as string);
|
const threads = parseInt(input_threads.val() as string);
|
||||||
const target_level = parseInt(input_target_level.val() as string);
|
const target_level = parseInt(input_target_level.val() as string);
|
||||||
if(target_level == 0) {
|
if (target_level == 0) {
|
||||||
identity.improve_level(-1, threads, () => active, current_level => {
|
identity.improve_level(-1, threads, () => active, current_level => {
|
||||||
input_current_level.val(current_level);
|
input_current_level.val(current_level);
|
||||||
}, hash_rate => {
|
}, hash_rate => {
|
||||||
|
@ -59,7 +59,7 @@ namespace Modals {
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
createErrorModal(tr("Failed to improve identity"), tr("Failed to improve identity.<br>Error:") + error).open();
|
createErrorModal(tr("Failed to improve identity"), tr("Failed to improve identity.<br>Error:") + error).open();
|
||||||
if(active)
|
if (active)
|
||||||
button_start_stop.trigger('click');
|
button_start_stop.trigger('click');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,7 +68,7 @@ namespace Modals {
|
||||||
}, hash_rate => {
|
}, hash_rate => {
|
||||||
input_hash_rate.val(hash_rate);
|
input_hash_rate.val(hash_rate);
|
||||||
}).then(success => {
|
}).then(success => {
|
||||||
if(success) {
|
if (success) {
|
||||||
identity.level().then(level => {
|
identity.level().then(level => {
|
||||||
input_current_level.val(level);
|
input_current_level.val(level);
|
||||||
createInfoModal(tr("Identity successfully improved"), MessageHelper.formatMessage(tr("Identity successfully improved to level {}"), level)).open();
|
createInfoModal(tr("Identity successfully improved"), MessageHelper.formatMessage(tr("Identity successfully improved to level {}"), level)).open();
|
||||||
|
@ -76,12 +76,12 @@ namespace Modals {
|
||||||
input_current_level.val("error: " + error);
|
input_current_level.val("error: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(active)
|
if (active)
|
||||||
button_start_stop.trigger('click');
|
button_start_stop.trigger('click');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
createErrorModal(tr("Failed to improve identity"), tr("Failed to improve identity.<br>Error:") + error).open();
|
createErrorModal(tr("Failed to improve identity"), tr("Failed to improve identity.<br>Error:") + error).open();
|
||||||
if(active)
|
if (active)
|
||||||
button_start_stop.trigger('click');
|
button_start_stop.trigger('click');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -92,10 +92,10 @@ namespace Modals {
|
||||||
let seconds = Math.floor(time % 60).toString();
|
let seconds = Math.floor(time % 60).toString();
|
||||||
let minutes = Math.floor(time / 60).toString();
|
let minutes = Math.floor(time / 60).toString();
|
||||||
|
|
||||||
if(seconds.length < 2)
|
if (seconds.length < 2)
|
||||||
seconds = "0" + seconds;
|
seconds = "0" + seconds;
|
||||||
|
|
||||||
if(minutes.length < 2)
|
if (minutes.length < 2)
|
||||||
minutes = "0" + minutes;
|
minutes = "0" + minutes;
|
||||||
|
|
||||||
input_elapsed.val(minutes + ":" + seconds);
|
input_elapsed.val(minutes + ":" + seconds);
|
||||||
|
@ -119,7 +119,7 @@ namespace Modals {
|
||||||
return modal;
|
return modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnTeamSpeakIdentityImport(callback: (identity: profiles.identities.TeaSpeakIdentity) => any) : Modal {
|
function spawnTeamSpeakIdentityImport(callback: (identity: profiles.identities.TeaSpeakIdentity) => any): Modal {
|
||||||
let modal: Modal;
|
let modal: Modal;
|
||||||
let loaded_identity: profiles.identities.TeaSpeakIdentity;
|
let loaded_identity: profiles.identities.TeaSpeakIdentity;
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ namespace Modals {
|
||||||
const button_import = template.find(".button-import");
|
const button_import = template.find(".button-import");
|
||||||
const set_error = message => {
|
const set_error = message => {
|
||||||
template.find(".success").hide();
|
template.find(".success").hide();
|
||||||
if(message) {
|
if (message) {
|
||||||
template.find(".error").text(message).show();
|
template.find(".error").text(message).show();
|
||||||
button_import.prop("disabled", true);
|
button_import.prop("disabled", true);
|
||||||
} else
|
} else
|
||||||
|
@ -157,7 +157,7 @@ namespace Modals {
|
||||||
const element = event.target as HTMLInputElement;
|
const element = event.target as HTMLInputElement;
|
||||||
const file_reader = new FileReader();
|
const file_reader = new FileReader();
|
||||||
|
|
||||||
file_reader.onload = function() {
|
file_reader.onload = function () {
|
||||||
import_identity(file_reader.result as string, true);
|
import_identity(file_reader.result as string, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ namespace Modals {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(element.files && element.files.length > 0)
|
if (element.files && element.files.length > 0)
|
||||||
file_reader.readAsText(element.files[0]);
|
file_reader.readAsText(element.files[0]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ namespace Modals {
|
||||||
{ /* text input */
|
{ /* text input */
|
||||||
template.find(".button-load-text").on('click', event => {
|
template.find(".button-load-text").on('click', event => {
|
||||||
createInputModal("Import identity from text", "Please paste your idenity bellow<br>", text => text.length > 0 && text.indexOf('V') != -1, result => {
|
createInputModal("Import identity from text", "Please paste your idenity bellow<br>", text => text.length > 0 && text.indexOf('V') != -1, result => {
|
||||||
if(result)
|
if (result)
|
||||||
import_identity(result as string, false);
|
import_identity(result as string, false);
|
||||||
}).open();
|
}).open();
|
||||||
});
|
});
|
||||||
|
@ -197,7 +197,7 @@ namespace Modals {
|
||||||
return modal;
|
return modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function spawnSettingsModal() : Modal {
|
export function spawnSettingsModal(): Modal {
|
||||||
let modal: Modal;
|
let modal: Modal;
|
||||||
modal = createModal({
|
modal = createModal({
|
||||||
header: tr("Settings"),
|
header: tr("Settings"),
|
||||||
|
@ -206,6 +206,7 @@ namespace Modals {
|
||||||
client: native_client,
|
client: native_client,
|
||||||
valid_forum_identity: profiles.identities.valid_static_forum_identity(),
|
valid_forum_identity: profiles.identities.valid_static_forum_identity(),
|
||||||
forum_path: settings.static("forum_path"),
|
forum_path: settings.static("forum_path"),
|
||||||
|
voice_available: !!globalClient.voiceConnection
|
||||||
});
|
});
|
||||||
|
|
||||||
initialiseVoiceListeners(modal, (template = template.tabify()).find(".settings_audio"));
|
initialiseVoiceListeners(modal, (template = template.tabify()).find(".settings_audio"));
|
||||||
|
@ -226,12 +227,12 @@ namespace Modals {
|
||||||
console.log(tag);
|
console.log(tag);
|
||||||
{/* setup the forum */
|
{/* setup the forum */
|
||||||
const identity = profiles.identities.static_forum_identity();
|
const identity = profiles.identities.static_forum_identity();
|
||||||
if(identity && identity.valid()) {
|
if (identity && identity.valid()) {
|
||||||
tag.find(".not-connected").hide();
|
tag.find(".not-connected").hide();
|
||||||
|
|
||||||
tag.find(".property.username .value").text(identity.name());
|
tag.find(".property.username .value").text(identity.name());
|
||||||
const premium_tag = tag.find(".property.premium .value").text("");
|
const premium_tag = tag.find(".property.premium .value").text("");
|
||||||
if(identity.is_stuff() || identity.is_premium())
|
if (identity.is_stuff() || identity.is_premium())
|
||||||
premium_tag.append($.spawn("div").addClass("premium").text(tr("yes")));
|
premium_tag.append($.spawn("div").addClass("premium").text(tr("yes")));
|
||||||
else
|
else
|
||||||
premium_tag.append($.spawn("div").addClass("non-premium").text(tr("no")));
|
premium_tag.append($.spawn("div").addClass("non-premium").text(tr("no")));
|
||||||
|
@ -250,6 +251,17 @@ namespace Modals {
|
||||||
function initialiseVoiceListeners(modal: Modal, tag: JQuery) {
|
function initialiseVoiceListeners(modal: Modal, tag: JQuery) {
|
||||||
let currentVAD = settings.global("vad_type", "vad");
|
let currentVAD = settings.global("vad_type", "vad");
|
||||||
|
|
||||||
|
const display_error = (message: string) => {
|
||||||
|
const alert = tag.find(".settings-device-error").first();
|
||||||
|
alert.clone()
|
||||||
|
.alert()
|
||||||
|
.css("display", "block")
|
||||||
|
.insertAfter(alert)
|
||||||
|
.find(".message")
|
||||||
|
.text(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (globalClient.voiceConnection) {
|
||||||
{ //Initialized voice activation detection
|
{ //Initialized voice activation detection
|
||||||
const vad_tag = tag.find(".settings-vad-container");
|
const vad_tag = tag.find(".settings-vad-container");
|
||||||
|
|
||||||
|
@ -301,7 +313,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
|
|
||||||
let listener = (event: ppt.KeyEvent) => {
|
let listener = (event: ppt.KeyEvent) => {
|
||||||
if(event.type == ppt.EventType.KEY_TYPED) {
|
if (event.type == ppt.EventType.KEY_TYPED) {
|
||||||
settings.changeGlobal('vad_ppt_key', undefined); //TODO remove that because its legacy shit
|
settings.changeGlobal('vad_ppt_key', undefined); //TODO remove that because its legacy shit
|
||||||
console.log(tr("Got key %o"), event);
|
console.log(tr("Got key %o"), event);
|
||||||
|
|
||||||
|
@ -336,20 +348,20 @@ namespace Modals {
|
||||||
slider.on("input change", () => {
|
slider.on("input change", () => {
|
||||||
settings.changeGlobal("vad_threshold", slider.val().toString());
|
settings.changeGlobal("vad_threshold", slider.val().toString());
|
||||||
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
||||||
if(vad instanceof VoiceActivityDetectorVAD)
|
if (vad instanceof VoiceActivityDetectorVAD)
|
||||||
vad.percentageThreshold = slider.val() as number;
|
vad.percentageThreshold = slider.val() as number;
|
||||||
vad_tag.find(".vad_vad_slider_value").text(slider.val().toString());
|
vad_tag.find(".vad_vad_slider_value").text(slider.val().toString());
|
||||||
});
|
});
|
||||||
modal.properties.registerCloseListener(() => {
|
modal.properties.registerCloseListener(() => {
|
||||||
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
||||||
if(vad instanceof VoiceActivityDetectorVAD)
|
if (vad instanceof VoiceActivityDetectorVAD)
|
||||||
vad.percentage_listener = undefined;
|
vad.percentage_listener = undefined;
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let target_tag = vad_tag.find('input[type=radio][name="vad_type"][value="' + currentVAD + '"]');
|
let target_tag = vad_tag.find('input[type=radio][name="vad_type"][value="' + currentVAD + '"]');
|
||||||
if(target_tag.length == 0) {
|
if (target_tag.length == 0) {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.warn("Failed to find tag for " + currentVAD + ". Using latest tag!");
|
console.warn("Failed to find tag for " + currentVAD + ". Using latest tag!");
|
||||||
target_tag = vad_tag.find('input[type=radio][name="vad_type"]').last();
|
target_tag = vad_tag.find('input[type=radio][name="vad_type"]').last();
|
||||||
|
@ -358,16 +370,6 @@ namespace Modals {
|
||||||
setTimeout(() => target_tag.trigger('change'), 0);
|
setTimeout(() => target_tag.trigger('change'), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const display_error = (message: string) => {
|
|
||||||
const alert = tag.find(".settings-device-error").first();
|
|
||||||
alert.clone()
|
|
||||||
.alert()
|
|
||||||
.css("display", "block")
|
|
||||||
.insertAfter(alert)
|
|
||||||
.find(".message")
|
|
||||||
.text(message);
|
|
||||||
};
|
|
||||||
|
|
||||||
{ //Initialize microphone
|
{ //Initialize microphone
|
||||||
|
|
||||||
const setting_tag = tag.find(".settings-microphone");
|
const setting_tag = tag.find(".settings-microphone");
|
||||||
|
@ -385,9 +387,9 @@ namespace Modals {
|
||||||
navigator.mediaDevices.enumerateDevices().then(devices => {
|
navigator.mediaDevices.enumerateDevices().then(devices => {
|
||||||
const active_device = globalClient.voiceConnection.voiceRecorder.device_id();
|
const active_device = globalClient.voiceConnection.voiceRecorder.device_id();
|
||||||
|
|
||||||
for(const device of devices) {
|
for (const device of devices) {
|
||||||
console.debug(tr("Got device %s (%s): %s (%o)"), device.deviceId, device.kind, device.label);
|
console.debug(tr("Got device %s (%s): %s (%o)"), device.deviceId, device.kind, device.label);
|
||||||
if(device.kind !== 'audioinput') continue;
|
if (device.kind !== 'audioinput') continue;
|
||||||
|
|
||||||
$.spawn("option")
|
$.spawn("option")
|
||||||
.attr("device-id", device.deviceId)
|
.attr("device-id", device.deviceId)
|
||||||
|
@ -402,7 +404,7 @@ namespace Modals {
|
||||||
display_error(tr("Could not get microphone device list!"));
|
display_error(tr("Could not get microphone device list!"));
|
||||||
});
|
});
|
||||||
|
|
||||||
if(tag_select.find("option:selected").length == 0)
|
if (tag_select.find("option:selected").length == 0)
|
||||||
tag_select.find("option").prop("selected", true);
|
tag_select.find("option").prop("selected", true);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -420,6 +422,7 @@ namespace Modals {
|
||||||
update_devices();
|
update_devices();
|
||||||
setting_tag.find(".button-device-update").on('click', event => update_devices());
|
setting_tag.find(".button-device-update").on('click', event => update_devices());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{ //Initialize speaker
|
{ //Initialize speaker
|
||||||
const setting_tag = tag.find(".settings-speaker");
|
const setting_tag = tag.find(".settings-speaker");
|
||||||
|
@ -431,7 +434,7 @@ namespace Modals {
|
||||||
|
|
||||||
const active_device = audio.player.current_device();
|
const active_device = audio.player.current_device();
|
||||||
audio.player.available_devices().then(devices => {
|
audio.player.available_devices().then(devices => {
|
||||||
for(const device of devices) {
|
for (const device of devices) {
|
||||||
$.spawn("option")
|
$.spawn("option")
|
||||||
.attr("device-id", device.device_id)
|
.attr("device-id", device.device_id)
|
||||||
.text(device.name)
|
.text(device.name)
|
||||||
|
@ -445,7 +448,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if(tag_select.find("option:selected").length == 0)
|
if (tag_select.find("option:selected").length == 0)
|
||||||
tag_select.find("option").prop("selected", true);
|
tag_select.find("option").prop("selected", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +501,7 @@ namespace Modals {
|
||||||
const template_tag = $("#tmpl_settings-sound_entry");
|
const template_tag = $("#tmpl_settings-sound_entry");
|
||||||
const entry_tag = sound_tag.find(".sound-list-entries");
|
const entry_tag = sound_tag.find(".sound-list-entries");
|
||||||
|
|
||||||
for(const _sound in Sound) {
|
for (const _sound in Sound) {
|
||||||
const sound_name = Sound[_sound];
|
const sound_name = Sound[_sound];
|
||||||
|
|
||||||
console.log(sound.get_sound_volume(sound_name as Sound));
|
console.log(sound.get_sound_volume(sound_name as Sound));
|
||||||
|
@ -523,7 +526,7 @@ namespace Modals {
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const entry_container = sound_tag.find(".sound-list-entries-container");
|
const entry_container = sound_tag.find(".sound-list-entries-container");
|
||||||
if(entry_container.hasScrollBar())
|
if (entry_container.hasScrollBar())
|
||||||
entry_container.addClass("scrollbar");
|
entry_container.addClass("scrollbar");
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
@ -531,12 +534,12 @@ namespace Modals {
|
||||||
const filter_tag = sound_tag.find(".sound-list-filter input");
|
const filter_tag = sound_tag.find(".sound-list-filter input");
|
||||||
filter_tag.on('change keyup', event => {
|
filter_tag.on('change keyup', event => {
|
||||||
const filter = ((<HTMLInputElement>event.target).value || "").toLowerCase();
|
const filter = ((<HTMLInputElement>event.target).value || "").toLowerCase();
|
||||||
if(!filter)
|
if (!filter)
|
||||||
entry_tag.find(".entry").show();
|
entry_tag.find(".entry").show();
|
||||||
else {
|
else {
|
||||||
entry_tag.find(".entry").each((_, _entry) => {
|
entry_tag.find(".entry").each((_, _entry) => {
|
||||||
const entry = $(_entry);
|
const entry = $(_entry);
|
||||||
if(entry.text().toLowerCase().indexOf(filter) == -1)
|
if (entry.text().toLowerCase().indexOf(filter) == -1)
|
||||||
entry.hide();
|
entry.hide();
|
||||||
else
|
else
|
||||||
entry.show();
|
entry.show();
|
||||||
|
@ -547,44 +550,6 @@ namespace Modals {
|
||||||
|
|
||||||
modal.close_listener.push(sound.save);
|
modal.close_listener.push(sound.save);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initialise microphones
|
|
||||||
/*
|
|
||||||
let select_microphone = tag.find(".voice_microphone_select");
|
|
||||||
let select_error = tag.find(".voice_microphone_select_error");
|
|
||||||
|
|
||||||
navigator.mediaDevices.enumerateDevices().then(devices => {
|
|
||||||
let recoder = globalClient.voiceConnection.voiceRecorder;
|
|
||||||
|
|
||||||
console.log("Got " + devices.length + " devices:");
|
|
||||||
for(let device of devices) {
|
|
||||||
console.log(" - Type: %s Name %s ID: %s Group: %s", device.kind, device.label, device.deviceId, device.groupId);
|
|
||||||
if(device.kind == "audioinput") {
|
|
||||||
let dtag = $.spawn("option");
|
|
||||||
dtag.attr("device-id", device.deviceId);
|
|
||||||
dtag.attr("device-group", device.groupId);
|
|
||||||
dtag.text(device.label);
|
|
||||||
select_microphone.append(dtag);
|
|
||||||
|
|
||||||
if(recoder) dtag.prop("selected", device.deviceId == recoder.device_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error("Could not enumerate over devices!");
|
|
||||||
console.error(error);
|
|
||||||
select_error.text("Could not get device list!").show();
|
|
||||||
});
|
|
||||||
|
|
||||||
select_microphone.change(event => {
|
|
||||||
let deviceSelected = select_microphone.find("option:selected");
|
|
||||||
let deviceId = deviceSelected.attr("device-id");
|
|
||||||
let groupId = deviceSelected.attr("device-group");
|
|
||||||
console.log("Selected microphone device: id: %o group: %o", deviceId, groupId);
|
|
||||||
globalClient.voiceConnection.voiceRecorder.change_device(deviceId, groupId);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
//Initialise speakers
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initialise_translations(tag: JQuery) {
|
function initialise_translations(tag: JQuery) {
|
||||||
|
@ -648,7 +613,7 @@ namespace Modals {
|
||||||
tag_loading.show();
|
tag_loading.show();
|
||||||
i18n.iterate_translations((repo, entry) => {
|
i18n.iterate_translations((repo, entry) => {
|
||||||
let repo_tag = tag_list.find("[repository=\"" + repo.unique_id + "\"]");
|
let repo_tag = tag_list.find("[repository=\"" + repo.unique_id + "\"]");
|
||||||
if(repo_tag.length == 0) {
|
if (repo_tag.length == 0) {
|
||||||
repo_tag = template.renderTag({
|
repo_tag = template.renderTag({
|
||||||
type: "repository",
|
type: "repository",
|
||||||
name: repo.name || repo.url,
|
name: repo.name || repo.url,
|
||||||
|
@ -659,7 +624,7 @@ namespace Modals {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this repository?"), answer => {
|
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this repository?"), answer => {
|
||||||
if(answer) {
|
if (answer) {
|
||||||
i18n.delete_repository(repo);
|
i18n.delete_repository(repo);
|
||||||
update_list();
|
update_list();
|
||||||
}
|
}
|
||||||
|
@ -716,7 +681,7 @@ namespace Modals {
|
||||||
info_modal.open()
|
info_modal.open()
|
||||||
});
|
});
|
||||||
tag.on('click', e => {
|
tag.on('click', e => {
|
||||||
if(e.isDefaultPrevented()) return;
|
if (e.isDefaultPrevented()) return;
|
||||||
i18n.select_translation(repo, entry);
|
i18n.select_translation(repo, entry);
|
||||||
tag_list.find(".selected").removeClass("selected");
|
tag_list.find(".selected").removeClass("selected");
|
||||||
tag.addClass("selected");
|
tag.addClass("selected");
|
||||||
|
@ -734,7 +699,7 @@ namespace Modals {
|
||||||
{
|
{
|
||||||
tag.find(".button-add-repository").on('click', () => {
|
tag.find(".button-add-repository").on('click', () => {
|
||||||
createInputModal("Enter URL", tr("Enter repository URL:<br>"), text => true, url => { //FIXME test valid url
|
createInputModal("Enter URL", tr("Enter repository URL:<br>"), text => true, url => { //FIXME test valid url
|
||||||
if(!url) return;
|
if (!url) return;
|
||||||
|
|
||||||
tag_loading.show();
|
tag_loading.show();
|
||||||
i18n.load_repository(url as string).then(repository => {
|
i18n.load_repository(url as string).then(repository => {
|
||||||
|
@ -786,30 +751,30 @@ namespace Modals {
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
|
|
||||||
let tag: JQuery;
|
let tag: JQuery;
|
||||||
if(selected_type == profiles.identities.IdentitifyType.TEAFORO) {
|
if (selected_type == profiles.identities.IdentitifyType.TEAFORO) {
|
||||||
const forum_tag = tag = settings_tag.find(".identity-settings-teaforo");
|
const forum_tag = tag = settings_tag.find(".identity-settings-teaforo");
|
||||||
|
|
||||||
forum_tag.find(".connected, .disconnected").hide();
|
forum_tag.find(".connected, .disconnected").hide();
|
||||||
if(identity && identity.valid()) {
|
if (identity && identity.valid()) {
|
||||||
forum_tag.find(".connected").show();
|
forum_tag.find(".connected").show();
|
||||||
} else {
|
} else {
|
||||||
forum_tag.find(".disconnected").show();
|
forum_tag.find(".disconnected").show();
|
||||||
}
|
}
|
||||||
} else if(selected_type == profiles.identities.IdentitifyType.TEAMSPEAK) {
|
} else if (selected_type == profiles.identities.IdentitifyType.TEAMSPEAK) {
|
||||||
console.log("Set: " + identity);
|
console.log("Set: " + identity);
|
||||||
const teamspeak_tag = tag = settings_tag.find(".identity-settings-teamspeak");
|
const teamspeak_tag = tag = settings_tag.find(".identity-settings-teamspeak");
|
||||||
teamspeak_tag.find(".identity_string").val("");
|
teamspeak_tag.find(".identity_string").val("");
|
||||||
if(identity)
|
if (identity)
|
||||||
(identity as profiles.identities.TeaSpeakIdentity).export_ts().then(e => teamspeak_tag.find(".identity_string").val(e));
|
(identity as profiles.identities.TeaSpeakIdentity).export_ts().then(e => teamspeak_tag.find(".identity_string").val(e));
|
||||||
} else if(selected_type == profiles.identities.IdentitifyType.NICKNAME) {
|
} else if (selected_type == profiles.identities.IdentitifyType.NICKNAME) {
|
||||||
const name_tag = tag = settings_tag.find(".identity-settings-nickname");
|
const name_tag = tag = settings_tag.find(".identity-settings-nickname");
|
||||||
if(identity)
|
if (identity)
|
||||||
name_tag.find("input").val(identity.name());
|
name_tag.find("input").val(identity.name());
|
||||||
else
|
else
|
||||||
name_tag.find("input").val("");
|
name_tag.find("input").val("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tag)
|
if (tag)
|
||||||
tag.trigger('show');
|
tag.trigger('show');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -821,7 +786,7 @@ namespace Modals {
|
||||||
const update_profile_list = () => {
|
const update_profile_list = () => {
|
||||||
const profile_list = tag.find(".profile-list .list").empty();
|
const profile_list = tag.find(".profile-list .list").empty();
|
||||||
const profile_template = $("#settings-profile-list-entry");
|
const profile_template = $("#settings-profile-list-entry");
|
||||||
for(const profile of profiles.profiles()) {
|
for (const profile of profiles.profiles()) {
|
||||||
const list_tag = profile_template.renderTag({
|
const list_tag = profile_template.renderTag({
|
||||||
profile_name: profile.profile_name,
|
profile_name: profile.profile_name,
|
||||||
id: profile.id
|
id: profile.id
|
||||||
|
@ -829,7 +794,7 @@ namespace Modals {
|
||||||
|
|
||||||
const profile_status_update = () => {
|
const profile_status_update = () => {
|
||||||
list_tag.find(".status").hide();
|
list_tag.find(".status").hide();
|
||||||
if(profile.valid())
|
if (profile.valid())
|
||||||
list_tag.find(".status-valid").show();
|
list_tag.find(".status-valid").show();
|
||||||
else
|
else
|
||||||
list_tag.find(".status-invalid").show();
|
list_tag.find(".status-invalid").show();
|
||||||
|
@ -839,7 +804,7 @@ namespace Modals {
|
||||||
profile_list.find(".selected").removeClass("selected");
|
profile_list.find(".selected").removeClass("selected");
|
||||||
list_tag.addClass("selected");
|
list_tag.addClass("selected");
|
||||||
|
|
||||||
if(profile == selected_profile) return;
|
if (profile == selected_profile) return;
|
||||||
nickname_listener = () => list_tag.find(".name").text(profile.profile_name);
|
nickname_listener = () => list_tag.find(".name").text(profile.profile_name);
|
||||||
status_listener = profile_status_update;
|
status_listener = profile_status_update;
|
||||||
|
|
||||||
|
@ -848,14 +813,14 @@ namespace Modals {
|
||||||
|
|
||||||
|
|
||||||
profile_list.append(list_tag);
|
profile_list.append(list_tag);
|
||||||
if((!selected_profile && profile.id == "default") || selected_profile == profile)
|
if ((!selected_profile && profile.id == "default") || selected_profile == profile)
|
||||||
setTimeout(() => list_tag.trigger('click'), 1);
|
setTimeout(() => list_tag.trigger('click'), 1);
|
||||||
profile_status_update();
|
profile_status_update();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const display_error = (error?: string) => {
|
const display_error = (error?: string) => {
|
||||||
if(error){
|
if (error) {
|
||||||
settings_tag.find(".settings-profile-error").show().find(".message").html(error);
|
settings_tag.find(".settings-profile-error").show().find(".message").html(error);
|
||||||
} else
|
} else
|
||||||
settings_tag.find(".settings-profile-error").hide();
|
settings_tag.find(".settings-profile-error").hide();
|
||||||
|
@ -881,9 +846,9 @@ namespace Modals {
|
||||||
createInfoModal(tr("Identity imported"), tr("Your identity has been successfully imported!")).open();
|
createInfoModal(tr("Identity imported"), tr("Your identity has been successfully imported!")).open();
|
||||||
};
|
};
|
||||||
|
|
||||||
if(profile && profile.valid()) {
|
if (profile && profile.valid()) {
|
||||||
spawnYesNo(tr("Are you sure"), tr("Do you really want to import a new identity and override the old identity?"), result => {
|
spawnYesNo(tr("Are you sure"), tr("Do you really want to import a new identity and override the old identity?"), result => {
|
||||||
if(result)
|
if (result)
|
||||||
spawnTeamSpeakIdentityImport(set_identity);
|
spawnTeamSpeakIdentityImport(set_identity);
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
|
@ -891,10 +856,10 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
button_export.on('click', event => {
|
button_export.on('click', event => {
|
||||||
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK) as profiles.identities.TeaSpeakIdentity;
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK) as profiles.identities.TeaSpeakIdentity;
|
||||||
if(!profile) return;
|
if (!profile) return;
|
||||||
|
|
||||||
createInputModal(tr("File name"), tr("Please enter the file name"), text => !!text, name => {
|
createInputModal(tr("File name"), tr("Please enter the file name"), text => !!text, name => {
|
||||||
if(name) {
|
if (name) {
|
||||||
profile.export_ts(true).then(data => {
|
profile.export_ts(true).then(data => {
|
||||||
const element = $.spawn("a")
|
const element = $.spawn("a")
|
||||||
.text("donwload")
|
.text("donwload")
|
||||||
|
@ -925,9 +890,9 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if(profile && profile.valid()) {
|
if (profile && profile.valid()) {
|
||||||
spawnYesNo(tr("Are you sure"), tr("Do you really want to generate a new identity and override the old identity?"), result => {
|
spawnYesNo(tr("Are you sure"), tr("Do you really want to generate a new identity and override the old identity?"), result => {
|
||||||
if(result)
|
if (result)
|
||||||
generate_identity();
|
generate_identity();
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
|
@ -936,7 +901,7 @@ namespace Modals {
|
||||||
|
|
||||||
button_improve.on('click', event => {
|
button_improve.on('click', event => {
|
||||||
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK) as profiles.identities.TeaSpeakIdentity;
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK) as profiles.identities.TeaSpeakIdentity;
|
||||||
if(!profile) return;
|
if (!profile) return;
|
||||||
|
|
||||||
spawnTeamSpeakIdentityImprove(profile).close_listener.push(() => teamspeak_tag.trigger('show'));
|
spawnTeamSpeakIdentityImprove(profile).close_listener.push(() => teamspeak_tag.trigger('show'));
|
||||||
});
|
});
|
||||||
|
@ -945,7 +910,7 @@ namespace Modals {
|
||||||
teamspeak_tag.on('show', event => {
|
teamspeak_tag.on('show', event => {
|
||||||
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK) as profiles.identities.TeaSpeakIdentity;
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK) as profiles.identities.TeaSpeakIdentity;
|
||||||
|
|
||||||
if(!profile || !profile.valid()) {
|
if (!profile || !profile.valid()) {
|
||||||
identity_info_tag.hide();
|
identity_info_tag.hide();
|
||||||
teamspeak_tag.find(".identity-undefined").show();
|
teamspeak_tag.find(".identity-undefined").show();
|
||||||
button_export.prop("disabled", true);
|
button_export.prop("disabled", true);
|
||||||
|
@ -964,12 +929,12 @@ namespace Modals {
|
||||||
|
|
||||||
{ //The forum
|
{ //The forum
|
||||||
const teaforo_tag = settings_tag.find(".identity-settings-teaforo");
|
const teaforo_tag = settings_tag.find(".identity-settings-teaforo");
|
||||||
if(native_client) {
|
if (native_client) {
|
||||||
teaforo_tag.find(".native-teaforo-login").on('click', event => {
|
teaforo_tag.find(".native-teaforo-login").on('click', event => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const forum = require("teaforo.js");
|
const forum = require("teaforo.js");
|
||||||
const call = () => {
|
const call = () => {
|
||||||
if(modal.shown) {
|
if (modal.shown) {
|
||||||
display_settings(selected_profile);
|
display_settings(selected_profile);
|
||||||
status_listener();
|
status_listener();
|
||||||
}
|
}
|
||||||
|
@ -981,7 +946,8 @@ namespace Modals {
|
||||||
}
|
}
|
||||||
|
|
||||||
teaforo_tag.on('show', event => {
|
teaforo_tag.on('show', event => {
|
||||||
display_error(); /* clear error */
|
display_error();
|
||||||
|
/* clear error */
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,7 +958,7 @@ namespace Modals {
|
||||||
selected_profile.set_identity(profiles.identities.IdentitifyType.NICKNAME, new profiles.identities.NameIdentity(name));
|
selected_profile.set_identity(profiles.identities.IdentitifyType.NICKNAME, new profiles.identities.NameIdentity(name));
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
|
|
||||||
if(name.length < 3) {
|
if (name.length < 3) {
|
||||||
display_error("Name must be at least 3 characters long!");
|
display_error("Name must be at least 3 characters long!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1001,9 +967,9 @@ namespace Modals {
|
||||||
|
|
||||||
name_tag.on('show', event => {
|
name_tag.on('show', event => {
|
||||||
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.NICKNAME);
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.NICKNAME);
|
||||||
if(!profile)
|
if (!profile)
|
||||||
display_error("invalid profile");
|
display_error("invalid profile");
|
||||||
else if(!profile.valid())
|
else if (!profile.valid())
|
||||||
display_error("Name must be at least 3 characters long!");
|
display_error("Name must be at least 3 characters long!");
|
||||||
else
|
else
|
||||||
display_error();
|
display_error();
|
||||||
|
@ -1015,9 +981,9 @@ namespace Modals {
|
||||||
{
|
{
|
||||||
settings_tag.find(".setting-name").on('change', event => {
|
settings_tag.find(".setting-name").on('change', event => {
|
||||||
const value = settings_tag.find(".setting-name").val() as string;
|
const value = settings_tag.find(".setting-name").val() as string;
|
||||||
if(value && selected_profile) {
|
if (value && selected_profile) {
|
||||||
selected_profile.profile_name = value;
|
selected_profile.profile_name = value;
|
||||||
if(nickname_listener)
|
if (nickname_listener)
|
||||||
nickname_listener();
|
nickname_listener();
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
status_listener();
|
status_listener();
|
||||||
|
@ -1025,7 +991,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
settings_tag.find(".setting-default-nickname").on('change', event => {
|
settings_tag.find(".setting-default-nickname").on('change', event => {
|
||||||
const value = settings_tag.find(".setting-default-nickname").val() as string;
|
const value = settings_tag.find(".setting-default-nickname").val() as string;
|
||||||
if(value && selected_profile) {
|
if (value && selected_profile) {
|
||||||
selected_profile.default_username = value;
|
selected_profile.default_username = value;
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
status_listener();
|
status_listener();
|
||||||
|
@ -1033,7 +999,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
settings_tag.find(".setting-default-password").on('change', event => {
|
settings_tag.find(".setting-default-password").on('change', event => {
|
||||||
const value = settings_tag.find(".setting-default-password").val() as string;
|
const value = settings_tag.find(".setting-default-password").val() as string;
|
||||||
if(value && selected_profile) {
|
if (value && selected_profile) {
|
||||||
selected_profile.default_username = value;
|
selected_profile.default_username = value;
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
status_listener();
|
status_listener();
|
||||||
|
@ -1045,7 +1011,7 @@ namespace Modals {
|
||||||
{
|
{
|
||||||
tag.find(".button-add-profile").on('click', event => {
|
tag.find(".button-add-profile").on('click', event => {
|
||||||
createInputModal(tr("Please enter a name"), tr("Please enter a name for the new profile:<br>"), text => text.length > 0 && !profiles.find_profile_by_name(text), value => {
|
createInputModal(tr("Please enter a name"), tr("Please enter a name for the new profile:<br>"), text => text.length > 0 && !profiles.find_profile_by_name(text), value => {
|
||||||
if(value) {
|
if (value) {
|
||||||
display_settings(profiles.create_new_profile(value as string));
|
display_settings(profiles.create_new_profile(value as string));
|
||||||
update_profile_list();
|
update_profile_list();
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
|
@ -1054,7 +1020,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
|
|
||||||
tag.find(".button-set-default").on('click', event => {
|
tag.find(".button-set-default").on('click', event => {
|
||||||
if(selected_profile && selected_profile.id != 'default') {
|
if (selected_profile && selected_profile.id != 'default') {
|
||||||
profiles.set_default_profile(selected_profile);
|
profiles.set_default_profile(selected_profile);
|
||||||
update_profile_list();
|
update_profile_list();
|
||||||
profiles.mark_need_save();
|
profiles.mark_need_save();
|
||||||
|
@ -1062,10 +1028,10 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
|
|
||||||
tag.find(".button-delete").on('click', event => {
|
tag.find(".button-delete").on('click', event => {
|
||||||
if(selected_profile && selected_profile.id != 'default') {
|
if (selected_profile && selected_profile.id != 'default') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
spawnYesNo(tr("Are you sure?"), tr ("Do you really want to delete this profile?"), result => {
|
spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this profile?"), result => {
|
||||||
if(result) {
|
if (result) {
|
||||||
profiles.delete_profile(selected_profile);
|
profiles.delete_profile(selected_profile);
|
||||||
update_profile_list();
|
update_profile_list();
|
||||||
}
|
}
|
||||||
|
@ -1075,7 +1041,7 @@ namespace Modals {
|
||||||
}
|
}
|
||||||
|
|
||||||
modal.close_listener.push(() => {
|
modal.close_listener.push(() => {
|
||||||
if(profiles.requires_save())
|
if (profiles.requires_save())
|
||||||
profiles.save();
|
profiles.save();
|
||||||
});
|
});
|
||||||
update_profile_list();
|
update_profile_list();
|
||||||
|
|
|
@ -135,7 +135,21 @@ class ServerEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
spawnContextMenu(x: number, y: number, on_close: () => void = () => {}) {
|
spawnContextMenu(x: number, y: number, on_close: () => void = () => {}) {
|
||||||
|
let trigger_close = true;
|
||||||
spawn_context_menu(x, y, {
|
spawn_context_menu(x, y, {
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Show server info"),
|
||||||
|
callback: () => {
|
||||||
|
trigger_close = false;
|
||||||
|
this.channelTree.client.selectInfo.open_popover()
|
||||||
|
},
|
||||||
|
icon: "client-about",
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover()
|
||||||
|
}, {
|
||||||
|
type: MenuEntryType.HR,
|
||||||
|
visible: this.channelTree.client.selectInfo.is_popover(),
|
||||||
|
name: ''
|
||||||
|
}, {
|
||||||
type: MenuEntryType.ENTRY,
|
type: MenuEntryType.ENTRY,
|
||||||
icon: "client-virtualserver_edit",
|
icon: "client-virtualserver_edit",
|
||||||
name: tr("Edit"),
|
name: tr("Edit"),
|
||||||
|
@ -162,7 +176,7 @@ class ServerEntry {
|
||||||
createInfoModal(tr("Buddy invite URL"), tr("Your buddy invite URL:<br>") + url + tr("<bt>This has been copied to your clipboard.")).open();
|
createInfoModal(tr("Buddy invite URL"), tr("Your buddy invite URL:<br>") + url + tr("<bt>This has been copied to your clipboard.")).open();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MenuEntry.CLOSE(on_close)
|
MenuEntry.CLOSE(() => (trigger_close ? on_close : () => {})())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,7 @@ class VoiceConnection {
|
||||||
private vpacketId: number = 0;
|
private vpacketId: number = 0;
|
||||||
private chunkVPacketId: number = 0;
|
private chunkVPacketId: number = 0;
|
||||||
private send_task: NodeJS.Timer;
|
private send_task: NodeJS.Timer;
|
||||||
|
private _tag_favicon: JQuery;
|
||||||
|
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
@ -171,6 +172,7 @@ class VoiceConnection {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.send_task = setInterval(this.sendNextVoicePacket.bind(this), 20);
|
this.send_task = setInterval(this.sendNextVoicePacket.bind(this), 20);
|
||||||
|
this._tag_favicon = $("head link[rel='icon']");
|
||||||
}
|
}
|
||||||
|
|
||||||
native_encoding_supported() : boolean {
|
native_encoding_supported() : boolean {
|
||||||
|
@ -463,6 +465,8 @@ class VoiceConnection {
|
||||||
|
|
||||||
if(this.dataChannel)
|
if(this.dataChannel)
|
||||||
this.sendVoicePacket(new Uint8Array(0), this.current_channel_codec()); //TODO Use channel codec!
|
this.sendVoicePacket(new Uint8Array(0), this.current_channel_codec()); //TODO Use channel codec!
|
||||||
|
|
||||||
|
this._tag_favicon.attr('href', "img/favicon/teacup.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleVoiceStarted() {
|
private handleVoiceStarted() {
|
||||||
|
@ -470,5 +474,6 @@ class VoiceConnection {
|
||||||
|
|
||||||
if(this.client && this.client.getClient())
|
if(this.client && this.client.getClient())
|
||||||
this.client.getClient().speaking = true;
|
this.client.getClient().speaking = true;
|
||||||
|
this._tag_favicon.attr('href', "img/favicon/speaking.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
declare namespace WebAssembly {
|
declare namespace WebAssembly {
|
||||||
export function instantiateStreaming(stream: Promise<Response>, imports?: any) : Promise<ResultObject>;
|
export function instantiateStreaming(stream: Promise<Response>, imports?: any) : Promise<ResultObject>;
|
||||||
}
|
}
|
||||||
|
declare function postMessage(message: any): void;
|
||||||
|
|
||||||
const prefix = "[POWWorker] ";
|
const prefix = "[POWWorker] ";
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9a1c31f27fcac129fa3503c2c1d2096c126d3fd2
|
Subproject commit 23f9aca6b6dc1ffccd20d6da04953776a1882f2b
|
|
@ -1,17 +1,27 @@
|
||||||
html, body {
|
html, body {
|
||||||
height: 100%;
|
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
min-height: 250px;
|
||||||
|
min-width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-container {
|
.app-container {
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
right: 10px;
|
||||||
|
left: 10px;
|
||||||
|
bottom: 40px;
|
||||||
|
top: 10px;
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 50px);
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
display: flex; flex-direction: column; resize: both;
|
display: flex; flex-direction: column; resize: both;
|
||||||
|
|
Loading…
Reference in New Issue