Some updates

canary
WolverinDEV 2020-06-13 18:47:05 +02:00
parent d3df4f0976
commit b1ea450c5d
42 changed files with 562 additions and 2339 deletions

View File

@ -1,4 +1,8 @@
# Changelog:
* **13.06.20**
- Started to extract all color values and put them into css variables
- Fixed a minor issue related to server/channel groups
* **12.06.20**
- Added a copy/paste menu for all HTML input elements
- Heavily improved web client audio de/encoding

View File

@ -152,7 +152,6 @@ const loader_style = {
await loader.style.load_multiple([
"css/static/main.css",
"css/static/main-layout.css",
"css/static/helptag.css",
"css/static/scroll.css",
"css/static/channel-tree.css",
"css/static/ts/tab.css",
@ -173,7 +172,6 @@ const loader_style = {
"css/static/modal-volume.css",
"css/static/modal-latency.css",
"css/static/modal-invite.css",
"css/static/modal-playlist.css",
"css/static/modal-banlist.css",
"css/static/modal-banclient.css",
"css/static/modal-channelinfo.css",
@ -190,8 +188,6 @@ const loader_style = {
"css/static/modal-permissions.css",
"css/static/modal-group-assignment.css",
"css/static/overlay-image-preview.css",
"css/static/music/info_plate.css",
"css/static/frame/SelectInfo.css",
"css/static/context_menu.css",
"css/static/frame-chat.css",
"css/static/connection_handlers.css",

View File

@ -15,7 +15,6 @@ files=(
"css/static/frame-chat.css"
"css/static/server-log.css"
"css/static/scroll.css"
"css/static/helptag.css"
"css/static/hostbanner.css"
"css/static/htmltags.css"
"css/static/menu-bar.css"
@ -38,7 +37,6 @@ files=(
"css/static/modal-invite.css"
"css/static/modal-keyselect.css"
"css/static/modal-permissions.css"
"css/static/modal-playlist.css"
"css/static/modal-poke.css"
"css/static/modal-query.css"
"css/static/modal-server.css"
@ -54,8 +52,6 @@ files=(
"css/static/ts/icons.css"
"css/static/ts/icons_em.css"
"css/static/ts/country.css"
"css/static/music/info_plate.css"
"css/static/frame/SelectInfo.css"
)
target_file=`pwd`/../generated/static/base.css

View File

@ -1,5 +1,9 @@
@import "mixin";
html:root {
}
.container-connection-handlers {
$animation_length: .25s;

View File

@ -1,119 +0,0 @@
.select_info_table {
tr {
td {
&:nth-child(1) {
font-weight: bold;
padding-right: 5px;
//min-width: max(35%, 20px);
}
&:nth-child(2) {
//min-width: max(75%, 40px);
word-break: break-word;
}
}
}
.reserved-slots {
display: inline;
color: red;
}
}
.select_server {
height: 100%;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
flex-grow: 1;
.button-update {
width: 100%;
&:disabled {
pointer-events: none;
}
}
.container {
max-height: 100%;
display: flex;
flex-direction: column;
padding-right: 0;
padding-left: 0;
}
}
.select_info {
display: flex;
flex-direction: column;
justify-content: stretch;
width: 100%;
> .close {
z-index: 500;
display: none;
position: absolute;
right: 5px;
top: 5px;
}
> div {
width: 100%;
}
.container-banner {
position: relative;
flex-grow: 1;
flex-shrink: 2;
max-height: 300px;
min-height: 0;
display: flex;
justify-content: stretch;
overflow: hidden;
&.disabled {
display: none;
margin-bottom: 5px;
}
}
.container-select-info {
padding: 2px;
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
justify-content: stretch;
.select_server {
> div {
flex-grow: 1;
}
}
}
.client-avatar {
> div {
flex-grow: 1;
flex-shrink: 1;
> img {
max-width: 100%;
max-height: 100%;
}
}
}
.button-browser-info {
vertical-align: bottom;
cursor: pointer;
&:hover {
background-color: gray;
}
}
}

View File

@ -67,6 +67,10 @@
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
html:root {
--text: #999;
}
*, :before, :after {
box-sizing: border-box;
outline: none;

View File

@ -1,134 +0,0 @@
.help-tip-container {
/* position: relative; */
display: inline;
.help-tip {
position: absolute;
}
}
.help-tip {
z-index: 100;
display: inline-block;
position: relative;
text-align: center;
background-color: #BCDBEA;
border-radius: 50%;
width: 24px;
height: 24px;
font-size: 14px;
line-height: 26px;
cursor: default;
&:before {
content:'?';
font-weight: bold;
color:#fff;
}
&:hover, &.show {
p {
display:block;
transform-origin: 100% 0%;
-webkit-animation: fadeIn 0.3s ease-in-out;
animation: fadeIn 0.3s ease-in-out;
}
}
p {
display: none;
text-align: left;
background-color: #1E2021;
padding: 20px;
width: 400px; /* fallback */
width: max-content;
position: absolute;
border-radius: 3px;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
color: #FFF;
font-size: 13px;
line-height: 1.4;
&:before {
position: absolute;
content: '';
width:0;
height: 0;
border:6px solid transparent;
border-bottom-color:#1E2021;
top:-12px;
}
&:after {
width:100%;
height:40px;
content:'';
position: absolute;
top:-40px;
left:0;
}
}
&.tip-left {
p {
right: -4px;
&:before {
right: 10px;
}
}
}
&.tip-right {
p {
left: -4px;
&:before {
left: 10px;
}
}
}
&.tip-center {
p {
left: 50%;
transform: translate(-50%, 0);
&:before {
right: calc(50% - 5px);
}
}
}
&.tip-small {
width: 16px;
height: 16px;
font-size: 12px;
line-height: 18px;
}
}
@-webkit-keyframes fadeIn {
0% {
opacity:0;
transform: scale(0.6);
}
100% {
opacity:100%;
transform: scale(1);
}
}
@keyframes fadeIn {
0% { opacity:0; }
100% { opacity:100%; }
}

View File

@ -1,5 +1,9 @@
@import "mixin";
html:root {
--hostbanner-background: #2e2e2e;
}
.hostbanner {
.container-hostbanner {
position: relative;
@ -14,7 +18,7 @@
cursor: pointer;
&:not(.no-background) {
background-color: #2e2e2e;
background-color: var(--hostbanner-background);
border-top-left-radius: 5px;
border-top-right-radius: 5px;
-moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);

View File

@ -1,5 +1,5 @@
.htmltag-client, .htmltag-channel {
color: blue;
color: var(--text);
font-weight: bold;
cursor: pointer;
}

View File

@ -4,6 +4,21 @@ $separator_thickness: 5px;
$small_device: 650px;
$animation_length: .5s;
html:root {
--app-background: #1e1e1e;
--control-bar-background: #454545;
--chat-background: #353535;
--channel-tree-background: #353535;
--server-log-background: #353535;
--footer-background: #252525;
--footer-text: #666666;
--channel-chat-seperator: #707070;
}
.app {
min-width: 600px;
min-height: 330px;
@ -45,7 +60,7 @@ $animation_length: .5s;
width: 50%; /* "default" settings */
height: 100%;
background: #353535;
background: var(--channel-tree-background);
min-width: 200px;
display: flex;
@ -89,7 +104,7 @@ $animation_length: .5s;
width: 50%; /* "default" settings */
height: 100%;
background: #353535;
background: var(--chat-background);
min-width: 350px;
display: flex;
@ -125,7 +140,7 @@ $animation_length: .5s;
padding-right: 5px;
padding-left: 5px;
background: #353535;
background: var(--server-log-background);
}
> .container-footer {
@ -134,17 +149,17 @@ $animation_length: .5s;
height: 1.5em;
background: #252525;
color: #666666;
background: var(--footer-background);
color: var(--footer-text);
border-radius: 0 0 5px 5px;
padding-right: 5px;
padding-left: 5px;
padding-top: 2px;
-webkit-box-shadow: inset 0px 2px 5px 0px rgba(0,0,0,0.125);
-moz-box-shadow: inset 0px 2px 5px 0px rgba(0,0,0,0.125);
box-shadow: inset 0px 2px 5px 0px rgba(0,0,0,0.125);
-webkit-box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
-moz-box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
box-shadow: inset 0 2px 5px 0 rgba(0,0,0,0.125);
display: flex;
flex-direction: row;
@ -165,7 +180,7 @@ $animation_length: .5s;
}
a[href], a[href]:visited {
color: #666666!important;
color: var(--footer-text)!important;
}
}
}
@ -181,7 +196,7 @@ $animation_length: .5s;
height: 2em;
width: 100%;
background-color: #454545;
background-color: var(--control-bar-background);
display: flex;
flex-direction: column;
@ -250,7 +265,7 @@ $animation_seperator_length: .1s;
&.seperator-selected {
@include transition(all $animation_seperator_length ease-in-out);
background-color: #707070;
background-color: var(--channel-chat-seperator);
}
}
@ -270,5 +285,5 @@ html, body {
}
body {
background: #1e1e1e !important;
background: var(--app-background)!important;
}

View File

@ -1,6 +1,11 @@
@import "mixin";
@import "properties";
html:root {
--modal-newcomer-header-color: hsla(222, 5%, 39%, 1);
--modal-newcomer-divider: #313135;
}
.modal-body.modal-newcomer {
display: flex!important;
flex-direction: column!important;
@ -17,7 +22,7 @@
flex-shrink: 0;
flex-grow: 0;
color: #565656;
color: var(--modal-newcommer-header-color);
padding: .5em .5em .25em;
position: relative;
@ -40,7 +45,7 @@
height: 1.25px;
//background: linear-gradient(90deg, rgba(49,49,53,1) 80%, rgba(49,49,53,0) 100%);
background: rgba(49,49,53,1);
background: var(--modal-newcomer-divider);
}
&.hidden {
@ -118,23 +123,20 @@
padding: .5em;
.left .body {
// background-color: #19191b;
background-color: hsla(220, 4%, 13%, 1);
background-color: #202122;
.overlay {
background-color: hsla(220, 4%, 13%, 1);
background-color: #202122;
}
.profile.selected {
background-color: hsla(240, 2%, 8%, 1);
background-color: #141415;
}
}
}
&.step-identity {
}
&.step-identity { }
&.step-microphone {
}
&.step-microphone { }
&.hidden {
display: none;
@ -151,7 +153,7 @@
flex-direction: row;
justify-content: space-between;
border-top: 1.25px solid rgba(49,49,53,1);
border-top: 1.25px solid var(--modal-newcomer-divider);
padding: .5em;
}
}

View File

@ -1,6 +1,47 @@
@import "mixin";
@import "properties";
html:root {
--modal-permissions-header-text: #e1e1e1;
--modal-permissions-header-background: #19191b;
--modal-permissions-header-hover: #4e4e4e;
--modal-permissions-header-selected: #0073d4;
--modal-permission-right: #303036;
--modal-permission-left: #222226;
--modal-permissions-entry-hover: #28282c;
--modal-permissions-entry-selected: #111111;
--modal-permissions-current-group: #101012;
--modal-permissions-buttons-background: #1b1b1b;
--modal-permissions-buttons-hover: #262626;
--modal-permissions-buttons-disabled: hsla(0, 0%, 9%, 1);
--modal-permissions-seperator: #1e1e1e; /* the seperator for the "enter a unique id" and "client info" part */
--modal-permissions-container-seperator: #222224; /* the seperator between left and right */
--modal-permissions-icon-select: #121213;
--modal-permissions-icon-select-border: #0d0d0d;
--modal-permissions-icon-select-hover: #17171a;
--modal-permissions-icon-select-hover-border: #333333;
--modal-permissions-table-border: #1e2025;
--modal-permissions-table-header: #303036;
--modal-permissions-table-entry-odd: #303036;
--modal-permissions-table-entry-even: #25252a;
--modal-permissions-table-entry-hover: #343a47;
--modal-permissions-table-header-text: #e1e1e1;
--modal-permissions-table-entry-text: #535455;
--modal-permissions-table-entry-active-text: #e1e1e1;
--modal-permissions-table-entry-group-text: #e1e1e1;
--modal-permissions-table-input: #e1e1e1;
--modal-permissions-table-input-focus: #3f7dbf;
}
.modal-body.modal-permission-editor {
padding: 0!important;
@ -28,8 +69,8 @@
.header {
height: 4em;
background-color: #19191b;
color: #e1e1e1;
background-color: var(--modal-permissions-header-text);
color: var(--modal-permissions-header-background);
display: flex;
flex-direction: row;
@ -73,7 +114,7 @@
width: 75%;
min-width: 30em;
background-color: #303036;
background-color: var(--modal-permission-right);
.header {
> .entry {
@ -91,7 +132,7 @@
&:hover {
border: none;
border-bottom: 2px solid #4e4e4e;
border-bottom: 2px solid var(--modal-permissions-header-hover);
padding-bottom: 0;
@ -107,13 +148,13 @@
height: 100%;
width: calc(100% + 20em);
box-shadow: inset 0px -1.2em 3em -20px #424242;
box-shadow: inset 0px -1.2em 3em -20px var(--modal-permissions-header-hover);
}
}
&.selected {
border: none;
border-bottom: 2px solid #0073d4;
border-bottom: 2px solid var(--modal-permissions-header-selected);
padding-bottom: 0;
@ -129,7 +170,7 @@
height: 100%;
width: calc(100% + 20em);
box-shadow: inset 0px -1.2em 3em -20px #0073d4;
box-shadow: inset 0px -1.2em 3em -20px var(--modal-permissions-header-selected);
}
}
}
@ -168,7 +209,7 @@
min-height: 10em;
overflow: hidden;
background-color: #222226;
background-color: var(--modal-permission-left);
.header {
font-weight: bold;
@ -212,7 +253,7 @@
width: 100%;
.list-groups, .list-channel, .list-clients {
color: #999999;
color: var(--text);
display: flex;
flex-direction: column;
@ -252,15 +293,11 @@
width: 100%;
&:hover {
background-color: #28282c;
background-color: var(--modal-permissions-entry-hover);
}
&.selected {
background-color: #111111;
&.client {
background-color: #1a1b1e;
}
background-color: var(--modal-permissions-entry-selected);
}
@include transition(background-color .25s ease-in-out);
@ -296,15 +333,16 @@
cursor: pointer;
background-color: #1b1b1b;
background-color: var(--modal-permissions-buttons-background);
&:hover {
background-color: #262626;
background-color: var(--modal-permissions-buttons-hover);
}
&:disabled {
background-color: hsla(0, 0%, 9%, 1);
background-color: var(--modal-permissions-buttons-disabled);
}
@include transition(background-color .25s ease-in-out);
img {
@ -365,8 +403,8 @@
flex-direction: row;
justify-content: stretch;
background-color: #101012;
color: #999999;
background-color: var(--modal-permissions-current-group);
color: var(--text);
padding-left: .25em;
@ -405,7 +443,7 @@
hr {
border: none;
border-top: 2px solid #1e1e1e;
border-top: 2px solid var(--modal-permissions-seperator);
}
}
@ -420,7 +458,7 @@
.container-seperator {
width: 3px;
height: unset!important;
background-color: #222224!important;
background-color: var(--modal-permissions-container-seperator)!important;
}
}
@ -531,7 +569,7 @@
max-width: 10em;
min-width: 5em;
color: #999999;
color: var(--text);
> label {
font-size: .75em;
@ -571,15 +609,15 @@
justify-content: flex-end;
cursor: pointer;
background-color: #121213;
border: 1px solid #0d0d0d;
background-color: var(--modal-permissions-icon-select);
border: 1px solid var(--modal-permissions-icon-select-border);
.icon-preview {
height: 100%;
width: 3em;
border: none;
border-right: 1px solid #0d0d0d;
border-right: 1px solid var(--modal-permissions-icon-select-border);
display: flex;
flex-direction: column;
@ -614,7 +652,7 @@
text-align: center;
.arrow {
border-color: #999999;
border-color: var(--text);
}
}
@ -623,13 +661,13 @@
position: absolute;
width: max-content;
top: calc(2.5em - 1px);
top: calc(2.5em - 2px);
flex-direction: column;
justify-content: flex-start;
background-color: #121213;
border: 1px solid #0d0d0d;
background-color: var(--modal-permissions-icon-select);
border: 1px solid var(--modal-permissions-icon-select-border);
border-radius: .2em 0 .2em .2em;
right: -1px;
@ -639,11 +677,11 @@
&:not(:last-of-type) {
border: none;
border-bottom: 1px solid #0d0d0d;
border-bottom: 1px solid var(--modal-permissions-icon-select-border);
}
&:hover {
background-color: #17171a;
background-color: var(--modal-permissions-icon-select-hover);
}
}
}
@ -657,11 +695,11 @@
}
&:hover {
background-color: #17171a;
border-color: hsla(0, 0%, 20%, 1);
background-color: var(--modal-permissions-icon-select-hover);
border-color: var(--modal-permissions-icon-select-hover-border);
.icon-preview {
border-color: hsla(0, 0%, 20%, 1);
border-color: var(--modal-permissions-icon-select-hover-border);
}
}
@ -677,7 +715,7 @@
&.container-mode-permissions {
.container-permission-list {
width: 100%;
color: #999999;
color: var(--text);
display: flex;
flex-direction: column;
@ -697,9 +735,10 @@
height: 2em;
border: none;
border-bottom: 1px solid #1e2025;
border-bottom: 1px solid var(--modal-permissions-table-border);
background-color: var(--modal-permissions-table-entry-odd);
color: #535455;
color: var(--modal-permissions-table-entry-text);
@mixin fixed-column($name, $width) {
.column-#{$name} {
@ -717,7 +756,7 @@
padding-left: 1em;
border: none;
border-right: 1px solid #1e2025;
border-right: 1px solid var(--modal-permissions-table-border);
overflow: hidden;
@ -743,7 +782,7 @@
.arrow {
cursor: pointer;
border-color: #e1e1e1;
border-color: var(--modal-permissions-table-entry-active-text);
}
.group-name {
@ -757,16 +796,16 @@
&.active {
color: #e1e1e1;
color: var(--modal-permissions-table-entry-active-text);
}
&.group {
color: #e1e1e1;
color: var(--modal-permissions-table-entry-group-text);
font-weight: bold;
}
input {
color: #e1e1e1;
color: var(--modal-permissions-table-input);
outline: none;
background: transparent;
@ -782,7 +821,7 @@
border-bottom: 2px solid transparent;
&:focus {
border-bottom-color: #3f7dbf;
border-bottom-color: var(--modal-permissions-table-input-focus);
}
@include transition(border-bottom-color $button_hover_animation_time ease-in-out);
}
@ -806,10 +845,11 @@
.entry {
&.even {
background-color: #25252a;
background-color: var(--modal-permissions-table-entry-even);
}
&:hover {
background-color: #343a47;
background-color: var(--modal-permissions-table-entry-hover);
}
/* We cant use this effect here because the odd/even effect would be a bit crazy then */
//@include transition(background-color $button_hover_animation_time ease-in-out);
@ -817,9 +857,9 @@
}
.header {
background-color: unset;
background-color: var(--modal-permissions-table-header);
color: var(--modal-permissions-table-header-text);
color: #e1e1e1;
font-weight: bold;
.column-granted {
@ -838,7 +878,7 @@
text-align: center;
font-size: 2em;
color: #222226;
color: var(--modal-permission-left);
}
}

View File

@ -1,440 +0,0 @@
.playlist-management {
height: 100%;
display: flex!important;;
flex-direction: column!important;;
.header, .footer {
flex-grow: 0;
flex-shrink: 0;
}
.header {
display: flex;
flex-direction: row;
justify-content: stretch;
.buttons {
flex-grow: 0;
}
.search {
margin-left: 5px;
flex-grow: 1;
input {
width: 100%;
}
}
}
.playlist-list {
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
$width_id: 80px;
$width_type: 150px;
$width_used: 40px;
.column {
&.column-id {
width: 80px;
text-align: center;
}
&.column-title {
width: calc(50% - 95px - 40px);
}
&.column-creator {
width: calc(50% - 95px - 40px);
text-align: center;
}
&.column-type {
width: 150px;
flex-grow: 0;
text-align: center;
}
&.column-used {
width: 40px;
flex-grow: 0;
text-align: center;
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
}
}
.playlist-list-header {
flex-grow: 0;
flex-shrink: 0;
display: flex;
flex-direction: row;
.column {
border: 1px solid lightgray;
text-align: center;
}
}
.playlist-list-entries-container {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: start;
overflow-y: auto;
min-height: 250px;
.entry {
display: flex;
flex-direction: row;
.column {
margin-left: 2px;
}
cursor: pointer;
&.selected {
background-color: blue;
}
&.highlighted {
font-weight: bold;
}
}
&.scrollbar {
.column-title {
width: calc(50% - 95px - 40px + 30px)
}
.column-creator {
width: calc(50% - 95px - 40px + 30px)
}
}
}
}
.footer {
margin-top: 5px;
display: flex;
flex-direction: row;
justify-content: space-between;
.info {
align-self: center;
}
.buttons {
display: flex;
flex-direction: row;
justify-content: stretch;
.highlight-own {
display: flex;
flex-direction: row;
justify-content: stretch;
margin-right: 10px;
align-self: center;
}
}
}
}
.playlist-edit {
display: flex;
flex-direction: column;
justify-content: stretch;
min-height: 0;
.tab-content {
padding: 0; /* override tab-content setting */
}
.general-properties, .playback-properties {
padding: 5px;
width: 100%;
display: flex;
flex-direction: column;
.property {
display: flex;
flex-direction: row;
margin-bottom: 5px;
.key {
width: 150px;
flex-grow: 0;
}
.value {
flex-grow: 1;
flex-shrink: 1;
}
.checkbox-container {
input {
margin-left: 0;
}
}
&.property-description {
textarea {
resize: vertical;
max-height: 400px;
}
}
}
flex-shrink: 0;
flex-grow: 0;
}
.playback-properties {
.property .key {
width: 175px;
}
}
.container-permissions {
padding: 5px;
display: flex;
flex-direction: row;
justify-content: space-around;
.group_box {
min-width: 30%;
}
.permissions-list {
display: flex;
flex-direction: column;
}
}
.container-no-permissions {
background: lightgray;
padding: 50px;
text-align: center;
}
x-content {
overflow-y: hidden;
display: flex;
flex-direction: column;
}
.container-songs {
width: 100%;
display: flex;
flex-direction: column;
padding: 5px;
.song-list {
min-height: 300px;
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
.column {
&.column-id {
width: 50px;
}
&.column-url {
width: calc(100% - 140px)
}
&.column-loaded {
width: 50px;
flex-grow: 0;
display: flex;
justify-content: center;
flex-direction: row;
}
&.column-buttons {
width: 40px;
flex-grow: 0;
display: flex;
justify-content: center;
flex-direction: row;
.button {
display: flex;
flex-direction: column;
justify-content: center;
&:hover {
background: rgba(0, 0, 0, 0.2);
}
}
}
}
.song-list-header {
flex-grow: 0;
flex-shrink: 0;
display: flex;
flex-direction: row;
justify-content: center;
.column {
border: 1px solid lightgray;
text-align: center;
}
}
.song-list-entries-container {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: start;
overflow-y: auto;
min-height: 250px;
.entry {
display: flex;
flex-direction: row;
.column {
margin-left: 2px;
}
cursor: pointer;
&.selected {
background-color: blue;
}
&.playing {
background-color: lightgreen;
}
}
&.scrollbar {
&.column-url {
width: calc(100% - 140px + 30px)
}
}
}
}
.footer {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-grow: 0;
flex-shrink: 0;
margin-top: 5px;
}
}
> .buttons {
margin-top: 5px;
align-self: flex-end;
button {
width: 100px;
}
}
}
.container-song-info {
display: flex;
flex-shrink: 1;
flex-direction: column;
.properties {
display: flex;
flex-direction: column;
padding-bottom: 5px;
.property {
display: flex;
flex-direction: row;
justify-content: stretch;
flex-shrink: 0;
.key {
width: 150px;
flex-grow: 0;
}
.value {
flex-grow: 1;
}
&.property-metadata-raw {
flex-direction: column;
flex-shrink: 1;
margin-top: 5px;
.line {
width: 100%;
display: flex;
flex-direction: row;
justify-content: stretch;
flex-shrink: 0;
}
textarea {
margin-top: 5px;
width: 100%;
max-height: 100%;
resize: vertical;
}
}
}
}
}
.container-song-add {
display: flex;
flex-shrink: 1;
flex-direction: column;
.properties {
display: flex;
flex-direction: column;
padding-bottom: 5px;
.property {
margin-bottom: 5px;
display: flex;
flex-direction: row;
justify-content: stretch;
flex-shrink: 0;
.key {
width: 150px;
flex-grow: 0;
}
.value {
flex-grow: 1;
}
}
}
}

View File

@ -1,3 +1,8 @@
html:root {
--modal-poke-date: cornflowerblue;
--modal-poke-text: #004d00;
}
.container-poke {
display: flex!important;;
flex-direction: column!important;;
@ -47,10 +52,10 @@
}
.date {
color: cornflowerblue;
color: var(--modal-poke-date);
}
.text {
color: #004d00;
color: var(--modal-poke-text);
}
}
}
@ -80,17 +85,4 @@
float: right;
}
}
}
/*
<script class="jsrender-template" id="tmpl_poke_popup" type="text/html">
<div class="container-poke">
<div class="container-information">
<a>You have been poked by </a><node key="invoker"></node><a>:</a>
</div>
<div class="container-message">
<a class="message">{{>message}}</a>
</div>
</div>
</script>
*/
}

View File

@ -54,6 +54,22 @@
}
}
html:root {
--modal-query-title: #e0e0e0;
--modal-query-list: #28292b;
--modal-query-list-border: #1f2122;
--modal-query-empty: #4d4d4d;
--modal-query-error: #732626;
--modal-query-entry-hover: #2c2d2f;
--modal-query-entry-selected: #1a1a1b;
--modal-query-key: #557edc;
--modal-query-copy-hover: #28292b;
}
.modal-body.modal-query-manage {
display: flex!important;
flex-direction: row!important;
@ -100,7 +116,7 @@
a {
font-weight: bold;
color: #e0e0e0;
color: var(--modal-query-title);
flex-grow: 1;
flex-shrink: 1;
@ -145,8 +161,8 @@
justify-content: stretch;
border-radius: 0.2em;
border: 1px solid #1f2122;
background-color: #28292b;
border: 1px solid var(--modal-query-list-border);
background-color: var(--modal-query-list);
.container-entries {
flex-shrink: 1;
@ -175,12 +191,15 @@
text-align: center;
font-size: 2em;
background-color: #28292b;
color: hsla(0, 0%, 30%, 1);
background-color: var(--modal-query-list);
}
.container-empty {
color: var(--modal-query-empty);
}
.container-error {
color: #732626;
color: var(--modal-query-error);
}
.entry {
@ -201,11 +220,11 @@
cursor: pointer;
&:hover {
background-color: #2c2d2f;
background-color: var(--modal-query-entry-hover);
}
&.selected {
background-color: #1a1a1b;
background-color: var(--modal-query-entry-selected);
}
}
}
@ -216,7 +235,7 @@
padding: 0 .5em;
border-top: 1px solid #1f2122;
border-top: 1px solid var(--modal-query-list-border);
display: flex;
flex-direction: row;
@ -271,7 +290,7 @@
.title, .title a {
text-transform: uppercase;
color: #557edc;
color: var(--modal-query-key);
white-space: nowrap;
overflow: hidden;
@ -307,7 +326,7 @@
border-radius: .2em;
&:hover {
background: #28292b;
background: var(--modal-query-copy-hover);
}
margin-bottom: .2em; /* "text sub" */

View File

@ -1,5 +1,16 @@
@import "mixin";
html:root {
--serverinfo-background: #2f2f35;
--serverinfo-hostbanner-background: #26222a;
--serverinfo-group-border: #1f2122;
--serverinfo-group-background: #28292b;
--serverinfo-key: #557edc;
--serverinfo-value: #d6d6d7;
}
.modal-body.modal-server-info {
padding: 0!important;
width: 55em;
@ -8,7 +19,7 @@
flex-direction: column!important;
justify-content: flex-start!important;
background-color: #2f2f35;
background-color: var(--serverinfo-background);
.container-tooltip {
flex-shrink: 0;
@ -51,8 +62,7 @@
.container-hostbanner {
border: none;
border-radius: 0;
//background-color: #261f30;
background-color: hsla(265, 10%, 15%, 1);
background-color: var(--serverinfo-hostbanner-background);
}
&.hidden {
@ -77,9 +87,9 @@
padding: .5em;
border-radius: .2em;
border: 1px solid #1f2122;
border: 1px solid var(--serverinfo-group-border);
background-color: #28292b;
background-color: var(--serverinfo-group-background);
display: flex;
flex-direction: row;
@ -135,7 +145,7 @@
flex-shrink: 0;
flex-grow: 0;
color: #557edc;
color: var(--serverinfo-key);
text-transform: uppercase;
align-self: center;
@ -147,7 +157,7 @@
}
.value {
color: #d6d6d7;
color: var(--serverinfo-value);
align-self: center;
white-space: nowrap;
overflow: hidden;

View File

@ -1,7 +1,13 @@
@import "mixin";
$color_upload: #0a5eaa;
$color_download: #9f2712;
html:root {
--serverinfo-bandwidth-upload: #0a5eaa;
--serverinfo-bandwidth-download: #9f2712;
--serverinfo-title: #e3e3e4;
--serverinfo-statistics-title: #244c78;
}
.modal-body.modal-server-info-bandwidth {
padding: 0!important;
width: 55em;
@ -90,7 +96,7 @@ $color_download: #9f2712;
> a {
font-size: 1.25em;
color: #e3e3e4;
color: var(--serverinfo-title);
line-height: normal;
text-transform: uppercase;
@ -107,11 +113,11 @@ $color_download: #9f2712;
}
.upload {
color: $color_upload;
color: var(--serverinfo-bandwidth-upload);
}
.download {
color: $color_download;
color: var(--serverinfo-bandwidth-download);
}
}
@ -150,7 +156,7 @@ $color_download: #9f2712;
flex-grow: 0;
flex-shrink: 0;
color: #244c78;
color: var(--serverinfo-statistics-title);
font-size: 1.25em;
text-transform: uppercase;
@ -186,11 +192,11 @@ $color_download: #9f2712;
text-align: right;
.upload {
color: $color_upload;
color: var(--serverinfo-bandwidth-upload);
}
.download {
color: $color_download;
color: var(--serverinfo-bandwidth-download);
}
}
}

View File

@ -9,7 +9,7 @@
justify-content: stretch;
.htmltag-client {
color: #999!important;
color: var(--text)!important;
margin-left: .25em;
}

View File

@ -1,90 +1,3 @@
.channel_perm_tbl .value {
width: 60px;
}
.group_box {
display: flex;
flex-direction: column;
justify-content: stretch;
.header {
flex-grow: 0;
flex-shrink: 0;
float: left;
margin-bottom: 2px;
}
.content {
flex-grow: 1;
flex-shrink: 1;
background: rgba(0, 0, 0, .035);
border: lightgray solid 1px;
border-radius: 0 2px;
padding: 6px;
}
}
/* Channel edit/create modal */
.settings_audio {
display: grid;
grid-template-columns: 40% 60%;
grid-gap: 10px;
.custom {
display: grid;
grid-template-columns: min-content auto;
grid-template-rows: repeat(auto-fill, min-content);
grid-column-gap: 5px;
select {
height: fit-content;
}
.quality {
display: inline-grid;
grid-template-columns: auto min-content;
grid-column-gap: 5px;
}
}
}
.settings_advanced {
display: grid;
grid-template-columns: repeat(auto-fill, max-content);
grid-template-rows: repeat(auto-fill, max-content);
grid-gap: 5px;
> div:first-of-type {
grid-column: auto / span 2;
}
.max_limited {
width: 100%;
display: inline-flex;
input[type="number"] {
width: 75px;
}
}
.group_box {
fieldset, fieldset > div {
width: 100%;
}
}
}
.horizontal-stretch {
display: flex;
flex-grow: 1;
flex-direction: column;
}
.container-ban-type {
margin: 5px;
}
.arrow {
display: inline-block;
border: solid black;
@ -115,91 +28,4 @@
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
}
.layout-group-server, .layout-group-channel, .layout-channel, .layout-client, .layout-client-channel {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: stretch;
& > div {
margin: 5px;
}
.list-group-server, .list-group-channel, .list-group-server-clients, .list-channel {
border: grey solid 1px;
position: relative;
width: 175px;
flex-grow: 0;
min-width: 125px;
.entries {
display: table;
position: absolute;
top: 0; bottom: 0;
left: 0; right: 0;
min-width: 100%;
}
}
.list-group-server, .list-group-channel {
border: grey solid 1px;
user-select: none;
overflow: auto;
position: relative;
.group {
display: block;
white-space: nowrap;
cursor: pointer;
.icon, .icon_empty, .icon-container {
margin-right: 3px;
margin-left: 3px;
}
.name.savedb {
color: blue;
}
.name.default {
color: black;
font-weight: bold;
}
&.selected {
background-color: blue;
.name.savedb {
color: white;
}
}
}
}
}
.layout-channel, .layout-client-channel {
.list-channel {
display: flex;
flex-direction: column;
overflow: auto;
.channel {
cursor: pointer;
display: block;
width: 100%;
height: max-content;
white-space: nowrap;
.icon, .icon_empty {
margin-right: 3px;
}
&.selected {
background-color: blue;
}
}
}
}

View File

@ -1,315 +0,0 @@
$animtime: .5s;
$ease: cubic-bezier(.45, 0, .55, 1);
.music-wrapper {
display: flex;
position: relative;
width: 400px;
height: 400px;
user-select: none;
.left, .right {
position: absolute;
width: 50%;
height: 100%;
perspective-origin: 50% 50%;
perspective: 1200px;
label {
margin-bottom: 0!important; /* bootstrap fix */
}
.flip-card,
.static-card {
background: white;
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
border: 7px solid #dedede;
img {
width: calc(100% * 2);
//height: 100%;
}
}
.static-card {
border-right: none;
}
.flip-card {
border-left: none;
transform-origin: 0% 50%;
transition: transform $animtime $ease;
transform: rotateY(0);
&:before {
position: absolute;
content: '';
width: 100%;
height: 100%;
top: 0;
right: -20px;
box-shadow: 29px 0px 52px 6px rgba(186, 186, 186, 1);
}
img {
position: absolute;
background-color: #fff;
right: 0;
}
}
}
.left {
left: 0;
}
.right {
right: 0;
}
.right:hover {
.flip-card {
transform: rotateY(-60deg);
}
//z-index: 120;
}
.controls {
position: absolute;
right: 0;
width: 50%;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
cursor: pointer;
&:after {
position: absolute;
content: '';
right: 0;
top: 0;
width: 100%;
height: 100%;
box-shadow: inset 20px 0px 37px -10px rgba(0, 0, 0, 0.75);
pointer-events: none;
transition: width $animtime $ease;
}
input[type="radio"] {
position: absolute;
left: -1000px;
}
label {
flex-grow: 1;
display: block;
width: 100%;
border-top: 1px #e6e6e6 solid;
border-bottom: 1px #9c9c9c solid;
box-sizing: border-box;
cursor: pointer;
background-color: #dcdcdc;
span {
background: no-repeat 16px 42px;
width: 80px;
height: 125px;
display: block;
pointer-events: none;
}
}
input:checked + label,
label:active {
background-color: #BCBCBC;
box-shadow: inset 0px 0px 10px 5px rgba(120, 120, 120, 0.2);
border: 1px solid #fff;
}
//https://insidemartialartsmagazine.com.au/images/glyphicons/glyphicons/svg/individual_svg/
.btn-forward span {
background-size: calc(42px * 2) calc(42px * 2);
margin-left: 10px;
background: url("%%base_path%%/img/music/forward.svg") no-repeat center;
background: url("/img/music/forward.svg") no-repeat center;
background: url("img/music/forward.svg") no-repeat center;
}
.btn-rewind span {
background-size: calc(42px * 2) calc(42px * 2);
margin-left: 10px;
background: url("%%base_path%%/img/music/rewind.svg") no-repeat center;
background: url("/img/music/rewind.svg") no-repeat center;
background: url("img/music/rewind.svg") no-repeat center;
}
.btn-settings span {
background-size: calc(42px * 2) calc(42px * 2);
margin-left: 10px;
background: url("%%base_path%%/img/music/playlist.svg") no-repeat center;
background: url("/img/music/playlist.svg") no-repeat center;
background: url("img/music/playlist.svg") no-repeat center;
}
}
.controls-overlay {
position: absolute;
display: block;
top: calc(100% - 60px);
width: 100%;
height: 60px;
z-index: 100;
overflow-x: hidden;
transition: width $animtime $ease;
.song {
margin-top: 5px;
margin-left: 20px;
height: 15px;
width: 360px;
font-family: "DejaVu Serif", serif;
}
.timer {
margin-left: 20px;
height: 15px;
z-index: 200;
width: 360px;
display: inline-flex;
justify-content: space-between;
vertical-align: center;
.button-container{
display: inline-block;
> div {
display: inline-block;
}
}
.button {
width: 10px;
height: 12px;
margin-left: 2px;
svg {
fill: none;
stroke: #4c4c4c;;
stroke-width: 0.5;
stroke-miterlimit: 10;
cursor: pointer;
color: white;
mix-blend-mode: difference;
//box-shadow: 20px 20px 20px 20px rgb(186, 0, 12);
}
}
.button.active {
svg {
animation: bounce 500ms alternate;
transform: scale(1.3);
transition: transform 150ms;
}
}
.button:hover {
svg {
animation: bounce 500ms alternate;
transform: scale(1.1);
transition: transform 150ms;
}
}
.button.active:hover {
svg {
animation: bounce 500ms alternate;
transform: scale(1.5);
transition: transform 150ms;
}
}
.timeline * {
border: gray 0;
border-radius: 8px;
}
//TODO box SHADOW
.timeline {
width: calc(100% - 100px);
height: 4px;
float: left;
background: #DBE3E3;
position: relative;
align-self: center;
border: gray 0;
border-radius: 8px;
.buffered {
position: absolute;
width: 80%;
height: 100%;
background: #a0a0a0;
}
.played {
position: absolute;
width: 60%;
height: 100%;
background: #1fe2e3;
}
.slider {
position: absolute;
width: 4px;
height: 12px;
top: -4px;
background: #303030;
cursor: pointer;
}
}
.time {
min-width: 38px;
margin-left: 5px;
position: relative;
align-self: center;
font-family: 'fantasy'
}
}
}
.controls-overlay.flipped {
width: calc(50% + 7px);
}
}
.music-wrapper.empty {
border: 7px solid #dedede;
display: flex;
flex-direction: column;
background: white;
}
.music-wrapper.empty img {
margin: 5px;
-webkit-animation: rotation 5s infinite linear;
}
@-webkit-keyframes rotation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(359deg);
}
}
.music-wrapper.empty a {
text-align: center;
margin: 5px;
margin-top: 20px;
font-size: 20px;
font-family: Arial;
}

View File

@ -1,5 +1,11 @@
@import "mixin";
html:root {
--server-log-text: #6e6e6e;
--server-log-error: #e62222;
--server-log-tree-entry: #d8d8d8;
}
.container-log {
display: block;
overflow-y: auto;
@ -19,7 +25,7 @@
flex-shrink: 0;
flex-grow: 0;
color: #6e6e6e;
color: var(--server-log-text);
overflow-x: hidden;
overflow-y: hidden;
@ -47,15 +53,11 @@
.log-error {
color: rgba(230, 34, 34, 1);
&:hover {
color: rgba(230, 34, 34, 1);
}
color: var(--server-log-error);
}
.htmltag-client, .htmltag-channel {
color: #d8d8d8;
color: var(--server-log-tree-entry);
}
}
}

View File

@ -3447,81 +3447,6 @@
</div>
</script>
<!-- TODO: Delete me! -->
<script class="jsrender-template" id="tmpl_ban_create" type="text/html">
<div class="bancreate">
<div class="frame-container">
<div class="form-group">
<label class="bmd-label-static">{{tr "IP:" /}}</label>
<input class="form-control input-ip" type="text" maxlength="128">
</div>
<div class="form-row">
<div class="form-group">
<label class="bmd-label-static">{{tr "Name:" /}}</label>
<input class="form-control input-name" type="text" maxlength="128">
</div>
<div class="form-group">
<label class="bmd-label-static">{{tr "Interpret IP/Name as:" /}}</label>
<select class="form-control input-name-type">
<option value="wildcard-4">{{tr "Wildcard IPv4" /}}</option>
<option value="wildcard-6">{{tr "Wildcard IPv6" /}}</option>
<option value="fixed" selected>{{tr "Fixed string" /}}</option>
<option value="regex">{{tr "Regular Expression" /}}</option>
</select>
</div>
</div>
<div class="form-group">
<label class="bmd-label-static">{{tr "Unique ID:" /}}</label>
<div><input class="form-control input-uid" type="text" maxlength="64"></div>
</div>
<div class="form-group">
<label class="bmd-label-static">{{tr "Hardware ID:" /}}</label>
<input class="form-control input-hwid" type="text" max="64">
</div>
<div class="form-group container-reason">
<label class="bmd-label-static">{{tr "Reason" /}}</label>
<textarea class="form-control input-reason"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label>{{tr "Duration:" /}}</label>
<input type="number" value="1" class="form-control input-time" style="margin-right: 7px"
min="1">
</div>
<div class="form-group input-time-unit">
<select class="form-control input-time-unit">
<option value="sec">{{tr "seconds"/}}</option>
<option value="min">{{tr "minutes"/}}</option>
<option value="hours">{{tr "hours"/}}</option>
<option value="days">{{tr "days"/}}</option>
<option value="perm">{{tr "permanent"/}}</option>
</select>
</div>
</div>
<div class="footer">
<div class="switch">
<label>
<input type="checkbox" class="input-global">
{{tr "Use this ban as a global ban" /}}
<div class="help-tip tip-center tip-small">
<p>
{{tr "Global bans are bans which apply instance wide.<br>" +
"This means that (if this rule apply to a victim) cant join <b>any</b> virtualserver!<br>" +
"Global bans are by default shown to every server admin group,<br>" +
"but could only be created with query rights"/}}
</p>
</div>
</label>
</div>
<div class="bmd-form-group">
<button class="btn btn-danger button-close">{{tr "Cancel"/}}</button>
<button class="btn btn-success btn-raised button-success">{{tr "OK"/}}</button>
</div>
</div>
</div>
</div>
</script>
<!-- Music interface -->
<script class="jsrender-template" id="tmpl_music_frame" type="text/html">
<!-- First we want to define some variables if not defined yet. -->
@ -4003,13 +3928,6 @@
</div>
<a>{{tr "Connect directly" /}}</a>
<!--
<div class="help-tip tip-center tip-small">
<p>
{{tr "Lets the user directly connect to the server and not open the connect modal" /}}
</p>
</div>
-->
</label>
<label>
<div class="checkbox flag-resolved-address">
@ -4018,13 +3936,6 @@
</div>
<a>{{tr "Use resolved address" /}}</a>
<!--
<div class="help-tip tip-center tip-small">
<p>
{{tr "Use the resolved server address (IP) instead of the given address" /}}
</p>
</div>
-->
</label>
</div>
</div>
@ -4210,154 +4121,6 @@
</div>
</script>
<script class="jsrender-template" id="tmpl_playlist_edit" type="text/html">
<div class="playlist-edit">
<div class="general-properties">
<div class="form-group property-owner">
<label>{{tr "Playlist owner:" /}}</label>
<input type="text" class="form-control value" readonly>
</div>
<div class="form-group property-title">
<label>{{tr "Title:" /}}</label>
<input type="text" class="form-control value">
</div>
<div class="form-group property-description">
<label>{{tr "Description:" /}}</label>
<textarea class="form-control value"></textarea>
</div>
<div class="form-group property-type">
<label>{{tr "Type:" /}}</label>
<select class="form-control">
<option value="0">{{tr "Bot bound" /}}</option>
<option value="1">{{tr "Global" /}}</option>
</select>
</div>
</div>
<x-tab>
<x-entry>
<x-tag>{{tr "Songs" /}}</x-tag>
<x-content>
<div class="container-songs">
<div class="song-list">
<div class="song-list-header">
<div class="column column-id">{{tr "ID" /}}</div>
<div class="column column-url">{{tr "Url" /}}</div>
<div class="column column-loaded">{{tr "loaded" /}}</div>
<div class="column column-buttons"></div>
</div>
<div class="song-list-entries-container">
<div class="song-list-entries">
</div>
</div>
</div>
<div class="footer">
<div class="buttons">
<button class="btn btn-success button-song-add">{{tr "Add song" /}}</button>
<button class="btn btn-secondary button-refresh">{{tr "Refresh" /}}</button>
</div>
<div class="info-message"></div>
</div>
</div>
</x-content>
</x-entry>
<x-entry>
<x-tag>{{tr "Playback settings"/}}</x-tag>
<x-content>
<div class="playback-properties">
<div class="form-group property-replay-mode">
<label>{{tr "Replay mode" /}}</label>
<select class="form-control value">
<option value="0">{{tr "Normal"/}}</option>
<option value="1">{{tr "Loop list"/}}</option>
<option value="2">{{tr "Loop single entry"/}}</option>
<option value="3">{{tr "Shuffle"/}}</option>
</select>
</div>
<div class="form-group property-flag-delete-played">
<div class="switch">
<label>
<input type="checkbox">
{{tr "Delete played song:" /}}
</label>
</div>
</div>
<div class="form-group property-current-song">
<label>{{tr "Current replaying song:" /}}</label>
<input type="text" class="form-control value"/>
</div>
<div class="form-group property-flag-finished">
<div class="switch">
<label>
{{tr "Playlist finished status" /}}
<input type="checkbox">
<!-- TODO add info text here -->
</label>
</div>
</div>
</div>
</x-content>
</x-entry>
<x-entry>
<x-tag>{{tr "Permissions" /}}</x-tag>
<x-content>
<div class="container-permissions">
<div class="group_box">
<div class="header">{{tr "Access/modify powers" /}}</div>
<div class="content permissions-list">
<div class="form-group permission" permission="i_playlist_needed_view_power">
<label>{{tr "View power" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
<div class="form-group permission" permission="i_playlist_needed_modify_power">
<label>{{tr "Modify" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
<div class="form-group permission"
permission="i_playlist_needed_permission_modify_power">
<label>{{tr "Permission modify" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
<div class="form-group permission" permission="i_playlist_needed_delete_power">
<label>{{tr "Delete" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
</div>
</div>
<div class="group_box">
<div class="header">{{tr "Song management powers" /}}</div>
<div class="content permissions-list">
<div class="form-group permission"
permission="i_playlist_song_needed_add_power">
<label>{{tr "Song add" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
<div class="form-group permission"
permission="i_playlist_song_needed_move_power">
<label>{{tr "Song reorder" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
<div class="form-group permission"
permission="i_playlist_song_needed_remove_power">
<label>{{tr "Song delete" /}}</label>
<input type="number" min="0" value="0" class="form-control value">
</div>
</div>
</div>
</div>
<div class="container-no-permissions">
<div class="text">You dont have permissions to see playlist permissions!</div>
</div>
</x-content>
</x-entry>
</x-tab>
<div class="buttons">
<button class="btn btn-success button-save">{{tr "Save" /}}</button>
<button class="btn btn-secondary button-close">{{tr "Close" /}}</button>
</div>
</div>
</script>
<script class="jsrender-template" id="tmpl_playlist_edit-song_entry" type="text/html">
<div class="entry">
<div class="column column-id">{{>song_id}}</div>
@ -4809,7 +4572,7 @@
<div class="container-logo">
<img src="https://teaspeak.de/img/teaspeak_cup_animated.png"/>
</div>
<div class="copyright">Copyright (c) 2017-2019 TeaSpeak<br>(Markus Hadenfeldt)</div>
<div class="copyright">Copyright (c) 2017-2020 TeaSpeak<br>(Markus Hadenfeldt)</div>
<div class="versions">
{{if client}}
<div class="version version-native">

View File

@ -4,7 +4,7 @@ import {LogCategory} from "tc-shared/log";
import {PermissionManager, PermissionValue} from "tc-shared/permission/PermissionManager";
import {ServerCommand} from "tc-shared/connection/ConnectionBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {ConnectionEvents, ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import {AbstractCommandHandler} from "tc-shared/connection/AbstractCommandHandler";
import {Registry} from "tc-shared/events";
@ -32,13 +32,27 @@ export class GroupPermissionRequest {
promise: LaterPromise<PermissionValue[]>;
}
export interface GroupManagerEvents {
notify_reset: {},
notify_groups_created: {
groups: Group[],
cause: "list-update" | "initialize" | "user-action"
},
notify_groups_deleted: {
groups: Group[],
cause: "list-update" | "reset" | "user-action"
}
}
export interface GroupEvents {
notify_deleted: {},
notify_group_deleted: { },
notify_properties_updated: {
updated_properties: {[Key in keyof GroupProperties]: GroupProperties[Key]};
group_properties: GroupProperties
}
},
notify_needed_powers_updated: { }
}
export class Group {
@ -69,15 +83,19 @@ export class Group {
updateProperties(properties: {key: string, value: string}[]) {
let updates = {};
for(const { key, value } of properties) {
if(!JSON.map_field_to(this.properties, value, key))
continue; /* no updates */
if(key === "iconid")
this.properties.iconid = this.properties.iconid >>> 0;
updates[key] = this.properties[key];
}
if(Object.keys(updates).length === 0)
return;
this.events.fire("notify_properties_updated", {
group_properties: this.properties,
updated_properties: updates as any
@ -86,44 +104,6 @@ export class Group {
}
export class GroupManager extends AbstractCommandHandler {
readonly handle: ConnectionHandler;
serverGroups: Group[] = [];
channelGroups: Group[] = [];
private requests_group_permissions: GroupPermissionRequest[] = [];
constructor(client: ConnectionHandler) {
super(client.serverConnection);
client.serverConnection.command_handler_boss().register_handler(this);
this.handle = client;
}
destroy() {
this.handle.serverConnection && this.handle.serverConnection.command_handler_boss().unregister_handler(this);
this.serverGroups = undefined;
this.channelGroups = undefined;
}
handle_command(command: ServerCommand): boolean {
switch (command.command) {
case "notifyservergrouplist":
case "notifychannelgrouplist":
this.handle_grouplist(command.arguments);
return true;
case "notifyservergrouppermlist":
case "notifychannelgrouppermlist":
this.handle_group_permission_list(command.arguments);
return true;
}
return false;
}
requestGroups(){
this.handle.serverConnection.send_command("servergrouplist");
this.handle.serverConnection.send_command("channelgrouplist");
}
static sorter() : (a: Group, b: Group) => number {
return (a, b) => {
if(!a)
@ -144,78 +124,159 @@ export class GroupManager extends AbstractCommandHandler {
}
}
serverGroup?(id: number) : Group {
for(let group of this.serverGroups)
if(group.id == id) return group;
return undefined;
readonly events = new Registry<GroupManagerEvents>();
readonly connectionHandler: ConnectionHandler;
serverGroups: Group[] = [];
channelGroups: Group[] = [];
private readonly connectionStateListener;
private groupPermissionRequests: GroupPermissionRequest[] = [];
constructor(client: ConnectionHandler) {
super(client.serverConnection);
this.connectionHandler = client;
this.connectionStateListener = (event: ConnectionEvents["notify_connection_state_changed"]) => {
if(event.new_state === ConnectionState.DISCONNECTING || event.new_state === ConnectionState.UNCONNECTED || event.new_state === ConnectionState.CONNECTING)
this.reset();
};
client.serverConnection.command_handler_boss().register_handler(this);
client.events().on("notify_connection_state_changed", this.connectionStateListener);
this.reset();
}
channelGroup?(id: number) : Group {
for(let group of this.channelGroups)
if(group.id == id) return group;
return undefined;
destroy() {
this.reset();
this.connectionHandler.events().off("notify_connection_state_changed", this.connectionStateListener);
this.connectionHandler.serverConnection?.command_handler_boss().unregister_handler(this);
this.serverGroups = undefined;
this.channelGroups = undefined;
}
private handle_grouplist(json) {
let target : GroupTarget;
if(json[0]["sgid"]) target = GroupTarget.SERVER;
else if(json[0]["cgid"]) target = GroupTarget.CHANNEL;
else {
log.error(LogCategory.CLIENT, tr("Could not resolve group target! => %o"), json[0]);
reset() {
if(this.serverGroups.length === 0 && this.channelGroups.length === 0)
return;
log.debug(LogCategory.PERMISSIONS, tr("Resetting server/channel groups"));
this.serverGroups = [];
this.channelGroups = [];
for(const permission of this.groupPermissionRequests)
permission.promise.rejected(tr("Group manager reset"));
this.groupPermissionRequests = [];
this.events.fire("notify_reset");
}
handle_command(command: ServerCommand): boolean {
switch (command.command) {
case "notifyservergrouplist":
this.handleGroupList(command.arguments, GroupTarget.SERVER);
return true;
case "notifychannelgrouplist":
this.handleGroupList(command.arguments, GroupTarget.CHANNEL);
return true;
case "notifyservergrouppermlist":
case "notifychannelgrouppermlist":
this.handleGroupPermissionList(command.arguments);
return true;
}
return false;
}
let group_list = target == GroupTarget.SERVER ? this.serverGroups : this.channelGroups;
const deleted_groups = group_list.slice(0);
requestGroups(){
this.connectionHandler.serverConnection.send_command("servergrouplist", {}, { process_result: false }).catch(error => {
log.warn(LogCategory.PERMISSIONS, tr("Failed to request the server group list: %o"), error);
});
for(const group_data of json) {
this.connectionHandler.serverConnection.send_command("channelgrouplist", {}, { process_result: false }).catch(error => {
log.warn(LogCategory.PERMISSIONS, tr("Failed to request the channel group list: %o"), error);
});
}
findServerGroup(id: number) : Group | undefined {
for(let group of this.serverGroups)
if(group.id === id)
return group;
return undefined;
}
findChannelGroup(id: number) : Group | undefined {
for(let group of this.channelGroups)
if(group.id === id)
return group;
return undefined;
}
private handleGroupList(json: any[], target: GroupTarget) {
let groupList = target == GroupTarget.SERVER ? this.serverGroups : this.channelGroups;
const deleteGroups = groupList.slice(0);
const newGroups: Group[] = [];
const isInitialList = groupList.length === 0;
for(const groupData of json) {
let type : GroupType;
switch (parseInt(group_data["type"])) {
switch (parseInt(groupData["type"])) {
case 0: type = GroupType.TEMPLATE; break;
case 1: type = GroupType.NORMAL; break;
case 2: type = GroupType.QUERY; break;
default:
log.error(LogCategory.CLIENT, tr("Invalid group type: %o for group %s"), group_data["type"],group_data["name"]);
log.error(LogCategory.CLIENT, tr("Invalid group type: %o for group %s"), groupData["type"], groupData["name"]);
continue;
}
const group_id = parseInt(target == GroupTarget.SERVER ? group_data["sgid"] : group_data["cgid"]);
let group_index = deleted_groups.findIndex(e => e.id === group_id);
const groupId = parseInt(target == GroupTarget.SERVER ? groupData["sgid"] : groupData["cgid"]);
let groupIndex = deleteGroups.findIndex(e => e.id === groupId);
let group: Group;
if(group_index === -1) {
group = new Group(this, group_id, target, type, group_data["name"]);
group_list.push(group);
} else
group = deleted_groups.splice(group_index, 1)[0];
if(groupIndex === -1) {
group = new Group(this, groupId, target, type, groupData["name"]);
groupList.push(group);
newGroups.push(group);
} else {
group = deleteGroups.splice(groupIndex, 1)[0];
}
const property_blacklist = [
"sgid", "cgid", "type", "name",
"n_member_removep", "n_member_addp", "n_modifyp"
];
group.updateProperties(Object.keys(group_data).filter(e => property_blacklist.findIndex(a => a === e) === -1).map(e => { return { key: e, value: group_data[e] } }));
group.requiredMemberRemovePower = parseInt(group_data["n_member_removep"]);
group.requiredMemberAddPower = parseInt(group_data["n_member_addp"]);
group.requiredModifyPower = parseInt(group_data["n_modifyp"]);
group.requiredMemberRemovePower = parseInt(groupData["n_member_removep"]);
group.requiredMemberAddPower = parseInt(groupData["n_member_addp"]);
group.requiredModifyPower = parseInt(groupData["n_modifyp"]);
group.updateProperties(Object.keys(groupData).filter(e => property_blacklist.findIndex(a => a === e) === -1).map(e => { return { key: e, value: groupData[e] } }));
group.events.fire("notify_needed_powers_updated");
}
for(const deleted of deleted_groups) {
group_list.remove(deleted);
deleted.events.fire("notify_deleted");
if(newGroups.length !== 0) {
this.events.fire("notify_groups_created", { groups: newGroups, cause: isInitialList ? "initialize" : "list-update" });
}
for(const deleted of deleteGroups) {
groupList.remove(deleted);
deleted.events.fire("notify_group_deleted");
}
if(deleteGroups.length !== 0) {
this.events.fire("notify_groups_deleted", { groups: deleteGroups, cause: "list-update" });
}
}
request_permissions(group: Group) : Promise<PermissionValue[]> { //database_empty_result
for(let request of this.requests_group_permissions)
request_permissions(group: Group) : Promise<PermissionValue[]> {
for(let request of this.groupPermissionRequests)
if(request.group_id == group.id && request.promise.time() + 1000 > Date.now())
return request.promise;
let req = new GroupPermissionRequest();
req.group_id = group.id;
req.promise = new LaterPromise<PermissionValue[]>();
this.requests_group_permissions.push(req);
this.groupPermissionRequests.push(req);
this.handle.serverConnection.send_command(group.target == GroupTarget.SERVER ? "servergrouppermlist" : "channelgrouppermlist", {
this.connectionHandler.serverConnection.send_command(group.target == GroupTarget.SERVER ? "servergrouppermlist" : "channelgrouppermlist", {
cgid: group.id,
sgid: group.id
}).catch(error => {
@ -226,21 +287,21 @@ export class GroupManager extends AbstractCommandHandler {
}).then(() => {
//No notify handler
setTimeout(() => {
if(this.requests_group_permissions.remove(req))
if(this.groupPermissionRequests.remove(req))
req.promise.rejected(tr("no response"));
}, 1000);
});
return req.promise;
}
private handle_group_permission_list(json: any[]) {
let group = json[0]["sgid"] ? this.serverGroup(parseInt(json[0]["sgid"])) : this.channelGroup(parseInt(json[0]["cgid"]));
private handleGroupPermissionList(json: any[]) {
let group = json[0]["sgid"] ? this.findServerGroup(parseInt(json[0]["sgid"])) : this.findChannelGroup(parseInt(json[0]["cgid"]));
if(!group) {
log.error(LogCategory.PERMISSIONS, tr("Got group permissions for group %o/%o, but its not a registered group!"), json[0]["sgid"], json[0]["cgid"]);
return;
}
let requests: GroupPermissionRequest[] = [];
for(let req of this.requests_group_permissions)
for(let req of this.groupPermissionRequests)
if(req.group_id == group.id)
requests.push(req);
@ -249,9 +310,9 @@ export class GroupManager extends AbstractCommandHandler {
return;
}
let permissions = PermissionManager.parse_permission_bulk(json, this.handle.permissions);
let permissions = PermissionManager.parse_permission_bulk(json, this.connectionHandler.permissions);
for(let req of requests) {
this.requests_group_permissions.remove(req);
this.groupPermissionRequests.remove(req);
req.promise.resolved(permissions);
}
}

View File

@ -629,10 +629,10 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
return ChannelType.TEMPORARY;
}
joinChannel() {
if(this.properties.channel_flag_password === true && !this.cachedPasswordHash) {
this.requestChannelPassword(PermissionType.B_CHANNEL_JOIN_IGNORE_PASSWORD).then(password => {
this.joinChannel();
joinChannel(ignorePasswordFlag?: boolean) {
if(this.properties.channel_flag_password === true && !this.cachedPasswordHash && !ignorePasswordFlag) {
this.requestChannelPassword(PermissionType.B_CHANNEL_JOIN_IGNORE_PASSWORD).then(() => {
this.joinChannel(true);
});
return;
}

View File

@ -237,7 +237,7 @@ export class ClientInfo {
if(client) {
const invalid_groups = [];
const groups = client.assignedServerGroupIds().map(group_id => {
const result = this.handle.handle.groups.serverGroup(group_id);
const result = this.handle.handle.groups.findServerGroup(group_id);
if(!result)
invalid_groups.push(group_id);
return result;
@ -263,7 +263,7 @@ export class ClientInfo {
container_group.children().detach();
if(client) {
const group_id = client.assignedChannelGroup();
let group = this.handle.handle.groups.channelGroup(group_id);
let group = this.handle.handle.groups.findChannelGroup(group_id);
if(group) {
container_group.append(
$.spawn("div").addClass("group-container")

View File

@ -303,7 +303,7 @@ function apply_groups(client: ClientEntry, tag: JQuery, modal: Modal, callbacks:
if(group_id == client.channelTree.server.properties.virtualserver_default_server_group)
continue;
const group = client.channelTree.client.groups.serverGroup(group_id);
const group = client.channelTree.client.groups.findServerGroup(group_id);
if(!group) continue; //This shall never happen!
container_empty.hide();

View File

@ -44,7 +44,7 @@ export function createServerGroupAssignmentModal(client: ClientEntry, callback:
entry.on('change', event => {
let group_id = parseInt(entry.attr("group-id"));
let group = client.channelTree.client.groups.serverGroup(group_id);
let group = client.channelTree.client.groups.findServerGroup(group_id);
if(!group) {
console.warn(tr("Could not resolve target group!"));
return false;

View File

@ -353,7 +353,7 @@ function permission_controller(event_registry: Registry<modal.music_manage>, bot
for(const e of result) {
if(e.type !== "server_group") continue;
const group = client.groups.serverGroup((e as ServerGroup).group_id);
const group = client.groups.findServerGroup((e as ServerGroup).group_id);
if(!group) continue;
groups.push({

View File

@ -1,6 +1,31 @@
@import "../../../../css/static/mixin";
@import "../../../../css/static/properties";
html:root {
--modal-transfer-refresh-hover: #ffffff0e;
--modal-transfer-path-hover: #E6E6E6;
--modal-transfer-error-overlay-text: #9e9494;
--modal-transfer-filelist: #28292b;
--modal-transfer-filelist-border: #161616;
--modal-transfer-entry-hover: #2c2d2f;
--modal-transfer-entry-selected: #1a1a1b;
--modal-transfer-indicator-red: #a10000;
--modal-transfer-indicator-red-end: #e60000;
--modal-transfer-indicator-blue: #005fa1;
--modal-transfer-indicator-blue-end: #007acc;
--modal-transfer-indicator-green: #389738;
--modal-transfer-indicator-green-end: #4ecc4e;
--modal-transfer-indicator-hidden: #28292b00;
--modal-transfer-indicator-hidden-end: #28292b00;
}
.container {
padding: 1em;
position: relative;
@ -53,7 +78,7 @@
cursor: pointer;
&:hover {
background-color: #ffffff0e;
background-color: var(--modal-transfer-refresh-hover);
}
}
}
@ -90,7 +115,7 @@
@include transition(color $button_hover_animation_time ease-in-out);
&:hover, &.hovered {
color: #E6E6E6;
color: var(--modal-transfer-path-hover);
}
}
}
@ -104,16 +129,16 @@
margin-top: 1em;
border: 1px #161616 solid;
border: 1px var(--modal-transfer-filelist-border) solid;
border-radius: 0.2em;
background-color: #28292b;
background-color: var(--modal-transfer-filelist);
.header {
z-index: 1;
padding-top: .2em;
padding-bottom: .2em;
background-color: #28292b;
background-color: var(--modal-transfer-filelist);
.columnName, .columnSize, .columnType, .columnChanged {
position: relative;
@ -129,7 +154,7 @@
bottom: .2em;
width: .1em;
background-color: #999999;
background-color: var(--text);
}
}
@ -206,7 +231,7 @@
.overlayError {
a {
font-size: 1.2em;
color: #9e9494;
color: var(--modal-transfer-error-overlay-text);
}
}
@ -219,16 +244,16 @@
cursor: pointer;
&:hover {
background-color: #2c2d2f;
background-color: var(--modal-transfer-entry-hover);
}
&.selected {
background-color: #1a1a1b;
background-color: var(--modal-transfer-entry-selected);
}
/* drag hovered overrides selected */
&.hovered {
background-color: #2c2d2f;
background-color: var(--modal-transfer-entry-hover);
}
$indicator_transform_time: .5s;
@ -266,7 +291,7 @@
height: 100%;
width: 10px;
background-image: linear-gradient(to right, #28292b, #28292b);
background-image: linear-gradient(to right, var(--modal-transfer-filelist), var(--modal-transfer-filelist));
@include transition(all $indicator_transform_time ease-in-out);
}
@include transition(all $indicator_transform_time ease-in-out);
@ -283,24 +308,24 @@
}
&:after {
background-image: linear-gradient(to right, $color, #28292b);
background-image: linear-gradient(to right, $color, var(--modal-transfer-filelist));
}
}
&.red {
@include define-indicator(#a10000, #e60000);
@include define-indicator(var(--modal-transfer-indicator-red), var(--modal-transfer-indicator-red-end));
}
&.blue {
@include define-indicator(#005fa1, #007acc);
@include define-indicator(var(--modal-transfer-indicator-blue), var(--modal-transfer-indicator-blue-end));
}
&.green {
@include define-indicator(#389738, #4ecc4e);
@include define-indicator(var(--modal-transfer-indicator-green), var(--modal-transfer-indicator-green-end));
}
&.hidden {
@include define-indicator(#28292b00, #28292b00);
@include define-indicator(var(--modal-transfer-indicator-hidden), var(--modal-transfer-indicator-hidden-end));
}
}
}
@ -345,7 +370,7 @@
-webkit-transform: rotate(-45deg);
display: inline-block;
border: solid #999999;
border: solid var(--text);
border-width: 0 0.125em 0.125em 0;
padding: 0.15em;

View File

@ -1,6 +1,16 @@
@import "../../../../css/static/mixin";
@import "../../../../css/static/properties";
html:root {
--modal-transfer-background-text: #595959;
--modal-transfer-expend: #363636;
--modal-transfer-expend-hover: #404040;
--modal-transfer-header: #cccccc;
--modal-transfer-header-line: #393939;
}
.container {
z-index: 1;
position: absolute;
@ -20,7 +30,7 @@
.overlay {
position: absolute;
background-color: #19191b;
background-color: var(--modal-content-background);
top: 0;
bottom: 0;
@ -44,7 +54,7 @@
justify-content: center;
a {
color: #595959;
color: var(--modal-transfer-background-text);
align-self: center;
font-size: 1.2em;
}
@ -58,7 +68,7 @@
.expendedContainer {
height: 100%;
margin-top: auto;
background-color: #19191b;
background-color: var(--modal-content-background);
overflow: hidden;
@ -92,7 +102,7 @@
a {
font-weight: bold;
color: #cccccc;
color: var(--modal-transfer-header);
font-size: 1.05em;
}
@ -102,7 +112,7 @@
font-size: .7em;
}
border-bottom: 1px solid #393939;
border-bottom: 1px solid var(--modal-transfer-header-line);
}
.list {
@ -140,7 +150,7 @@
a {
align-self: center;
color: #595959;
color: var(--modal-transfer-background-text);
}
}
}
@ -192,7 +202,7 @@
align-self: center;
height: 1.4em;
fill: hsla(0, 0%, 21%, 1);
fill: var(--modal-transfer-expend);
@include transform(rotate(-180deg));
@include transition($button_hover_animation_time ease-in-out);
@ -207,7 +217,7 @@
&:hover {
svg {
fill: hsla(0, 0%, 25%, 1);
fill: var(--modal-transfer-expend-hover);
}
}
}
@ -241,7 +251,7 @@
flex-direction: row;
justify-content: flex-start;
background-color: #19191b;
background-color: var(--modal-content-background);
z-index: 1;
top: 0;

View File

@ -1,16 +1,31 @@
@import "../../../css/static/mixin.scss";
@import "../../../css/static/properties.scss";
html:root {
--button-background: rgba(0, 0, 0, 0.5);
--button-hover-background: rgba(0, 0, 0, 0.7);
--button-disabled-background: rgba(0, 0, 0, 0.27);
--button-color: #7c7c7c;
--button-green: #389738;
--button-blue: #386896;
--button-red: #973838;
--button-purple: #5f3586;
--button-brown: #965238;
--button-yellow: #96903a;
}
.button {
cursor: pointer;
background-color: rgba(0, 0, 0, 0.5);
background-color: var(--button-background);
border-width: 0;
border-radius: $border_radius_middle;
border-style: solid;
color: #7c7c7c;
color: var(--button-color);
height: 2.2em;
padding: .25em 1em;
@ -25,41 +40,41 @@
&:disabled {
box-shadow: none;
background-color: rgba(0, 0, 0, 0.27);
background-color: var(--button-disabled-background);
&:hover {
background-color: rgba(0, 0, 0, 0.27);
background-color: var(--button-disabled-background);
}
}
&.color-green {
border-bottom-width: 2px;
border-bottom-color: #389738;
border-bottom-color: var(--button-green);
}
&.color-blue, &.color-default {
border-bottom-width: 2px;
border-bottom-color: #386896;
border-bottom-color: var(--button-blue);
}
&.color-red {
border-bottom-width: 2px;
border-bottom-color: #973838;
border-bottom-color: var(--button-red);
}
&.color-purple {
border-bottom-width: 2px;
border-bottom-color: #5f3586;
border-bottom-color: var(--button-purple);
}
&.color-brown {
border-bottom-width: 2px;
border-bottom-color: #965238;
border-bottom-color: var(--button-brown);
}
&.color-yellow {
border-bottom-width: 2px;
border-bottom-color: #96903a;
border-bottom-color: var(--button-yellow);
}
&.type-normal { }

View File

@ -1,6 +1,13 @@
@import "../../../css/static/mixin";
@import "../../../css/static/properties";
html:root {
--checkbox-checkmark: #46c0ec;
--checkbox-background: #272626;
--checkbox-disabled-background: #46c0ec;
}
.checkbox {
flex-shrink: 0;
flex-grow: 0;
@ -15,7 +22,7 @@
overflow: hidden;
background-color: #272626;
background-color: var(--checkbox-background);
border-radius: $border_radius_middle;
input {
@ -37,8 +44,8 @@
margin-top: .3em;
border: none;
border-bottom: .2em solid #46c0ec;
border-left: .2em solid #46c0ec;
border-bottom: .2em solid var(--checkbox-checkmark);
border-left: .2em solid var(--checkbox-checkmark);
transform: rotateY(0deg) rotate(-45deg); /* needs Y at 0 deg to behave properly*/
@include transition(.4s);
@ -70,6 +77,6 @@
label.disabled > .checkbox, .checkbox:disabled, .checkbox.disabled {
&.checkbox, > .checkbox {
pointer-events: none!important;
background-color: #1a1a1e;
background-color: var(--checkbox-disabled-background);
}
}

View File

@ -1,17 +1,34 @@
@import "../../../css/static/mixin";
@import "../../../css/static/properties";
html:root {
--input-field-border: #111112;
--input-field-background: #121213;
--input-field-text: #b3b3b3;
--input-field-placeholder: #606060;
--input-field-disabled-background: #1a1819;
--input-field-focus-border: #111112;
--input-field-focus-background: #121213;
--input-field-focus-text: #b3b3b3;
--input-field-invalid-border: #721c1c;
--input-field-invalid-background: #180d0d;
--input-field-invalid-text: #b3b3b3;
}
.container {
border-radius: .2em;
border: 1px solid #111112;
border: 1px solid var(--input-field-border);
background-color: #121213;
background-color: var(--input-field-background);
display: flex;
flex-direction: row;
justify-content: stretch;
color: #b3b3b3;
color: var(--input-field-text);
&.size-normal {
height: 2em;
@ -26,7 +43,7 @@
}
@include placeholder(&) {
color: #606060;
color: var(--input-field-placeholder);
};
.prefix {
@ -49,17 +66,18 @@
}
&.is-invalid {
background-color: #180d0d;
border-color: #721c1c;
background-color: var(--input-field-invalid-background);
border-color: var(--input-field-invalid-border);
color: var(--input-field-invalid-text);
background-image: unset!important;
}
&:focus, &:focus-within {
background-color: #131b22;
border-color: #284262;
background-color: var(--input-field-focus-background);
border-color: var(--input-field-focus-border);
color: #e1e2e3;
color: var(--input-field-focus-text);
.prefix {
width: 0;
@ -79,8 +97,7 @@
outline: none;
margin: 0;
color: #b3b3b3;
//color: #b3b3b3;
min-width: 2em;
&.editable {
@ -106,7 +123,7 @@
}
&.disabled, &:disabled {
background-color: #1a1819;
background-color: var(--input-field-disabled-background);
}
&.noRightIcon {

View File

@ -1,8 +1,12 @@
@import "../../../css/static/mixin";
@import "../../../css/static/properties";
html:root {
--modal-content-background: #19191b;
}
.modal {
color: #999999; /* base color */
color: var(--text); /* base color */
overflow: auto; /* allow scrolling if a modal is too big */
@ -45,7 +49,7 @@
max-height: calc(100% - 3.5em);
.content {
background: #19191b;
background: var(--modal-content-background);
border: 1px solid black;
border-radius: $border_radius_middle;
@ -145,11 +149,11 @@
/* special modal types */
.modal {
&.header-error .header {
background-color: hsla(0, 100%, 25%, 1);
background-color: #800000;
}
&.header-info .header {
background-color: hsla(199, 98%, 20%, 1);
background-color: #014565;
}
&.header-warning .header,

View File

@ -1,6 +1,14 @@
@import "../../../css/static/mixin";
@import "../../../css/static/properties";
html:root {
--progress-bar-background: #242527;
--progress-bar-filler-normal: #4370a299;
--progress-bar-filler-error: #a1000099;
--progress-bar-filler-success: #2b854199;
}
.container {
position: relative;
@ -13,7 +21,7 @@
overflow: hidden;
background-color: #242527;
background-color: var(--progress-bar-background);
-webkit-box-shadow: inset 0 0 2px 0 rgba(0, 0, 0, 0.75);
-moz-box-shadow: inset 0 0 2px 0 rgba(0, 0, 0, 0.75);
box-shadow: inset 0 0 2px 0 rgba(0, 0, 0, 0.75);
@ -35,19 +43,19 @@
&.type-normal {
.filler {
background-color: #4370a299;
background-color: var(--progress-bar-filler-normal);
}
}
&.type-error {
.filler {
background-color: #a1000099;
background-color: var(--progress-bar-filler-error);
}
}
&.type-success {
.filler {
background-color: #2b854199;
background-color: var(--progress-bar-filler-success);
}
}
}

View File

@ -10,6 +10,14 @@ $thumb_height: 2em;
$tooltip_width: 4em;
$tooltip_height: 1.8em;
html:root {
--slider-filler-color: #4370a2;
--slider-disabled-filler-color: #3d618a;
--slider-thumb-color: #808080;
--slider-disabled-thumb-color: #4d4d4d;
}
.container {
font-size: .8em;
@ -36,7 +44,7 @@ $tooltip_height: 1.8em;
top: 0;
bottom: 0;
background-color: #4370a2;
background-color: var(--slider-filler-color);
border-radius: $border_radius_large;
@include transition(background-color .15s ease-in-out);
@ -57,7 +65,7 @@ $tooltip_height: 1.8em;
margin-top: -($thumb_height - $track_height) / 2;
margin-bottom: -($thumb_height - $track_height) / 2;
background-color: #808080;
background-color: var(--slider-thumb-color);
@include transition(background-color .15s ease-in-out);
}
@ -65,11 +73,11 @@ $tooltip_height: 1.8em;
pointer-events: none;
.thumb {
background-color: #4d4d4d!important;
background-color: var(--slider-disabled-thumb-color)!important;
}
.filler {
background-color: #3d618a;
background-color: var(--slider-disabled-filler-color);
}
}
}

View File

@ -1,8 +1,11 @@
@import "../../../css/static/mixin";
html:root {
--tooltip-background-color: #232222;
}
.container {
color: #999999;
background-color: #232222;
background-color: var(--tooltip-background-color);
position: fixed;
z-index: 1000000;
@ -34,7 +37,7 @@
border-style: solid;
border-width: .5em .5em 0 .5em;
border-color: #232222 transparent transparent transparent;
border-color: var(--tooltip-background-color) transparent transparent transparent;
}
&.shown {

View File

@ -1,5 +1,11 @@
@import "../../../css/static/mixin";
html:root {
--channel-tree-name-edit-color: black;
--channel-tree-name-edit-background: white;
--channel-tree-name-edit-border: white;
}
.clientEntry {
cursor: pointer;
@ -34,8 +40,9 @@
width: 100%;
font-weight: normal;
color: black;
background-color: white;
color: var(--channel-tree-name-edit-color);
background-color: var(--channel-tree-name-edit-background);
border: 1px solid var(--channel-tree-name-edit-border);
overflow-y: hidden;
overflow-x: hidden;
@ -87,7 +94,7 @@
.clientName {
&:focus {
position: absolute;
color: black;
color: var(--channel-tree-name-edit-color);
padding-top: 1px;
padding-bottom: 1px;

View File

@ -133,7 +133,7 @@ class ClientServerGroupIcons extends ReactComponentBase<ClientServerGroupIconsPr
this.unsubscribeGroupEvents();
const groups = this.props.client.assignedServerGroupIds()
.map(e => this.props.client.channelTree.client.groups.serverGroup(e)).filter(e => !!e);
.map(e => this.props.client.channelTree.client.groups.findServerGroup(e)).filter(e => !!e);
if(groups.length === 0) return null;
groups.forEach(e => {
@ -189,7 +189,7 @@ class ClientChannelGroupIcon extends ReactComponentBase<ClientChannelGroupIconPr
const cgid = this.props.client.assignedChannelGroup();
if(cgid === 0) return null;
const channel_group = this.props.client.channelTree.client.groups.channelGroup(cgid);
const channel_group = this.props.client.channelTree.client.groups.findChannelGroup(cgid);
if(!channel_group) return null;
channel_group.events.on("notify_properties_updated", this.group_updated_callback);
@ -278,7 +278,7 @@ class ClientName extends ReactComponentBase<ClientNameProperties, ClientNameStat
let prefix_groups: string[] = [];
let suffix_groups: string[] = [];
for(const group_id of this.props.client.assignedServerGroupIds()) {
const group = this.props.client.channelTree.client.groups.serverGroup(group_id);
const group = this.props.client.channelTree.client.groups.findServerGroup(group_id);
if(!group) continue;
if(group.properties.namemode == 1)
@ -287,7 +287,7 @@ class ClientName extends ReactComponentBase<ClientNameProperties, ClientNameStat
suffix_groups.push(group.name);
}
const channel_group = this.props.client.channelTree.client.groups.channelGroup(this.props.client.assignedChannelGroup());
const channel_group = this.props.client.channelTree.client.groups.findChannelGroup(this.props.client.assignedChannelGroup());
if(channel_group) {
if(channel_group.properties.namemode == 1)
prefix_groups.push(channel_group.name);

View File

@ -122,7 +122,7 @@ export class RecorderProfile {
volume: 100,
vad_threshold: {
threshold: 50
threshold: 25
},
vad_type: "threshold",
vad_push_to_talk: {

View File

@ -1,617 +0,0 @@
/// <reference path="loader.ts" />
interface Window {
$: JQuery;
}
namespace app {
export enum Type {
UNKNOWN,
CLIENT_RELEASE,
CLIENT_DEBUG,
WEB_DEBUG,
WEB_RELEASE
}
export let type: Type = Type.UNKNOWN;
export function is_web() {
return type == Type.WEB_RELEASE || type == Type.WEB_DEBUG;
}
let _ui_version;
export function ui_version() {
if(typeof(_ui_version) !== "string") {
const version_node = document.getElementById("app_version");
if(!version_node) return undefined;
const version = version_node.hasAttribute("value") ? version_node.getAttribute("value") : undefined;
if(!version) return undefined;
return (_ui_version = version);
}
return _ui_version;
}
}
/* all javascript loaders */
const loader_javascript = {
detect_type: async () => {
if(window.require) {
const request = new Request("js/proto.js");
let file_path = request.url;
if(!file_path.startsWith("file://"))
throw "Invalid file path (" + file_path + ")";
file_path = file_path.substring(process.platform === "win32" ? 8 : 7);
const fs = require('fs');
if(fs.existsSync(file_path)) {
app.type = app.Type.CLIENT_DEBUG;
} else {
app.type = app.Type.CLIENT_RELEASE;
}
} else {
/* test if js/proto.js is available. If so we're in debug mode */
const request = new XMLHttpRequest();
request.open('GET', "js/proto.js?_ts=" + Date.now(), true);
await new Promise((resolve, reject) => {
request.onreadystatechange = () => {
if (request.readyState === 4){
if (request.status === 404) {
app.type = app.Type.WEB_RELEASE;
} else {
app.type = app.Type.WEB_DEBUG;
}
resolve();
}
};
request.onerror = () => {
reject("Failed to detect app type");
};
request.send();
});
}
},
load_scripts: async () => {
if(!window.require) {
await loader.load_script(["vendor/jquery/jquery.min.js"]);
} else {
/*
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
name: "forum sync",
priority: 10,
function: async () => {
forum.sync_main();
}
});
*/
}
await loader.load_script(["vendor/DOMPurify/purify.min.js"]);
await loader.load_script("vendor/jsrender/jsrender.min.js");
await loader.load_scripts([
["vendor/xbbcode/src/parser.js"],
["vendor/moment/moment.js"],
["vendor/twemoji/twemoji.min.js", ""], /* empty string means not required */
["vendor/highlight/highlight.pack.js", ""], /* empty string means not required */
["vendor/remarkable/remarkable.min.js", ""], /* empty string means not required */
["adapter/adapter-latest.js", "https://webrtc.github.io/adapter/adapter-latest.js"]
]);
await loader.load_scripts([
["vendor/emoji-picker/src/jquery.lsxemojipicker.js"]
]);
if(app.type == app.Type.WEB_RELEASE || app.type == app.Type.CLIENT_RELEASE) {
loader.register_task(loader.Stage.JAVASCRIPT, {
name: "scripts release",
priority: 20,
function: loader_javascript.load_release
});
} else {
loader.register_task(loader.Stage.JAVASCRIPT, {
name: "scripts debug",
priority: 20,
function: loader_javascript.load_scripts_debug
});
}
},
load_scripts_debug: async () => {
/* test if we're loading as TeaClient or WebClient */
if(!window.require) {
loader.register_task(loader.Stage.JAVASCRIPT, {
name: "javascript web",
priority: 10,
function: loader_javascript.load_scripts_debug_web
});
} else {
loader.register_task(loader.Stage.JAVASCRIPT, {
name: "javascript client",
priority: 10,
function: loader_javascript.load_scripts_debug_client
});
}
await loader.load_scripts([
["https://unpkg.com/simplebar@latest/dist/simplebar.min.js"]
]);
/* load some extends classes */
await loader.load_scripts([
["js/connection/ConnectionBase.js"]
]);
/* load the main app */
await loader.load_scripts([
//Load general API's
"js/proto.js",
"js/i18n/localize.js",
"js/i18n/country.js",
"js/log.js",
"js/sound/Sounds.js",
"js/utils/helpers.js",
"js/crypto/sha.js",
"js/crypto/hex.js",
"js/crypto/asn1.js",
"js/crypto/crc32.js",
//load the profiles
"js/profiles/ConnectionProfile.js",
"js/profiles/Identity.js",
"js/profiles/identities/teaspeak-forum.js",
//Basic UI elements
"js/ui/elements/context_divider.js",
"js/ui/elements/context_menu.js",
"js/ui/elements/modal.js",
"js/ui/elements/tab.js",
"js/ui/elements/slider.js",
"js/ui/elements/tooltip.js",
"js/ui/elements/net_graph.js",
//Load permissions
"js/permission/PermissionManager.js",
"js/permission/GroupManager.js",
//Load UI
"js/ui/modal/ModalAbout.js",
"js/ui/modal/ModalAvatar.js",
"js/ui/modal/ModalAvatarList.js",
"js/ui/modal/ModalClientInfo.js",
"js/ui/modal/ModalChannelInfo.js",
"js/ui/modal/ModalServerInfo.js",
"js/ui/modal/ModalServerInfoBandwidth.js",
"js/ui/modal/ModalQuery.js",
"js/ui/modal/ModalQueryManage.js",
"js/ui/modal/ModalPlaylistList.js",
"js/ui/modal/ModalPlaylistEdit.js",
"js/ui/modal/ModalBookmarks.js",
"js/ui/modal/ModalConnect.js",
"js/ui/modal/ModalSettings.js",
"js/ui/modal/ModalCreateChannel.js",
"js/ui/modal/ModalServerEdit.js",
"js/ui/modal/ModalChangeVolume.js",
"js/ui/modal/ModalChangeLatency.js",
"js/ui/modal/ModalBanClient.js",
"js/ui/modal/ModalIconSelect.js",
"js/ui/modal/ModalInvite.js",
"js/ui/modal/ModalIdentity.js",
"js/ui/modal/ModalBanList.js",
"js/ui/modal/ModalYesNo.js",
"js/ui/modal/ModalPoke.js",
"js/ui/modal/ModalKeySelect.js",
"js/ui/modal/ModalGroupAssignment.js",
"js/ui/modal/permission/ModalPermissionEdit.js",
{url: "js/ui/modal/permission/SenselessPermissions.js", depends: ["js/permission/PermissionManager.js"]},
{url: "js/ui/modal/permission/CanvasPermissionEditor.js", depends: ["js/ui/modal/permission/ModalPermissionEdit.js"]},
{url: "js/ui/modal/permission/HTMLPermissionEditor.js", depends: ["js/ui/modal/permission/ModalPermissionEdit.js"]},
"js/ui/channel.js",
"js/ui/client.js",
"js/ui/server.js",
"js/ui/view.js",
"js/ui/client_move.js",
"js/ui/htmltags.js",
"js/ui/frames/ControlBar.js",
"js/ui/frames/chat.js",
"js/ui/frames/chat_frame.js",
"js/ui/frames/connection_handlers.js",
"js/ui/frames/server_log.js",
"js/ui/frames/hostbanner.js",
"js/ui/frames/MenuBar.js",
//Load audio
"js/voice/RecorderBase.js",
"js/voice/RecorderProfile.js",
//Load general stuff
"js/settings.js",
"js/bookmarks.js",
"js/FileManager.js",
"js/ConnectionHandler.js",
"js/BrowserIPC.js",
"js/dns.js",
//Connection
"js/connection/CommandHandler.js",
"js/connection/CommandHelper.js",
"js/connection/HandshakeHandler.js",
"js/connection/ServerConnectionDeclaration.js",
"js/stats.js",
"js/PPTListener.js",
"js/profiles/identities/NameIdentity.js", //Depends on Identity
"js/profiles/identities/TeaForumIdentity.js", //Depends on Identity
"js/profiles/identities/TeamSpeakIdentity.js", //Depends on Identity
]);
await loader.load_script("js/main.js");
},
load_scripts_debug_web: async () => {
await loader.load_scripts([
["js/audio/AudioPlayer.js"],
["js/audio/WebCodec.js"],
["js/WebPPTListener.js"],
"js/voice/AudioResampler.js",
"js/voice/JavascriptRecorder.js",
"js/voice/VoiceHandler.js",
"js/voice/VoiceClient.js",
//Connection
"js/connection/ServerConnection.js",
//Load codec
"js/codec/Codec.js",
"js/codec/BasicCodec.js",
{url: "js/codec/CodecWrapperWorker.js", depends: ["js/codec/BasicCodec.js"]},
]);
},
load_scripts_debug_client: async () => {
await loader.load_scripts([
]);
},
load_release: async () => {
console.log("Load for release!");
await loader.load_scripts([
//Load general API's
["js/client.min.js", "js/client.js"]
]);
}
};
const loader_webassembly = {
test_webassembly: async () => {
/* We dont required WebAssembly anymore for fundamental functions, only for auto decoding
if(typeof (WebAssembly) === "undefined" || typeof (WebAssembly.compile) === "undefined") {
console.log(navigator.browserSpecs);
if (navigator.browserSpecs.name == 'Safari') {
if (parseInt(navigator.browserSpecs.version) < 11) {
displayCriticalError("You require Safari 11 or higher to use the web client!<br>Safari " + navigator.browserSpecs.version + " does not support WebAssambly!");
return;
}
}
else {
// Do something for all other browsers.
}
displayCriticalError("You require WebAssembly for TeaSpeak-Web!");
throw "Missing web assembly";
}
*/
}
};
const loader_style = {
load_style: async () => {
await loader.load_styles([
"vendor/xbbcode/src/xbbcode.css"
]);
await loader.load_styles([
"vendor/emoji-picker/src/jquery.lsxemojipicker.css"
]);
await loader.load_styles([
["vendor/highlight/styles/darcula.css", ""], /* empty string means not required */
]);
if(app.type == app.Type.WEB_DEBUG || app.type == app.Type.CLIENT_DEBUG) {
await loader_style.load_style_debug();
} else {
await loader_style.load_style_release();
}
},
load_style_debug: async () => {
await loader.load_styles([
"https://unpkg.com/simplebar@latest/dist/simplebar.css"
]);
await loader.load_styles([
"css/static/main.css",
"css/static/main-layout.css",
"css/static/helptag.css",
"css/static/scroll.css",
"css/static/channel-tree.css",
"css/static/ts/tab.css",
"css/static/ts/icons.css",
"css/static/ts/icons_em.css",
"css/static/ts/country.css",
"css/static/general.css",
"css/static/modal.css",
"css/static/modals.css",
"css/static/modal-about.css",
"css/static/modal-avatar.css",
"css/static/modal-icons.css",
"css/static/modal-bookmarks.css",
"css/static/modal-connect.css",
"css/static/modal-channel.css",
"css/static/modal-query.css",
"css/static/modal-volume.css",
"css/static/modal-latency.css",
"css/static/modal-invite.css",
"css/static/modal-playlist.css",
"css/static/modal-banlist.css",
"css/static/modal-banclient.css",
"css/static/modal-channelinfo.css",
"css/static/modal-clientinfo.css",
"css/static/modal-serverinfo.css",
"css/static/modal-serverinfobandwidth.css",
"css/static/modal-identity.css",
"css/static/modal-settings.css",
"css/static/modal-poke.css",
"css/static/modal-server.css",
"css/static/modal-keyselect.css",
"css/static/modal-permissions.css",
"css/static/modal-group-assignment.css",
"css/static/music/info_plate.css",
"css/static/frame/SelectInfo.css",
"css/static/control_bar.css",
"css/static/context_menu.css",
"css/static/frame-chat.css",
"css/static/connection_handlers.css",
"css/static/server-log.css",
"css/static/htmltags.css",
"css/static/hostbanner.css",
"css/static/menu-bar.css"
]);
},
load_style_release: async () => {
await loader.load_styles([
"css/static/base.css",
"css/static/main.css",
]);
}
};
async function load_templates() {
try {
const response = await $.ajax("templates.html" + loader.get_cache_version());
let node = document.createElement("html");
node.innerHTML = response;
let tags: HTMLCollection;
if(node.getElementsByTagName("body").length > 0)
tags = node.getElementsByTagName("body")[0].children;
else
tags = node.children;
let root = document.getElementById("templates");
if(!root) {
loader.critical_error("Failed to find template tag!");
return;
}
while(tags.length > 0){
let tag = tags.item(0);
root.appendChild(tag);
}
} catch(error) {
loader.critical_error("Failed to find template tag!");
throw "template error";
}
}
/* register tasks */
loader.register_task(loader.Stage.INITIALIZING, {
name: "safari fix",
function: async () => {
/* safari remove "fix" */
if(Element.prototype.remove === undefined)
Object.defineProperty(Element.prototype, "remove", {
enumerable: false,
configurable: false,
writable: false,
value: function(){
this.parentElement.removeChild(this);
}
});
},
priority: 50
});
loader.register_task(loader.Stage.INITIALIZING, {
name: "Browser detection",
function: async () => {
navigator.browserSpecs = (function(){
let ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if(/trident/i.test(M[1])){
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return {name:'IE',version:(tem[1] || '')};
}
if(M[1]=== 'Chrome'){
tem = ua.match(/\b(OPR|Edge)\/(\d+)/);
if(tem != null) return {name:tem[1].replace('OPR', 'Opera'),version:tem[2]};
}
M = M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
if((tem = ua.match(/version\/(\d+)/i))!= null)
M.splice(1, 1, tem[1]);
return {name:M[0], version:M[1]};
})();
console.log("Resolved browser manufacturer to \"%s\" version \"%s\"", navigator.browserSpecs.name, navigator.browserSpecs.version);
},
priority: 30
});
loader.register_task(loader.Stage.INITIALIZING, {
name: "secure tester",
function: async () => {
/* we need https or localhost to use some things like the storage API */
if(typeof isSecureContext === "undefined")
(<any>window)["isSecureContext"] = location.protocol !== 'https:' && location.hostname !== 'localhost';
if(!isSecureContext) {
loader.critical_error("TeaWeb cant run on unsecured sides.", "App requires to be loaded via HTTPS!");
throw "App requires a secure context!"
}
},
priority: 20
});
loader.register_task(loader.Stage.INITIALIZING, {
name: "webassembly tester",
function: loader_webassembly.test_webassembly,
priority: 20
});
loader.register_task(loader.Stage.INITIALIZING, {
name: "app type test",
function: loader_javascript.detect_type,
priority: 20
});
loader.register_task(loader.Stage.JAVASCRIPT, {
name: "javascript",
function: loader_javascript.load_scripts,
priority: 10
});
loader.register_task(loader.Stage.STYLE, {
name: "style",
function: loader_style.load_style,
priority: 10
});
loader.register_task(loader.Stage.TEMPLATES, {
name: "templates",
function: load_templates,
priority: 10
});
loader.register_task(loader.Stage.LOADED, {
name: "loaded handler",
function: async () => {
fadeoutLoader();
},
priority: 5
});
loader.register_task(loader.Stage.LOADED, {
name: "error task",
function: async () => {
if(Settings.instance.static(Settings.KEY_LOAD_DUMMY_ERROR, false)) {
loader.critical_error("The tea is cold!", "Argh, this is evil! Cold tea dosn't taste good.");
throw "The tea is cold!";
}
},
priority: 20
});
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
name: "lsx emoji picker setup",
function: async () => await (window as any).setup_lsx_emoji_picker({twemoji: typeof(window.twemoji) !== "undefined"}),
priority: 10
});
loader.register_task(loader.Stage.SETUP, {
name: "page setup",
function: async () => {
const body = document.body;
/* top menu */
{
const container = document.createElement("div");
container.setAttribute('id', "top-menu-bar");
body.append(container);
}
/* template containers */
{
const container = document.createElement("div");
container.setAttribute('id', "templates");
body.append(container);
}
/* sounds container */
{
const container = document.createElement("div");
container.setAttribute('id', "sounds");
body.append(container);
}
/* mouse move container */
{
const container = document.createElement("div");
container.setAttribute('id', "mouse-move");
const inner_container = document.createElement("div");
inner_container.classList.add("container");
container.append(inner_container);
body.append(container);
}
/* tooltip container */
{
const container = document.createElement("div");
container.setAttribute('id', "global-tooltip");
container.append(document.createElement("a"));
body.append(container);
}
},
priority: 10
});
/* test if we're getting loaded within a TeaClient preview window */
loader.register_task(loader.Stage.SETUP, {
name: "TeaClient tester",
function: async () => {
//@ts-ignore
if(typeof __teaclient_preview_notice !== "undefined" && typeof __teaclient_preview_error !== "undefined") {
loader.critical_error("Why you're opening TeaWeb within the TeaSpeak client?!");
throw "we're already a TeaClient!";
}
},
priority: 100
});
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
name: "log enabled initialisation",
function: async () => log.initialize(app.type === app.Type.CLIENT_DEBUG || app.type === app.Type.WEB_DEBUG ? log.LogType.TRACE : log.LogType.INFO),
priority: 150
});
window["Module"] = (window["Module"] || {}) as any;
/* TeaClient */
if(window.require) {
const path = require("path");
const remote = require('electron').remote;
module.paths.push(path.join(remote.app.getAppPath(), "/modules"));
module.paths.push(path.join(path.dirname(remote.getGlobal("browser-root")), "js"));
const connector = require("renderer");
console.log(connector);
loader.register_task(loader.Stage.INITIALIZING, {
name: "teaclient initialize",
function: connector.initialize,
priority: 40
});
}
if(!loader.running()) {
/* we know that we want to load the app */
loader.execute_managed();
}