Some changes :)

canary
WolverinDEV 2018-09-25 12:57:47 +02:00
parent b0a0e61a85
commit 99b465f1d6
10 changed files with 297 additions and 53 deletions

View File

@ -1,5 +1,10 @@
# Changelog:
* **25.09.18**:
- Added support for token use
- Added support for away messages
* Fixed away display within information bar
- Capturing last given address and nickname within connect modal
* **24.09.18**:
- Added server passwords within login modal
- Fixed native encoding for opera and firefox

145
css/control_bar.scss Normal file
View File

@ -0,0 +1,145 @@
$border_color_activated: rgba(255, 255, 255, .75);
$background_activated: rgba(0,0,0,0.25);
$background:lightgray;
.control_bar {
display: flex;
flex-direction: row;
.divider {
border-left:2px solid gray;
height: auto;
margin-left: 5px;
margin-right: 5px
}
.button {
cursor: pointer;
background-color: lightgray;
border-radius: 5px;
align-items: center;
border: 2px solid rgba(0, 0, 0, 0);
height: 36px;
width: 36px;
margin-right: 5px;
margin-left: 5px;
&:hover {
background-color: rgba(0,0,0,0.4);
border-color: rgba(255, 255, 255, .75);
/*box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);*/
}
&.activated {
background-color: rgba(0,0,0,0.25);
border-color: rgba(255, 255, 255, .75);
&:hover {
background-color: rgba(0,0,0,0.4);
border-color: rgba(255, 255, 255, .75);
}
}
}
.button-dropdown {
.buttons {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: 100%;
grid-gap: 2px;
.button {
margin-right: 0px;
}
.button-dropdown {
display: inline-flex;
justify-content: space-around;
width: 18px;
cursor: pointer;
border-radius: 0 5px 5px 0;
align-items: center;
border: 2px solid rgba(0, 0, 0, 0);
border-left: 0;
.arrow {
border: solid black;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
vertical-align: text-bottom;
}
}
&:hover {
.button {
border-right: 1px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
background-color: rgba(0,0,0,0.4);
border-color: rgba(255, 255, 255, .75);
/*box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);*/
}
.button-dropdown {
background-color: rgba(0,0,0,0.4);
border-color: rgba(255, 255, 255, .75);
/*box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);*/
}
}
}
.dropdown {
display: none;
position: absolute;
margin-left: 5px;
background-color: $background;
border-radius: 5px;
align-items: center;
border: 2px solid rgba(0, 0, 0, 0);
border-color: $border_color_activated;
width: 230px;
user-select: none;
z-index: 1000;
/*box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);*/
.icon {
vertical-align: middle;
margin-right: 5px;
}
& > div {
display: block;
cursor: pointer;
padding: 1px 2px 1px 4px;
&:hover {
background-color: $background_activated;
}
}
& > div:first-of-type {
border-radius: 2px 2px 0 0;
}
& > div:last-of-type {
border-radius: 0 0 2px 2px;
}
}
&:hover {
.dropdown.displayed {
display: block;
}
}
}
}

View File

@ -234,43 +234,6 @@ fieldset {
border-color: red;
}
.control_bar {
display: flex;
flex-direction: row;
}
.control_bar .button {
cursor: pointer;
background-color: lightgray;
border: rgba(0, 0, 0, 0) solid;
border-radius: 5px;
align-items: center;
border-width: 2px;
height: 36px;
width: 36px;
margin-right: 5px;
margin-left: 5px;
}
.control_bar .button:hover {
background-color: rgba(0,0,0,0.4);
border: rgba(255,255,255,.75) solid;
border-width: 2px;
/*box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);*/
}
.control_bar .button.activated {
background-color: rgba(0,0,0,0.25);
border: rgba(255,255,255,.75) solid;
border-width: 2px;
}
.control_bar .button.activated:hover {
background-color: rgba(0,0,0,0.4);
border: rgba(255,255,255,.75) solid;
border-width: 2px;
}
.GroupBox {
border: gray solid;
border-width: 2px;

View File

@ -41,6 +41,7 @@
<link rel="stylesheet" href="css/loader.css" type="text/css">
<link rel="stylesheet" href="css/music/info_plate.css" type="text/css">
<link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css">
<link rel="stylesheet" href="css/control_bar.css" type="text/css">
<link rel="stylesheet" href="vendor/bbcode/xbbcode.css" type="text/css">
<!-- https://localhost:9987/?forward_url=http%3A%2F%2Flocalhost%3A63344%2FWeb-Client%2Findex.php%3F_ijt%3D82b1uhmnh0a5l1n35nnjps5eid%26loader_ignore_age%3D1%26connect_default_host%3Dlocalhost%26default_connect_type%3Dforum%26default_connect_url%3Dtrue%26default_connect_type%3Dteamspeak%26default_connect_url%3Dlocalhost%253A9987 -->
@ -130,22 +131,54 @@
<div style="height: 45px; width: 100%; border-radius: 2px 0px 0px 0px; border-bottom-width: 0px; background-color: lightgrey"
class="main_container">
<div id="control_bar" class="control_bar">
<div class="button btn_connect">
<div class="button btn_connect" title="Connect to a server">
<div class="icon_x32 client-connect"></div>
</div>
<div class="button btn_disconnect" title="Disconnect from server" style="display: none">
<div class="icon_x32 client-disconnect"></div>
</div>
<!--<div class="button btn_disconnect"><div class="icon_x32 client-disconnect"></div></div>-->
<div style="border-left:2px solid gray;height: auto; margin-left: 5px; margin-right: 5px"></div>
<div class="button btn_client_away">
<div class="icon_x32 client-away"></div>
<div class="divider"></div>
<div class="button-dropdown btn_away" title="Toggle away status">
<div class="buttons">
<div class="button icon_x32 client-away btn_away_toggle"></div>
<div class="button-dropdown">
<div class="arrow"></div>
</div>
</div>
<div class="dropdown">
<div class="btn_away_toggle"><div class="icon client-away"></div><a>Toggle away status</a></div>
<div class="btn_away_message"><div class="icon client-away"></div><a>Set away message</a></div>
</div>
</div>
<div class="button btn_mute_input">
<div class="icon_x32 client-input_muted"></div>
<div class="icon_x32 client-input_muted" title="Mute/unmute microphone"></div>
</div>
<div class="button btn_mute_output">
<div class="icon_x32 client-output_muted"></div>
<div class="icon_x32 client-output_muted" title="Mute/unmute headphones"></div>
</div>
<div class="divider"></div>
<div class="button-dropdown btn_token" title="Use token">
<div class="buttons">
<div class="button icon_x32 client-token btn_token_use"></div>
<div class="button-dropdown">
<div class="arrow"></div>
</div>
</div>
<div class="dropdown">
<div class="btn_token_list"><div class="icon client-token"></div><a>List tokens</a></div>
<div class="btn_token_use"><div class="icon client-token_use"></div><a>Use token</a></div>
</div>
</div>
<div style="width: 100%"></div>
<div class="button btn_open_settings">
<div class="button btn_permissions" title="View/edit permissions">
<div class="icon_x32 client-permission_overview"></div>
</div>
<div class="divider"></div>
<div class="button btn_open_settings" title="Edit global client settings">
<div class="icon_x32 client-settings"></div>
</div>
</div>

View File

@ -216,5 +216,6 @@ class TSClient {
this.channelTree.reset();
this.voiceConnection.dropSession();
if(this.serverConnection) this.serverConnection.disconnect();
this.controlBar.update_connection_state();
}
}

View File

@ -120,6 +120,7 @@ class ServerConnection {
updateConnectionState(state: ConnectionState) {
this._connectionState = state;
this._client.controlBar.update_connection_state();
}
disconnect() : boolean {

View File

@ -31,11 +31,35 @@ class ControlBar {
initialise() {
this.htmlTag.find(".btn_connect").on('click', this.onConnect.bind(this));
this.htmlTag.find(".btn_client_away").on('click', this.onAway.bind(this));
this.htmlTag.find(".btn_disconnect").on('click', this.onDisconnect.bind(this));
this.htmlTag.find(".btn_mute_input").on('click', this.onInputMute.bind(this));
this.htmlTag.find(".btn_mute_output").on('click', this.onOutputMute.bind(this));
this.htmlTag.find(".btn_open_settings").on('click', this.onOpenSettings.bind(this));
{
let tokens = this.htmlTag.find(".btn_token");
tokens.find(".button-dropdown").on('click', () => {
tokens.find(".dropdown").addClass("displayed");
});
tokens.on('mouseleave', () => {
tokens.find(".dropdown").removeClass("displayed");
});
tokens.find(".btn_token_use").on('click', this.on_token_use.bind(this));
tokens.find(".btn_token_list").on('click', this.on_token_list.bind(this));
}
{
let away = this.htmlTag.find(".btn_away");
away.find(".button-dropdown").on('click', () => {
away.find(".dropdown").addClass("displayed");
});
away.on('mouseleave', () => {
away.find(".dropdown").removeClass("displayed");
});
away.find(".btn_away_toggle").on('click', this.on_away_toggle.bind(this));
away.find(".btn_away_message").on('click', this.on_away_set_message.bind(this));
}
//Need an initialise
this.muteInput = settings.global("mute_input") == "1";
@ -43,10 +67,18 @@ class ControlBar {
}
onAway() {
on_away_toggle() {
this._awayMessage = "";
this.away = !this._away;
}
on_away_set_message() {
createInputModal("Set away message", "Please enter the away message", message => true, message => {
if(message)
this.away = message;
}).open();
}
onInputMute() {
this.muteInput = !this._muteInput;
}
@ -114,13 +146,11 @@ class ControlBar {
this._away = true;
}
let tag = this.htmlTag.find(".btn_client_away");
let tag = this.htmlTag.find(".btn_away_toggle");
if( this._away) {
if(!tag.hasClass("activated"))
tag.addClass("activated");
tag.addClass("activated");
} else {
if(tag.hasClass("activated"))
tag.removeClass("activated");
tag.removeClass("activated");
}
if(this.handle.serverConnection.connected)
@ -180,4 +210,41 @@ class ControlBar {
private onConnect() {
Modals.spawnConnectModal(settings.static("connect_default_host", "ts.TeaSpeak.de"));
}
update_connection_state() {
switch (this.handle.serverConnection ? this.handle.serverConnection._connectionState : ConnectionState.UNCONNECTED) {
case ConnectionState.CONNECTED:
case ConnectionState.CONNECTING:
case ConnectionState.INITIALISING:
this.htmlTag.find(".btn_disconnect").show();
this.htmlTag.find(".btn_connect").hide();
break;
default:
this.htmlTag.find(".btn_disconnect").hide();
this.htmlTag.find(".btn_connect").show();
}
}
private onDisconnect() {
this.handle.handleDisconnect(DisconnectReason.REQUESTED); //TODO message?
this.update_connection_state();
}
private on_token_use() {
createInputModal("Use token", "Please enter your token/priviledge key", message => message.length > 0, result => {
if(!result) return;
if(this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("tokenuse", {
token: result
}).then(() => {
createInfoModal("Use token", "Toke successfully used!").open();
}).catch(error => {
createErrorModal("Use token", "Failed to use token: " + (error instanceof CommandResult ? error.message : error)).open();
});
}).open();
}
private on_token_list() {
createErrorModal("Not implemented", "Token list is not implemented yet!").open();
}
}

View File

@ -19,10 +19,12 @@ namespace Modals {
let field_address = tag.find(".connect_address");
let address = field_address.val().toString();
settings.changeGlobal("connect_address", address);
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.DOMAIN);
let field_nickname = tag.find(".connect_nickname");
let nickname = field_nickname.val().toString();
settings.changeGlobal("connect_name", nickname);
let flag_nickname = (nickname.length == 0 && connectIdentity && connectIdentity.name().length > 0) || nickname.length >= 3 && nickname.length <= 32;
if(flag_address) {
@ -48,7 +50,8 @@ namespace Modals {
}
};
tag.find(".connect_address").val(defaultHost);
tag.find(".connect_nickname").val(settings.static_global("connect_name", undefined));
tag.find(".connect_address").val(settings.static_global("connect_address", defaultHost));
tag.find(".connect_address").on("keyup", () => updateFields());
tag.find(".connect_nickname").on("keyup", () => updateFields());

View File

@ -219,5 +219,19 @@ function createErrorModal(header: BodyCreator, message: BodyCreator, props: Moda
props.body = ModalFunctions.divify(ModalFunctions.jqueriefy(message));
props.footer = ModalFunctions.divify(ModalFunctions.jqueriefy(""));
return createModal(props);
}
function createInfoModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: "" }) {
props = ModalFunctions.warpProperties(props);
let head = $.spawn("div");
head.addClass("modal-head-info");
ModalFunctions.divify(ModalFunctions.jqueriefy(header)).appendTo(head);
props.header = head;
props.body = ModalFunctions.divify(ModalFunctions.jqueriefy(message));
props.footer = ModalFunctions.divify(ModalFunctions.jqueriefy(""));
return createModal(props);
}

View File

@ -696,6 +696,18 @@
</div>
<!-- Costume tags/icons -->
<!-- Client is away -->
{{if property_client_away}}
<div style="display: inline-flex">
<div class="icon_x32 client-away" style="margin-right: 5px"></div>
<a style="align-self: center">Away
{{if property_client_away_message && property_client_away_message.length > 0}}
({{>property_client_away_message}})
{{/if}}
</a>
</div>
{{/if}}
<!-- Speakers/Headphones disabled -->
{{if !property_client_output_hardware}}
<div style="display: inline-flex">