Fundamental style update

This commit is contained in:
WolverinDEV 2019-02-09 17:43:34 +01:00
parent 482b67f3c1
commit 9cd8f23987
53 changed files with 4554 additions and 23587 deletions

View file

@ -1,7 +1,7 @@
.context-menu { .context-menu {
overflow: visible; overflow: visible;
display: none; display: none;
z-index: 1000; z-index: 2000;
position: absolute; position: absolute;
border: 1px solid #CCC; border: 1px solid #CCC;
white-space: nowrap; white-space: nowrap;
@ -18,6 +18,11 @@
vertical-align: middle; vertical-align: middle;
} }
hr {
margin-top: 8px;
margin-bottom: 8px;
}
.entry { .entry {
/*padding: 8px 12px;*/ /*padding: 8px 12px;*/
padding-right: 12px; padding-right: 12px;

View file

@ -132,6 +132,12 @@ $background:lightgray;
display: block; display: block;
} }
} }
hr {
margin-top: 5px;
margin-bottom: 5px;
}
} }
.bookmark-dropdown { .bookmark-dropdown {

View file

@ -50,7 +50,7 @@
} }
/* The Modal (background) */ /* The Modal (background) */
.modal { .modal_disabled {
display: none; /* Hidden by default */ display: none; /* Hidden by default */
position: fixed; /* Stay in place */ position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */ z-index: 1; /* Sit on top */
@ -61,74 +61,74 @@
overflow: auto; /* Enable scroll if needed */ overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */ background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Header */ /* Modal Header */
.modal-header { .modal-header {
padding: 2px 16px; padding: 2px 16px;
min-height: 30px; min-height: 30px;
vertical-align: middle; vertical-align: middle;
display: flex; display: flex;
align-items: center; align-items: center;
border: grey solid; border: grey solid;
border-width: 0 0 1px 0; border-width: 0 0 1px 0;
background-color: lightgreen; background-color: lightgreen;
} }
/* Modal Body */ /* Modal Body */
.modal-body:not(:empty) { .modal-body:not(:empty) {
display: flex; display: flex;
padding: 2px 16px; padding: 2px 16px;
flex-grow: 1; flex-grow: 1;
flex-direction: column; flex-direction: column;
justify-content: stretch; justify-content: stretch;
} }
/* Modal Footer */ /* Modal Footer */
.modal-footer:not(:empty) { .modal-footer:not(:empty) {
padding: 2px 16px; padding: 2px 16px;
} }
/* The Close Button */ /* The Close Button */
.close { .close {
color: #aaa; color: #aaa;
float: right; float: right;
font-size: 28px; font-size: 28px;
font-weight: bold; font-weight: bold;
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 4px; right: 4px;
} }
.close:hover, .close:hover,
.close:focus { .close:focus {
color: black; color: black;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
} }
/* Modal Content */ /* Modal Content */
.modal-content:not(:empty) { .modal-content:not(:empty) {
position: absolute; position: absolute;
display: inline-flex; display: inline-flex;
flex-direction: column; flex-direction: column;
justify-content: stretch; justify-content: stretch;
background-color: #fefefe; background-color: #fefefe;
margin: auto; margin: auto;
padding: 0; padding: 0;
border: 2px solid #888; border: 2px solid #888;
width: auto; width: auto;
max-width: 90%; max-width: 90%;
box-shadow: 0 4px 15px 0 rgba(0,0,0,0.2), 2px 6px 20px 0 rgba(0,0,0,0.19); box-shadow: 0 4px 15px 0 rgba(0,0,0,0.2), 2px 6px 20px 0 rgba(0,0,0,0.19);
animation-name: modalFlyIn; animation-name: modalFlyIn;
animation-duration: 0.4s; animation-duration: 0.4s;
top: 10%; top: 10%;
max-height: 80%; max-height: 80%;
left: 0; left: 0;
right: 0; right: 0;
}
} }
/* Add Animation */ /* Add Animation */
@ -191,50 +191,6 @@ fieldset {
border-width: 2px; border-width: 2px;
border-radius: 0px 6px 6px 6px; border-radius: 0px 6px 6px 6px;
} }
.vad_vad_bar {
position: relative;
width: 100%;
height: 20px;
}
.vad_vad_bar .vad_vad_bar_filler {
background-color: green;
width: 50%;
height: 100%;
}
/* The slider itself */
.vad_vad_slider {
margin: 0px;
background-color: gray;
-webkit-appearance: none; /* Override default CSS styles */
appearance: none;
width: 100%;
height: 100%;
outline: none;
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
transition: opacity .2s;
}
/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
.vad_vad_slider::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 2px; /* Set a specific slider handle width */
height: 20px; /* Slider handle height */
background: #000000; /* Green background */
cursor: pointer; /* Cursor on hover */
}
.vad_vad_slider::-moz-range-thumb {
width: 2px; /* Set a specific slider handle width */
height: 100%; /* Slider handle height */
background: #000000; /* Green background */
cursor: pointer; /* Cursor on hover */
}
code { code {
background-color: lightgray; background-color: lightgray;
padding: 2px; padding: 2px;
@ -378,6 +334,11 @@ html, body {
overflow: hidden; overflow: hidden;
} }
body {
padding: 8px;
background: darkgray!important;
}
.icon-playlist-manage { .icon-playlist-manage {
display: inline-block; display: inline-block;
width: 32px; width: 32px;
@ -393,4 +354,9 @@ x-content {
flex-shrink: 1; flex-shrink: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: auto;
}
[class*=" bmd-label"], [class^=bmd-label] {
color: rgba(0, 0, 0, .6)!important;
} }

View file

@ -6,50 +6,39 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.container { select.form-control {
display: block; height: 2rem!important;
flex-shrink: 0; }
.form-row {
margin-right: 0;
margin-left: 0;
display: flex;
flex-direction: row;
justify-content: stretch;
div:first-of-type {
flex-grow: 1;
flex-shrink: 1;
margin-right: 10px;
}
div:nth-of-type(2) {
min-width: 150px;
}
}
.form-group, .form-row {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0;
a {
display: block;
}
input, textarea {
width: 100%;
}
textarea {
resize: vertical;
max-height: 100%;
overflow-y: auto;
}
&:not(:first-of-type) {
margin-top: 5px;
}
&.container-reason { &.container-reason {
max-height: 500px; flex-grow: 1;
display: flex; flex-shrink: 1;
flex-direction: column;
}
.container-name-type { overflow-y: auto;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 2px;
* {
display: inline-block;
}
}
.container-time-input {
display: flex;
flex-direction: row;
justify-content: stretch;
} }
} }

View file

@ -38,104 +38,113 @@
} }
.entry-container { .entry-container {
display: inline-flex;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
margin-bottom: 5px; margin-bottom: 5px;
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
.table-container { .entries {
width: 100%; width: 100%;
} min-height: 300px;
.ban-entry.selected { overflow-y: scroll;
background: blue; overflow-x: hidden;
}
.ban-entry-global { display: flex;
color: red; flex-direction: column;
} }
.ban-entry { .ban-entry {
.field-properties { flex-grow: 0;
a { flex-shrink: 0;
display: block;
display: flex;
flex-direction: row;
justify-content: stretch;
&.header {
.column {
font-weight: bold;
&.column-time {
margin-right: 0!important;
}
} }
} }
.field-reason {
word-wrap: break-word; &:not(.header) {
white-space: pre-wrap; cursor: pointer;
&:hover {
background-color: #00000011;
}
&.selected {
background: blue;
&:hover {
background-color: #0000FFAA;
}
}
}
.column {
flex-grow: 1;
&.column-keys {
width: 25%;
display: flex;
flex-direction: column;
}
&.column-reason {
width: 25%;
}
&.column-creator {
width: 25%;
}
&.column-time {
width: 25%;
min-width: 230px;
max-width: 300px;
display: flex;
flex-direction: column;
margin-right: -15px; /* because of the scroll bar */
> div {
display: flex;
flex-direction: row;
}
a {
display: inline;
width: 100px;
}
}
}
&.ban-entry-global {
color: red;
} }
&.ban-entry-own-bold { &.ban-entry-own-bold {
font-weight: bold; font-weight: bold;
} }
} }
table {
border: grey solid 1px;
display: block;
width: 100%;
height: 100%;
text-align: left;
min-width: 610px;
tr {
td, th {
text-align: center;
vertical-align: top;
&:nth-child(1) {
width: 25%;
text-align: left;
}
&:nth-child(2) {
width: 25%;
float: left;
}
&:nth-child(3) {
width: 25%;
float: left;
}
&:nth-child(4) {
width: 25%;
float: left;
}
}
}
th {
border: grey solid;
border-width: 0 0 1px 1px;
&:first-of-type {
border-width: 0 0 1px 0;
}
}
tbody {
height: calc(100% - 22px);
overflow-y: auto;
overflow-x: hidden;
}
th, td, thead,tbody {
display: block;
}
tr {
display: inline-block;
width: 100%;
&:nth-of-type(even) {
background-color: lightgray;
}
}
td,th {
float: left;
}
}
} }
.bottom-menu { .bottom-menu {
@ -159,6 +168,13 @@
input { input {
vertical-align: bottom; vertical-align: bottom;
} }
.bmd-form-group {
padding-top: 0;
align-self: center;
margin-left: 20px;
}
} }
} }
} }

View file

@ -105,6 +105,17 @@
flex-shrink: 0; flex-shrink: 0;
} }
} }
.container-default-channel-select {
display: flex;
flex-direction: row;
justify-content: stretch;
.container-default-channel {
flex-grow: 1;
flex-shrink: 1;
}
}
} }
} }

View file

@ -0,0 +1,171 @@
.container-channel-settings-standard {
flex-grow: 1;
display: flex;
flex-direction: row;
justify-content: stretch;
.container-divider {
border-left:1px solid #000;
height: auto;
flex-grow: 0;
flex-shrink: 0;
}
.container-left, .container-right {
display: flex;
justify-content: space-around;
align-self: center;
flex-grow: 1;
flex-shrink: 1;
width: 50%;
}
.container-right {
flex-direction: column;
align-content: stretch;
vertical-align: center;
margin: 20px 50px 20px 50px;
}
.container-channel-type {
padding: 5px;
border: lightgrey 2px solid;
border-radius: 2px;
text-align: left;
}
}
.container-channel-settings-audio {
flex-grow: 1;
display: flex;
flex-direction: row;
justify-content: stretch;
.container-divider {
border-left:1px solid #000;
height: auto;
flex-grow: 0;
flex-shrink: 0;
}
.container-presets, .container-custom {
display: flex;
justify-content: space-around;
text-align: left;
align-self: center;
flex-grow: 1;
flex-shrink: 1;
width: 50%;
}
.container-custom {
margin: 20px 50px 20px 50px;
justify-content: stretch;
> .group_box {
flex-grow: 1;
flex-shrink: 1;
}
}
}
.container-channel-settings-permission {
flex-grow: 1;
display: flex;
justify-content: space-evenly;
align-items: center;
.container-left, .container-right {
margin-top: 20px;
margin-bottom: 20px;
display: flex;
justify-content: space-around;
align-self: center;
flex-grow: 1;
flex-shrink: 1;
width: 50%;
> .group_box {
flex-grow: 1;
flex-shrink: 1;
}
.form-placeholder {
display: block;
visibility: hidden;
}
}
.container-left {
margin-left: 10%;
margin-right: 10px;
}
.container-right {
margin-right: 10%;
margin-left: 10px;
}
}
.container-channel-settings-advanced {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
.container-max-users, .container-other {
width: 100%;
}
.container-max-users {
margin-top: 20px;
display: flex;
flex-direction: row;
justify-content: stretch;
.group_box:not(:first-of-type) {
margin-left: 40px;
}
> .group_box {
flex-grow: 1;
flex-shrink: 1;
}
fieldset {
padding-top: 1rem;
}
.form-row {
margin-left: 20px;
display: flex;
flex-direction: row;
justify-content: stretch;
.bmd-form-group {
padding-top: 0;
}
label {
width: 100px;
}
}
}
}

View file

@ -1,4 +1,6 @@
.modal .modal-connect { .modal .modal-connect {
/*
margin-top: 5px; margin-top: 5px;
> div:not(:first-of-type) { > div:not(:first-of-type) {
@ -27,4 +29,45 @@
color: red; color: red;
} }
*/
.container-address-password {
display: flex;
flex-direction: row;
justify-content: stretch;
.container-address {
flex-grow: 1;
flex-shrink: 1;
}
.container-password {
flex-grow: 0;
flex-shrink: 0;
margin-left: 15px;
}
}
.container-profile-manage {
display: flex;
flex-direction: row;
justify-content: stretch;
.container-select-profile {
flex-grow: 1;
flex-shrink: 1;
}
.container-manage {
flex-grow: 0;
flex-shrink: 0;
margin-left: 15px;
}
}
.invalid-feedback {
position: absolute;
}
} }

View file

@ -0,0 +1,302 @@
permission-editor {
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 1;
}
.container-permissions {
flex-grow: 1;
flex-shrink: 1;
display: flex;
height: 100%;
}
.permission-explorer {
width: 100%;
display: flex;
flex-direction: column;
justify-content: stretch;
user-select: none;
.container-filter, .container-footer {
flex-grow: 0;
flex-shrink: 0;
display: flex;
flex-direction: row;
justify-content: stretch;
.container-input {
flex-grow: 1;
flex-shrink: 1;
margin-right: 10px;
}
}
.container-permission-list {
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
.header {
border: solid 1px lightgray;
display: flex;
flex-direction: row;
.column-granted {
width: 75px + 15px !important; /* because of the scroll bar */
}
.column-name {
padding-left: 4px;
}
}
.entries {
flex-grow: 1;
overflow-y: scroll;
overflow-x: hidden;
padding-left: 3px; /* because of the arrow */
padding-right: 3px; /* because of the scroll bar */
}
.entry {
flex-grow: 0;
flex-shrink: 0;
width: 100%;
display: flex;
flex-direction: row;
justify-content: stretch;
.column-name {
flex-grow: 1;
flex-shrink: 1;
}
.column-value, .column-granted {
flex-grow: 0;
flex-shrink: 0;
width: 75px;
text-align: center;
align-self: center;
display: flex;
flex-direction: row;
justify-content: space-around;
input[type=number] {
width: 68px;
}
}
.column-skip, .column-negate {
flex-grow: 0;
flex-shrink: 0;
width: 75px;
text-align: center;
align-self: center;
display: flex;
flex-direction: row;
justify-content: space-around;
}
&.value-unset {
.column-value, .column-skip, .column-negate {
.checkbox, input {
visibility: hidden;
}
}
}
&.grant-unset {
.column-granted {
.checkbox, input {
visibility: hidden;
}
}
}
.checkbox {
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 0!important;
}
.form-group {
margin-bottom: 0px;
}
&.group {
display: flex;
flex-direction: column;
.group-entries {
padding-left: 30px;
}
}
.bmd-form-group {
padding-top: 0;
}
&.permission {
height: 33px;
&:hover {
background: #00000011;
.checkbox {
.checkmark {
background-color: #bbb;
}
&:hover input ~ .checkmark {
background-color: #aaa;
}
input:checked ~ .checkmark {
background-color: #2196F3;
}
}
}
.checkbox {
height: 16px;
width: 16px;
display: block;
position: relative;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Hide the browser's default checkbox */
input {
position: absolute;
opacity: 0;
cursor: pointer;
left: 0;
top: 0;
}
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 16px;
width: 16px;
background-color: #eee;
&:after {
content: "";
position: absolute;
display: none;
left: 6px;
top: 2px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
}
&:hover input ~ .checkmark {
background-color: #ccc;
}
input:checked ~ .checkmark {
background-color: #2196F3;
}
input:checked ~ .checkmark:after {
display: block;
}
}
}
}
.arrow {
cursor: pointer;
margin-right: 5px;
}
}
.container-footer {
margin-top: 10px;
justify-content: flex-end;
}
.container-mode {
display: flex;
flex-grow: 1;
flex-shrink: 1;
&.container-mode-unset {
background-color: lightgray;
}
&.container-mode-no-permissions {
background-color: lightgray;
text-align: center;
justify-content: space-around;
display: flex;
flex-direction: column;
}
}
}
.tab-client, .tab-client-channel {
.client-select {
padding-bottom: 20px; /* for the error message */
.invalid-feedback {
position: absolute;
}
}
}
.tab-client-channel {
.container-client-channel {
display: flex;
flex-direction: column;
justify-content: stretch;
.list-channel {
flex-grow: 1;
flex-shrink: 1;
width: 100%;
}
}
}

View file

@ -4,36 +4,244 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.container { .header, .footer {
flex-grow: 0;
flex-shrink: 0;
}
.header {
display: flex; 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; flex-direction: column;
justify-content: stretch; justify-content: stretch;
.header, .footer { $width_id: 80px;
flex-grow: 0; $width_type: 150px;
flex-shrink: 0; $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;
}
} }
.header { .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; display: flex;
flex-direction: row; flex-direction: row;
justify-content: stretch; justify-content: stretch;
.buttons { .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;
.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; flex-grow: 0;
} }
.search { .value {
margin-left: 5px;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1;
}
.checkbox-container {
input { input {
width: 100%; margin-left: 0;
}
}
&.property-description {
textarea {
resize: vertical;
max-height: 400px;
} }
} }
} }
.playlist-list { 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;
}
.tab-content, x-content {
overflow-y: hidden;
display: flex;
flex-direction: column;
}
.container-songs {
display: flex;
flex-direction: column;
padding: 5px;
.song-list {
min-height: 300px;
margin-top: 5px; margin-top: 5px;
display: flex; display: flex;
@ -41,49 +249,51 @@
flex-direction: column; flex-direction: column;
justify-content: stretch; justify-content: stretch;
$width_id: 80px;
$width_type: 150px;
$width_used: 40px;
.column { .column {
&.column-id { &.column-id {
width: 80px; width: 50px;
text-align: center;
} }
&.column-title { &.column-url {
width: calc(50% - 95px - 40px); width: calc(100% - 140px)
} }
&.column-creator { &.column-loaded {
width: calc(50% - 95px - 40px); width: 50px;
text-align: center;
}
&.column-type {
width: 150px;
flex-grow: 0; flex-grow: 0;
text-align: center;
}
&.column-used {
width: 40px;
flex-grow: 0;
text-align: center;
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
align-self: 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: #00000033;
}
}
} }
} }
.playlist-list-header { .song-list-header {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 20px; justify-content: center;
.column { .column {
border: 1px solid lightgray; border: 1px solid lightgray;
@ -91,7 +301,7 @@
} }
} }
.playlist-list-entries-container { .song-list-entries-container {
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -113,269 +323,37 @@
background-color: blue; background-color: blue;
} }
&.highlighted { &.playing {
font-weight: bold; background-color: lightgreen;
} }
} }
&.scrollbar { &.scrollbar {
.column-title { &.column-url {
width: calc(50% - 95px - 40px + 30px) width: calc(100% - 140px + 30px)
}
.column-creator {
width: calc(50% - 95px - 40px + 30px)
} }
} }
} }
} }
.footer { .footer {
margin-top: 5px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center;
.buttons { flex-grow: 0;
display: flex; flex-shrink: 0;
flex-direction: row; margin-top: 5px;
justify-content: stretch;
.highlight-own {
display: flex;
flex-direction: row;
justify-content: stretch;
margin-right: 10px;
align-self: center;
}
}
} }
} }
}
.playlist-edit { > .buttons {
display: flex; margin-top: 5px;
flex-direction: column; align-self: flex-end;
justify-content: stretch;
.container { button {
display: flex; width: 100px;
flex-direction: column;
/* justify-content: stretch; */
.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;
.permissions-list {
display: flex;
flex-direction: column;
.permission {
display: flex;
flex-direction: row;
margin-bottom: 5px;
.key {
width: 150px;
flex-grow: 0;
}
.value {
flex-grow: 1;
flex-shrink: 1;
}
}
}
}
.container-no-permissions {
background: lightgray;
padding: 50px;
text-align: center;
}
.tab-content, x-content {
overflow-y: hidden;
display: flex;
flex-direction: column;
}
.container-songs {
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: #00000033;
}
}
}
}
.song-list-header {
flex-grow: 0;
flex-shrink: 0;
display: flex;
flex-direction: row;
justify-content: center;
height: 20px;
.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;
}
} }
} }
} }

View file

@ -26,35 +26,28 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.property-row { .buttons {
width: 100%; text-align: right;
}
.form-row {
margin-right: 0!important;
margin-left: 0!important;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: stretch; justify-content: stretch;
align-items: center;
margin-top: 2px; .icon_x32 {
align-self: center;
margin-right: 5px;
input {
flex-grow: 1;
flex-shrink: 1;
margin-left: 5px;
}
a:first-of-type {
width: 150px;
}
div:last-of-type {
margin-left: 5px;
cursor: pointer; cursor: pointer;
} }
}
.buttons { .form-group {
margin-top: 5px; flex-grow: 1;
text-align: right; }
} }
} }
@ -63,111 +56,104 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.container { .header, .footer {
flex-grow: 0;
flex-shrink: 0;
}
.header {
display: flex; display: flex;
flex-direction: row;
justify-content: stretch;
.buttons {
flex-grow: 0;
}
.search {
margin-left: 5px;
flex-grow: 1;
input {
width: 100%;
}
}
}
.query-list {
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column; flex-direction: column;
justify-content: stretch; justify-content: stretch;
.header, .footer { .column {
&.column-username {
width: calc(50% - 75px)
}
&.column-unique-id {
width: calc(50% - 75px)
}
&.column-bound-server {
width: 150px;
flex-grow: 0;
}
}
.query-list-header {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
}
.header {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: stretch;
.buttons {
flex-grow: 0;
}
.search {
margin-left: 5px;
flex-grow: 1;
input {
width: 100%;
}
}
}
.query-list {
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
.column { .column {
&.column-username { border: 1px solid lightgray;
width: calc(50% - 75px) text-align: center;
}
&.column-unique-id {
width: calc(50% - 75px)
}
&.column-bound-server {
width: 150px;
flex-grow: 0;
}
} }
}
.query-list-header { .query-list-entries-container {
flex-grow: 0; flex-grow: 1;
flex-shrink: 0; display: flex;
flex-direction: column;
justify-content: start;
overflow-y: auto;
min-height: 250px;
.entry {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 20px;
.column { .column {
border: 1px solid lightgray; margin-left: 2px;
text-align: center; }
cursor: pointer;
&.selected {
background-color: blue;
} }
} }
.query-list-entries-container { &.scrollbar {
flex-grow: 1; .column-username {
display: flex; width: calc(50% - 75px + 30px)
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;
}
} }
&.scrollbar { .column-unique-id {
.column-username { width: calc(50% - 75px + 30px)
width: calc(50% - 75px + 30px)
}
.column-unique-id {
width: calc(50% - 75px + 30px)
}
} }
} }
} }
}
.footer {
margin-top: 5px; .footer {
display: flex; margin-top: 5px;
flex-direction: row; display: flex;
justify-content: space-between; flex-direction: row;
} justify-content: space-between;
} }
} }

View file

@ -0,0 +1,76 @@
.container-server-settings-general {
.container-server-settings-slots {
display: flex;
flex-direction: row;
justify-content: stretch;
margin-right: 0;
margin-left: 0;
.form-group:not(:first-of-type) {
margin-left: 10px;
flex-grow: 30;
flex-shrink: 30;
}
.form-group:first-of-type {
flex-grow: 70;
flex-shrink: 70;
}
}
}
.container-server-settings-host {
padding: 5px;
.properties-hostbanner, .properties-hostbutton {
.form-row {
margin-left: 5px;
margin-right: 5px;
display: flex;
flex-direction: row;
justify-content: stretch;
> .form-group {
flex-grow: 1;
flex-shrink: 1;
}
> .form-group:not(:first-of-type) {
margin-left: 10px;
}
}
}
.virtualserver_hostbanner_gfx_interval {
height: calc(2.4375rem + 2px);
}
}
.container-server-settings-file-transfer, .container-server-settings-anti-flood, .container-server-settings-security {
padding: 5px;
}
.container-server-settings-misc {
padding: 5px;
.container-complains {
display: flex;
flex-direction: row;
justify-content: stretch;
> div {
flex-grow: 1;
flex-shrink: 1;
}
> div:not(:first-of-type) {
padding-left: 10px;
}
}
}
.container-server-settings-messages {
padding: 5px;
}

View file

@ -1,3 +1,6 @@
$small_device: 800px; /* tested out via audio tab */
.modal .settings_audio { .modal .settings_audio {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -7,6 +10,7 @@
user-select: none; user-select: none;
margin: 3px; margin: 3px;
> div { > div {
margin: 2px; margin: 2px;
} }
@ -15,6 +19,10 @@
align-self: center; align-self: center;
} }
.settings-device-error {
display: none;
}
.group_box { .group_box {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -24,7 +32,7 @@
flex-shrink: 1; flex-shrink: 1;
.content { .content {
display: flex; display: block;
flex-direction: column; flex-direction: column;
} }
} }
@ -32,34 +40,19 @@
.settings-device { .settings-device {
display: flex; display: flex;
flex-direction: column; flex-direction: row;
width: 100%; justify-items: stretch;
a {
flex-grow: 0;
}
.settings-device-error {
display: none;
width: 100%;
margin-bottom: 3px;
padding: 2px;
align-self: center;
text-align: center;
vertical-align: center;
border: darkred 2px solid;
border-radius: 4px;
background: #be00006b;
}
.settings-device-select { .settings-device-select {
flex-grow: 1;
flex-shrink: 1;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: stretch; justify-content: stretch;
margin-right: 5px;
> div { > div {
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
@ -75,11 +68,35 @@
.settings-vad-container { .settings-vad-container {
display: flex; display: flex;
flex-direction: row;
margin-top: 5px; margin-top: 5px;
min-height: 150px;
flex-direction: column;
width: 100%;
> div { > div {
width: 50%; width: 100%;
flex-grow: 1;
flex-shrink: 1;
}
/* for "normal" devices */
@media (min-width: $small_device) {
flex-direction: row;
> div {
width: unset;
}
}
.group_box {
min-width: 250px;
}
.content {
display: flex;
flex-direction: column;
justify-content: space-around;
} }
fieldset { fieldset {
@ -94,6 +111,12 @@
} }
.settings-vad-impl { .settings-vad-impl {
.setting-vad-ppt {
@media (min-width: $small_device) {
margin-bottom: -35px;
}
}
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
padding: 5px; padding: 5px;
@ -105,6 +128,74 @@
.settings-vad-impl-entry { .settings-vad-impl-entry {
display: none; display: none;
} }
.setting-vad-vad {
.vad_vad_bar {
position: relative;
width: 100%;
height: 20px;
background-image: linear-gradient(to right, green, yellow, red);
background-repeat: no-repeat;
background-size: 100%;
background-position: 0 100%;
display: flex;
flex-direction: column;
.bmd-form-group {
display: flex;
padding: 0px;
}
.container-hider {
position: absolute;
height: 100%;
width: 100%;
display: flex;
flex-direction: row-reverse;
.hider {
width: 50%;
height: 100%;
background-color: grey;
}
}
}
/* The slider itself */
.vad_vad_slider {
margin: 0;
background-color: gray;
-webkit-appearance: none; /* Override default CSS styles */
appearance: none;
width: 100%;
height: 100%;
outline: none;
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
transition: opacity .2s;
}
/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
.vad_vad_slider::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 2px; /* Set a specific slider handle width */
height: 20px; /* Slider handle height */
background: #000000FF; /* Green background */
cursor: pointer; /* Cursor on hover */
}
.vad_vad_slider::-moz-range-thumb {
width: 2px; /* Set a specific slider handle width */
height: 100%; /* Slider handle height */
background: #000000FF; /* Green background */
cursor: pointer; /* Cursor on hover */
}
}
} }
.property { .property {
@ -116,8 +207,19 @@
margin-right: 5px; margin-right: 5px;
} }
&.ppt-key {
.key {
align-self: center;
}
button {
min-width: 100px;
}
}
&.ppt-delay { &.ppt-delay {
margin-top: 5px; margin-top: 5px;
.value { .value {
display: inline-block; display: inline-block;
position: relative; position: relative;
@ -156,11 +258,14 @@
justify-content: stretch; justify-content: stretch;
.key { .key {
width: 150px; /*
width: 250px;
&.muted-sounds { &.muted-sounds {
width: 230px; width: 230px;
} }
*/
margin-right: 10px;
} }
.value { .value {
@ -182,6 +287,19 @@
text-align: right; text-align: right;
} }
} }
.bmd-form-group {
padding: 0;
label {
margin: 0;
top: -7px;
}
.bmd-switch-track {
top: 0;
}
}
} }
} }
@ -202,8 +320,17 @@
width: 150px; width: 150px;
flex-grow: 0; flex-grow: 0;
input { .bmd-form-group {
margin-left: 75px; padding: 0;
label {
margin: 0 0 0 75px;
top: -7px;
}
.bmd-switch-track {
top: 0;
}
} }
} }
} }
@ -213,7 +340,7 @@
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 20px; align-items: center;
.column { .column {
border: 1px solid lightgray; border: 1px solid lightgray;
@ -264,6 +391,7 @@
} }
} }
/*
.sound-list-filter { .sound-list-filter {
margin-top: 3px; margin-top: 3px;
@ -280,11 +408,13 @@
margin-right: 8px; margin-right: 8px;
} }
} }
*/
} }
} }
.modal .settings-translations { .modal .settings-translations {
margin: 5px; margin: 5px;
.setting-list { .setting-list {
user-select: none; user-select: none;
@ -311,7 +441,8 @@
flex-direction: row; flex-direction: row;
justify-content: stretch; justify-content: stretch;
.default { } .default {
}
.name { .name {
flex-grow: 1; flex-grow: 1;
@ -423,6 +554,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.contributor { .contributor {
display: block; display: block;
} }
@ -508,6 +640,7 @@
.modal .settings-profiles { .modal .settings-profiles {
margin: 5px; margin: 5px;
> div:not(:first-of-type) { > div:not(:first-of-type) {
margin-top: 5px; margin-top: 5px;
} }
@ -620,10 +753,6 @@
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
} }
.select-container {
text-align: right;
}
} }
} }
@ -643,6 +772,26 @@
} }
&.identity-settings-teamspeak { &.identity-settings-teamspeak {
.level {
padding-right: 5px;
padding-left: 5px;
display: flex;
flex-direction: row;
justify-content: stretch;
.container-input {
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: row;
justify-content: stretch;
margin-right: 10px;
}
}
.property { .property {
&:not(:first-of-type) { &:not(:first-of-type) {
margin-top: 5px; margin-top: 5px;
@ -664,18 +813,6 @@
width: 100%; width: 100%;
} }
} }
&.level {
.value {
display: flex;
flex-direction: row;
justify-content: stretch;
button {
margin-left: 5px;
}
}
}
} }
.identity-undefined { .identity-undefined {
@ -739,45 +876,15 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.property { .bmd-label-static {
&:not(:first-of-type) {
margin-top: 5px;
}
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: stretch;
.key {
display: flex;
flex-direction: row;
flex-grow: 0;
flex-shrink: 0;
width: 120px;
.help-tagged {
width: 80px;
}
}
.value {
flex-grow: 1;
flex-shrink: 2;
input {
width: 100%;
}
}
} }
.row { .form-row {
display: flex; margin-right: 0!important;
flex-direction: row; margin-left: 0!important;
justify-content: space-between; justify-content: space-between;
.property {
margin-top: 0px;
}
} }
.buttons { .buttons {
@ -787,7 +894,7 @@
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
button { button {
width: 100px; width: 100px;
} }
} }

View file

@ -1,3 +1,21 @@
body {
padding-right: 8px!important; /* remove the fucking bootstrap override */
}
/* backdrop fix */
.modal-backdrop {
visibility: hidden !important;
}
.modal {
background-color: rgba(0,0,0,0.5);
padding-right: 8% !important;
}
modal-body {
display: flex;
flex-direction: column;
}
.modal { .modal {
//General style //General style
.properties { .properties {
@ -13,42 +31,12 @@
width: 100%; width: 100%;
} }
.general_properties, .properties_general, .server_properties, .properties_messages {
width: 100%;
.group_box {
margin-top: 5px;
&:first-of-type {
margin-top: 0px;
}
}
}
.input_error { .input_error {
border-radius: 1px; border-radius: 1px;
border: solid red; border: solid red;
} }
.server_properties {
.properties {
grid-template-columns: 135px auto;
&:first-of-type {
margin-top: 5px;
}
}
.virtualserver_welcomemessage {
height: 70px;
resize: none;
}
}
.properties_messages textarea {
height: 70px;
resize: none;
}
.properties_misc { .properties_misc {
.complains { .complains {
display: grid; display: grid;
@ -62,34 +50,78 @@
.container { .container {
padding: 6px; padding: 6px;
} }
}
.modal-dialog {
max-height: 80%;
display: flex;
flex-direction: column;
justify-content: stretch;
.container-file-transfer { &.modal-dialog-centered {
.settings { justify-content: space-around;
.setting { }
}
.modal-content {
/* max-height: 500px; */
flex-direction: column;
justify-content: stretch;
.modal-header {
flex-shrink: 0;
flex-grow: 0;
&.modal-header-error {
background-color: #ce0000;
}
&.modal-header-info {
background-color: #03a9f4;
}
&.modal-header-warning, &.modal-header-info, &.modal-header-error {
border-top-left-radius: .125rem;
border-top-right-radius: .125rem;
}
}
.modal-body {
flex-grow: 1;
flex-shrink: 1;
display: flex; display: flex;
flex-direction: row; flex-direction: column;
justify-content: stretch;
&:not(:first-of-type) { input.is-invalid {
margin-top: 5px; background-image: linear-gradient(0deg, #d50000 2px, rgba(213, 0, 0, 0) 0), linear-gradient(0deg, rgba(241, 1, 1, 0.61) 1px, transparent 0);
} }
div { &.modal-body-input {
flex-grow: 0; .form-group:not(.with-title) {
padding-top: .75rem;
&.suffix {
width: 50px;
margin-left: 5px;
} }
&:first-of-type {
width: 130px; input.is-invalid ~ .container-help-feedback > .invalid-feedback {
display: block;
}
.container-help-feedback {
position: absolute;
} }
} }
}
input { .modal-footer {
flex-grow: 1; flex-shrink: 0;
flex-grow: 0;
&.modal-footer-button-group {
button {
min-width: 100px;
}
button:not(:first-of-type) {
margin-left: 15px;
};
} }
} }
} }
@ -178,197 +210,6 @@
flex-direction: column; flex-direction: column;
} }
.container-permissions {
display: flex;
height: 100%;
}
.permission-explorer {
width: 100%;
display: grid;
grid-template-rows: min-content auto min-content;
grid-gap: 5px;
.bar-filter {
display: grid;
grid-gap: 5px;
grid-template-columns: max-content auto max-content;
input[type="text"] {
width: 100%;
}
}
&.disabled {
pointer-events: none;
.overlay-disabled {
display: block;
}
input {
background-color: #00000033;
}
}
.overlay-disabled {
display: none;
position: absolute;
background-color: #00000033;
z-index: 1000;
height: 100%;
width: 100%;
}
.list {
display: flex;
position: relative;
flex-direction: column;
border: lightgray solid 2px;
user-select: none;
padding-bottom: 2px;
overflow-y: scroll;
overflow-x: hidden;
.header {
position: sticky;
top: 0;
z-index: 1;
background-color: lightgray;
padding-left: 0!important;
& > div {
border: grey solid;
border-width: 0 2px 0 0;
padding-left: 2px;
}
& > div:last-of-type {
border: none;
}
}
& > .entry {
padding-left: 4px;
}
.entry {
display: grid;
grid-template-columns: auto 100px 100px 100px 100px;
& > div {
padding-left: 2px;
}
&.selected {
background-color: #11111122;
}
&.unset {
& > .permission-value, & > .permission-skip, & > .permission-negate {
visibility: hidden;
}
& > .permission-name {
color: lightgray;
}
}
}
.group {
grid-template-columns: auto;
grid-template-rows: auto auto;
.group-entries {
margin-left: 50px;
}
.title {
&.selected {
background-color: #11111122;
}
}
}
.arrow {
cursor: pointer;
pointer-events: all;
width: 7px;
height: 7px;
padding: 0;
margin-right: 5px;
margin-left: 3px;
}
input {
border: none;
background: transparent;
vertical-align: text-bottom;
max-width: 90%;
}
.checkbox {
margin-top: 1px;
margin-left: 1px;
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Hide the browser's default checkbox */
input {
position: absolute;
opacity: 0;
cursor: pointer;
}
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 16px;
width: 16px;
background-color: #eee;
&:after {
content: "";
position: absolute;
display: none;
left: 6px;
top: 2px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
}
&:hover input ~ .checkmark {
background-color: #ccc;
}
input:checked ~ .checkmark {
background-color: #2196F3;
}
input:checked ~ .checkmark:after {
display: block;
}
}
}
}
.container-ban-type { .container-ban-type {
margin: 5px; margin: 5px;
} }
@ -499,30 +340,6 @@
} }
} }
.layout-client, .layout-client-channel {
.client-info {
display: flex;
flex-direction: column;
width: 200px;
& > div:not(.list-channel) {
display: grid;
grid-template-columns: auto;
grid-template-rows: max-content;
}
.client-info {
input {
pointer-events: none;
}
}
.list-channel {
flex-grow: 1;
}
}
}
.group-assignment-list { .group-assignment-list {
.group-list { .group-list {
border: lightgray solid 1px; border: lightgray solid 1px;

View file

@ -15,6 +15,10 @@ $ease: cubic-bezier(.45, 0, .55, 1);
perspective-origin: 50% 50%; perspective-origin: 50% 50%;
perspective: 1200px; perspective: 1200px;
label {
margin-bottom: 0!important; /* bootstrap fix */
}
.flip-card, .flip-card,
.static-card { .static-card {
background: white; background: white;

View file

@ -9,101 +9,115 @@
flex-direction: column; flex-direction: column;
flex-grow: 1; flex-grow: 1;
div, a {
vertical-align: middle;
}
.messages {
border-color: #6f6f6f;
border-radius: 2px 2px 2px 0;
border-style: solid;
overflow-y: auto;
flex-grow: 1;
.message_box {
flex-wrap: wrap;
display: flex;
align-items: flex-start;
height: auto;
.message {
width: 100%;
display: inline-block;
* {
display: inline-block;
vertical-align: top;
}
}
}
}
.chats {
max-width: 100%;
flex-shrink: 0;
flex-grow: 0;
/*height: 24px;*/
overflow: auto;
overflow-y: hidden;
white-space: nowrap;
margin-top: -1px;
display: flex;
user-select: none;
.chat {
background: #5f5f5f5f;
display: inline-block;
border: 1px solid #6f6f6f;
border-radius: 0px 0px 2px 2px;
vertical-align: middle;
padding-right: 5px;
padding-left: 2px;
cursor: pointer;
&.active {
background: #11111111;
}
.btn_close {
float: none;
margin-right: -5px;
margin-left: 8px;
&:hover, &:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
}
}
}
.input {
display: flex;
flex-direction: row;
justify-content: stretch;
height: auto;
width: 100%;
margin-top: 2px;
position: relative;
flex-shrink: 0;
.bmd-form-group {
flex-grow: 1;
flex-shrink: 1;
margin-right: 5px;
padding-top: 0;
}
.form-group {
flex-grow: 1;
flex-shrink: 1;
margin: 0 5px 0 0;
textarea {
height: 30px;
min-height: 30px;
max-height: 80px;
resize: vertical;
overflow-y: auto;
}
}
button {
padding-top: 1px;
padding-bottom: 1px;
}
}
} }
#chat div {
vertical-align: middle;
}
#chat .messages {
border-color: #6f6f6f;
border-radius: 2px 2px 2px 0px;
border-style: solid;
overflow-y: auto;
flex-grow: 1;
}
#chat .message_box {
flex-wrap: wrap;
display: flex;
align-items: flex-start;
height: auto;
}
#chat .message {
width: 100%;
display: inline-block;
}
#chat .message *{
display: inline-block;
vertical-align: top;
}
#chat .chats {
max-width: 100%;
flex-shrink: 0;
flex-grow: 0;
/*height: 24px;*/
overflow: auto;
overflow-y: hidden;
white-space: nowrap;
margin-top: -1px;
display: flex;
user-select: none;
}
#chat .chat {
background: #5f5f5f5f;
display: inline-block;
border: #6f6f6f;
border-width: 1px;
border-style: solid;
border-radius: 0px 0px 2px 2px;
vertical-align: middle;
padding-right: 5px;
padding-left: 2px;
cursor: pointer;
}
#chat .active {
background: #11111111;
}
#chat a {
vertical-align: middle;
}
#chat .btn_close {
float: none;
margin-right: -5px;
margin-left: 8px;
}
#chat .btn_close:hover,
#chat .btn_close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
#chat .input {
width: 100%;
margin-top: 2px;
display: flex;
height: auto;
position: relative;
flex-shrink: 0;
}
#chat .input .input_box {
width: 100%;
display:inline-block;
border: solid 1px #000;
height: 22px;
min-height: 22px;
max-height: 80px;
overflow-y: auto;
resize: vertical;
}

View file

@ -16,6 +16,8 @@ x-content {
} }
.tab .tab-content { .tab .tab-content {
min-height: 200px;
border-color: #6f6f6f; border-color: #6f6f6f;
border-radius: 0px 2px 2px 2px; border-radius: 0px 2px 2px 2px;
border-style: solid; border-style: solid;

View file

@ -32,6 +32,8 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<?php <?php
if(!$WEB_CLIENT) { if(!$WEB_CLIENT) {
echo "<title>TeaClient</title>"; echo "<title>TeaClient</title>";
@ -51,12 +53,15 @@
<link rel="stylesheet" href="css/modals.css" type="text/css"> <link rel="stylesheet" href="css/modals.css" type="text/css">
<link rel="stylesheet" href="css/modal-bookmarks.css" type="text/css"> <link rel="stylesheet" href="css/modal-bookmarks.css" type="text/css">
<link rel="stylesheet" href="css/modal-connect.css" type="text/css"> <link rel="stylesheet" href="css/modal-connect.css" type="text/css">
<link rel="stylesheet" href="css/modal-channel.css" type="text/css">
<link rel="stylesheet" href="css/modal-query.css" type="text/css"> <link rel="stylesheet" href="css/modal-query.css" type="text/css">
<link rel="stylesheet" href="css/modal-playlist.css" type="text/css"> <link rel="stylesheet" href="css/modal-playlist.css" type="text/css">
<link rel="stylesheet" href="css/modal-banlist.css" type="text/css"> <link rel="stylesheet" href="css/modal-banlist.css" type="text/css">
<link rel="stylesheet" href="css/modal-bancreate.css" type="text/css"> <link rel="stylesheet" href="css/modal-bancreate.css" type="text/css">
<link rel="stylesheet" href="css/modal-settings.css" type="text/css"> <link rel="stylesheet" href="css/modal-settings.css" type="text/css">
<link rel="stylesheet" href="css/modal-poke.css" type="text/css"> <link rel="stylesheet" href="css/modal-poke.css" type="text/css">
<link rel="stylesheet" href="css/modal-server.css" type="text/css">
<link rel="stylesheet" href="css/modal-permissions.css" type="text/css">
<link rel="stylesheet" href="css/loader.css" type="text/css"> <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/music/info_plate.css" type="text/css">
<link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css"> <link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css">
@ -100,6 +105,15 @@
gtag('js', new Date()); gtag('js', new Date());
gtag('config', 'UA-113151733-4'); gtag('config', 'UA-113151733-4');
</script> </script>
<!-- material design -->
<!-- <link rel="stylesheet" href="https://unpkg.com/bootstrap-material-design@4.1.1/dist/css/bootstrap-material-design.min.css" integrity="sha384-wXznGJNEXNG1NFsbm0ugrLFMQPWswR3lds2VeinahP8N0zJw9VWSopbjv2x7WCvX" crossorigin="anonymous"> -->
<link rel="stylesheet" href="css/bootstrap-material-design.css">
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/popper.js@1.12.6/dist/umd/popper.js" integrity="sha384-fA23ZRQ3G/J53mElWqVJEGJzU0sTs+SvzG8fXVWP+kJQ1lwFAOkcUOysnlKJC33U" crossorigin="anonymous"></script>
<script src="https://unpkg.com/bootstrap-material-design@4.1.1/dist/js/bootstrap-material-design.js" integrity="sha384-CauSuKpEqAFajSpkdjv3z9t8E7RlpJ1UP0lKM/+NdtSarroVKu069AlsRPKkFBz9" crossorigin="anonymous"></script>
<script>$(document).ready(function() { $('body').bootstrapMaterialDesign(); });</script>
<script> <script>
//const exports = {}; //const exports = {};
</script> </script>

File diff suppressed because it is too large Load diff

View file

@ -323,11 +323,17 @@ class ChatBox {
chats: ChatEntry[]; chats: ChatEntry[];
private _activeChat: ChatEntry; private _activeChat: ChatEntry;
private _button_send: JQuery;
private _input_message: JQuery;
constructor(htmlTag: JQuery) { constructor(htmlTag: JQuery) {
this.htmlTag = htmlTag; this.htmlTag = htmlTag;
this.htmlTag.find(".input button").click(this.onSend.bind(this)); this._button_send = this.htmlTag.find(".button-send");
this.htmlTag.find(".input_box").keypress(event => { this._input_message = this.htmlTag.find(".input-message");
this._button_send.click(this.onSend.bind(this));
this._input_message.keypress(event => {
if(event.keyCode == JQuery.Key.Enter && !event.shiftKey) { if(event.keyCode == JQuery.Key.Enter && !event.shiftKey) {
this.onSend(); this.onSend();
return false; return false;
@ -335,9 +341,9 @@ class ChatBox {
}).on('input', (event) => { }).on('input', (event) => {
let text = $(event.target).val().toString(); let text = $(event.target).val().toString();
if(this.testMessage(text)) if(this.testMessage(text))
this.htmlTag.find(".input button").removeAttr("disabled"); this._button_send.removeAttr("disabled");
else else
this.htmlTag.find(".input button").attr("disabled", "true"); this._button_send.attr("disabled", "true");
}).trigger("input"); }).trigger("input");
this.chats = []; this.chats = [];
@ -394,11 +400,10 @@ class ChatBox {
onSend() { onSend() {
let textBox = $(this.htmlTag).find(".input_box"); let text = this._input_message.val().toString();
let text = textBox.val().toString();
if(!this.testMessage(text)) return; if(!this.testMessage(text)) return;
textBox.val(""); this._input_message.val("");
$(this.htmlTag).find(".input_box").trigger("input"); this._input_message.trigger("input");
if(this._activeChat && $.isFunction(this._activeChat.onMessageSend)) if(this._activeChat && $.isFunction(this._activeChat.onMessageSend))
this._activeChat.onMessageSend(text); this._activeChat.onMessageSend(text);
@ -433,7 +438,7 @@ class ChatBox {
break; break;
} }
} }
this.htmlTag.find(".input_box").prop("disabled", !flagAllowSend); this._input_message.prop("disabled", !flagAllowSend);
} }
get activeChat(){ return this._activeChat; } get activeChat(){ return this._activeChat; }
@ -447,7 +452,7 @@ class ChatBox {
} }
focus(){ focus(){
$(this.htmlTag).find(".input_box").focus(); this._input_message.focus();
} }
private testMessage(message: string) : boolean { private testMessage(message: string) : boolean {

View file

@ -1,5 +1,8 @@
let context_menu: JQuery;
$(document).bind("mousedown", function (e) { $(document).bind("mousedown", function (e) {
let menu = $(".context-menu"); let menu = context_menu || (context_menu = $(".context-menu"));
if(!menu.is(":visible")) return; if(!menu.is(":visible")) return;
if ($(e.target).parents(".context-menu").length == 0) { if ($(e.target).parents(".context-menu").length == 0) {
@ -9,7 +12,8 @@ $(document).bind("mousedown", function (e) {
let contextMenuCloseFn = undefined; let contextMenuCloseFn = undefined;
function despawn_context_menu() { function despawn_context_menu() {
let menu = $(".context-menu"); let menu = context_menu || (context_menu = $(".context-menu"));
if(!menu.is(":visible")) return; if(!menu.is(":visible")) return;
menu.hide(100); menu.hide(100);
if(contextMenuCloseFn) contextMenuCloseFn(); if(contextMenuCloseFn) contextMenuCloseFn();
@ -102,7 +106,9 @@ function generate_tag(entry: ContextMenuEntry) : JQuery {
} }
function spawn_context_menu(x, y, ...entries: ContextMenuEntry[]) { function spawn_context_menu(x, y, ...entries: ContextMenuEntry[]) {
const menu = $("#contextMenu").finish().empty(); let menu = context_menu || (context_menu = $(".context-menu"));
menu.finish().empty();
contextMenuCloseFn = undefined; contextMenuCloseFn = undefined;
for(let entry of entries){ for(let entry of entries){

View file

@ -261,7 +261,7 @@ const loader_javascript = {
*/ */
if(!window.require) { if(!window.require) {
await loader.load_script(["vendor/jquery/jquery.min.js"]); //await loader.load_script(["vendor/jquery/jquery.min.js"]);
} }
await loader.load_script("vendor/jsrender/jsrender.min.js"); await loader.load_script("vendor/jsrender/jsrender.min.js");
await loader.load_scripts([ await loader.load_scripts([

View file

@ -248,14 +248,13 @@ function main() {
const profile_uuid = settings.static("connect_profile") as string; const profile_uuid = settings.static("connect_profile") as string;
console.log("UUID: %s", profile_uuid); console.log("UUID: %s", profile_uuid);
const profile = profiles.find_profile(profile_uuid) || profiles.default_profile(); const profile = profiles.find_profile(profile_uuid) || profiles.default_profile();
console.log("UUID: %s", profile.id);
const address = settings.static("connect_address", ""); const address = settings.static("connect_address", "");
const username = settings.static("connect_username", "Another TeaSpeak user"); const username = settings.static("connect_username", "Another TeaSpeak user");
const password = settings.static("connect_password", ""); const password = settings.static("connect_password", "");
const password_hashed = settings.static("connect_password_hashed", false); const password_hashed = settings.static("connect_password_hashed", false);
if(profile.valid()) { if(profile && profile.valid()) {
globalClient.startConnection(address, profile, username, password.length > 0 ? { globalClient.startConnection(address, profile, username, password.length > 0 ? {
password: password, password: password,
hashed: password_hashed hashed: password_hashed
@ -279,15 +278,20 @@ function main() {
$("#music-test").replaceWith(tag); $("#music-test").replaceWith(tag);
Modals.spawnSettingsModal();
/* /*
Modals.spawnYesNo("Are your sure?", "Do you really want to exit?", flag => { createInputModal("Please enter some input", "A text with A", text => text.indexOf('a') != -1, result => {
console.log("Response: " + flag); console.error("Result: %o", result);
}) }, {
}).open();
*/ */
//Modals.spawnSettingsModal();
setup_close(); setTimeout(() => {
//Modals.spawnPlaylistManage(globalClient);
//Modals.openBanList(globalClient);
//Modals.spawnPermissionEdit().open();
//Modals.createServerModal(globalClient.channelTree.server, () => {});
}, 1000);
let _resize_timeout: NodeJS.Timer; let _resize_timeout: NodeJS.Timer;
$(window).on('resize', () => { $(window).on('resize', () => {
if(_resize_timeout) if(_resize_timeout)

View file

@ -346,6 +346,11 @@ class PermissionInfo {
name: string; name: string;
id: number; id: number;
description: string; description: string;
is_boolean() { return this.name.startsWith("b_"); }
id_grant() : number {
return this.id | (1 << 15);
}
} }
class PermissionGroup { class PermissionGroup {
@ -369,7 +374,7 @@ class PermissionValue {
flag_negate: boolean; flag_negate: boolean;
granted_value: number; granted_value: number;
constructor(type, value) { constructor(type, value?) {
this.type = type; this.type = type;
this.value = value; this.value = value;
} }
@ -382,7 +387,10 @@ class PermissionValue {
} }
hasValue() : boolean { hasValue() : boolean {
return this.value != -2; return typeof(this.value) !== "undefined" && this.value != -2;
}
hasGrant() : boolean {
return typeof(this.granted_value) !== "undefined" && this.granted_value != -2;
} }
} }
@ -459,6 +467,8 @@ class PermissionManager {
public static parse_permission_bulk(json: any[], manager: PermissionManager) : PermissionValue[] { public static parse_permission_bulk(json: any[], manager: PermissionManager) : PermissionValue[] {
let permissions: PermissionValue[] = []; let permissions: PermissionValue[] = [];
for(let perm of json) { for(let perm of json) {
if(perm["permid"] === undefined) continue;
let perm_id = parseInt(perm["permid"]); let perm_id = parseInt(perm["permid"]);
let perm_grant = (perm_id & (1 << 15)) > 0; let perm_grant = (perm_id & (1 << 15)) > 0;
if(perm_grant) if(perm_grant)

View file

@ -580,7 +580,7 @@ namespace profiles.identities {
return await this.improve_level(-1, threads, () => active); return await this.improve_level(-1, threads, () => active);
} }
async improve_level(target: number, threads: number, active_callback: () => boolean, callback_level?: (current: number) => any) : Promise<Boolean> { async improve_level(target: number, threads: number, active_callback: () => boolean, callback_level?: (current: number) => any, callback_status?: (hash_rate: number) => any) : Promise<Boolean> {
if(!this._initialized || !this.public_key) if(!this._initialized || !this.public_key)
throw "not initialized"; throw "not initialized";
if(target == -1) /* get the highest level possible */ if(target == -1) /* get the highest level possible */
@ -625,6 +625,24 @@ namespace profiles.identities {
let target_level = target > 0 ? target : await this.level() + 1; let target_level = target > 0 ? target : await this.level() + 1;
const worker_promise: Promise<void>[] = []; const worker_promise: Promise<void>[] = [];
const hash_timestamps: number[] = [];
let last_hashrate_update: number = 0;
const update_hashrate = () => {
if(!callback_status) return;
const now = Date.now();
hash_timestamps.push(now);
if(last_hashrate_update + 1000 < now) {
last_hashrate_update = now;
const timeout = now - 10 * 1000; /* 10s */
const rounds = hash_timestamps.filter(e => e > timeout);
callback_status(Math.ceil((rounds.length * iterations) / Math.ceil((now - rounds[0]) / 1000)))
}
};
try { try {
result = await new Promise<boolean>((resolve, reject) => { result = await new Promise<boolean>((resolve, reject) => {
let active = true; let active = true;
@ -644,6 +662,8 @@ namespace profiles.identities {
const promise = worker.mine(next_hash(), iterations, target_level); const promise = worker.mine(next_hash(), iterations, target_level);
const p = promise.then(result => { const p = promise.then(result => {
update_hashrate();
worker_promise.remove(p); worker_promise.remove(p);
if(result.valueOf()) { if(result.valueOf()) {

View file

@ -14,6 +14,14 @@ interface JQuery<TElement = HTMLElement> {
render(values?: any) : string; render(values?: any) : string;
renderTag(values?: any) : JQuery<TElement>; renderTag(values?: any) : JQuery<TElement>;
hasScrollBar() : boolean; hasScrollBar() : boolean;
visible_height() : number;
/* bootstrap */
alert() : JQuery<TElement>;
modal(properties: any) : this;
bootstrapMaterialDesign() : this;
} }
interface JQueryStatic<TElement extends Node = HTMLElement> { interface JQueryStatic<TElement extends Node = HTMLElement> {
@ -133,6 +141,20 @@ if(typeof ($) !== "undefined") {
return this.get(0).scrollHeight > this.height(); return this.get(0).scrollHeight > this.height();
} }
if(!$.fn.visible_height)
$.fn.visible_height = function (this: JQuery<HTMLElement>) {
const original_style = this.attr("style");
this.css({
position: 'absolute!important',
visibility: 'hidden!important',
display: 'block!important'
});
const result = this.height();
console.log(original_style);
this.attr("style", original_style || "");
return result;
}
} }
if (!String.prototype.format) { if (!String.prototype.format) {

View file

@ -110,7 +110,7 @@ class ChannelEntry {
getChannelId(){ return this.channelId; } getChannelId(){ return this.channelId; }
channelClass() { return "channel_full"; } channelClass() { return "channel_full"; }
siblings(deep = false) : ChannelEntry[] { children(deep = false) : ChannelEntry[] {
const result: ChannelEntry[] = []; const result: ChannelEntry[] = [];
if(this.channelTree == null) return []; if(this.channelTree == null) return [];
@ -292,7 +292,7 @@ class ChannelEntry {
let subSize = 0; let subSize = 0;
let clientSize = 0; let clientSize = 0;
const sub = this.siblings(false); const sub = this.children(false);
sub.forEach(function (e) { sub.forEach(function (e) {
if(e.rootTag().is(":visible")) if(e.rootTag().is(":visible"))
subSize += e.rootTag().outerHeight(true); subSize += e.rootTag().outerHeight(true);

View file

@ -511,7 +511,6 @@ class MusicInfoManager extends ClientInfoManager {
}).catch(error => { }).catch(error => {
createErrorModal(tr("Failed to query playlist."), tr("Failed to query playlist info.")).open(); createErrorModal(tr("Failed to query playlist."), tr("Failed to query playlist info.")).open();
}); });
createErrorModal(tr("Not implemented"), tr("This function is not implemented yet!")).open();
}); });
} }

View file

@ -8,7 +8,6 @@ namespace Modals {
header: base && base.banid > 0 ? tr("Edit ban") : tr("Add ban"), header: base && base.banid > 0 ? tr("Edit ban") : tr("Add ban"),
body: () => { body: () => {
let template = $("#tmpl_ban_create").renderTag(); let template = $("#tmpl_ban_create").renderTag();
template = $.spawn("div").append(template);
const input_name = template.find(".input-name"); const input_name = template.find(".input-name");
const input_name_type = template.find(".input-name-type"); const input_name_type = template.find(".input-name-type");

View file

@ -180,10 +180,9 @@ namespace Modals {
header: tr("Banlist"), header: tr("Banlist"),
body: () => { body: () => {
let template = $("#tmpl_ban_list").renderTag(); let template = $("#tmpl_ban_list").renderTag();
template = $.spawn("div").append(template);
apply_filter(template.find(".entry-filter"), template.find(".filter-flag-force-own"), template.find(".filter-flag-highlight-own"), template.find(".ban-entry-list")); apply_filter(template.find(".entry-filter"), template.find(".filter-flag-force-own"), template.find(".filter-flag-highlight-own"), template.find(".ban-entry-list"));
update_function = apply_buttons(template.find(".manage-buttons"), template.find(".ban-entry-list"), callback_add, _callback_edit, _callback_delete); update_function = apply_buttons(template.find(".manage-buttons"), template.find(".entry-container .entries"), callback_add, _callback_edit, _callback_delete);
template.find(".button-close").on('click', _ => modal.close()); template.find(".button-close").on('click', _ => modal.close());
template.find(".button-refresh").on('click', () => callback_update()); template.find(".button-refresh").on('click', () => callback_update());
return template; return template;
@ -195,17 +194,18 @@ namespace Modals {
modal.open(); modal.open();
modal.close_listener.push(() => entries = []); modal.close_listener.push(() => entries = []);
const template_entry = $("#tmpl_ban_entry");
result.addbans = (bans: BanEntry[]) => { result.addbans = (bans: BanEntry[]) => {
for(const entry of bans) { for(const entry of bans) {
entries.push(entry); entries.push(entry);
$("#tmpl_ban_entry").renderTag(entry).appendTo(modal.htmlTag.find(".ban-entry-list")); template_entry.renderTag(entry).appendTo(modal.htmlTag.find(".entry-container .entries"));
} }
modal.htmlTag.find(".entry-filter").trigger("change"); modal.htmlTag.find(".entry-filter").trigger("change");
update_function(); update_function();
}; };
result.clear = () => { result.clear = () => {
entries = []; entries = [];
modal.htmlTag.find(".ban-entry-list").children().detach(); modal.htmlTag.find(".entry-container .entries").children().detach();
update_function(); update_function();
}; };
@ -253,24 +253,24 @@ namespace Modals {
function apply_buttons(tag: JQuery, elements: JQuery, cb_add: () => any, cb_edit: (id: number) => any, cb_delete: (id: number) => any) : () => any { function apply_buttons(tag: JQuery, elements: JQuery, cb_add: () => any, cb_edit: (id: number) => any, cb_delete: (id: number) => any) : () => any {
const update = () => { const update = () => {
console.log(elements.find("tr.selected").length); console.log(elements.find(".ban-entry.selected").length);
$(".button-edit, .button-remove").prop("disabled", elements.find("tr.selected").length == 0); $(".button-edit, .button-remove").prop("disabled", elements.find(".ban-entry.selected").length == 0);
}; };
tag.find(".button-add").on('click', event => cb_add()); tag.find(".button-add").on('click', event => cb_add());
tag.find(".button-edit").on('click', event => { tag.find(".button-edit").on('click', event => {
const selected = elements.find("tr.selected"); const selected = elements.find(".ban-entry.selected");
if(!selected) return; if(!selected) return;
cb_edit(parseInt(selected.attr("ban-id"))); cb_edit(parseInt(selected.attr("ban-id")));
}); });
tag.find(".button-remove").on('click', event => { tag.find(".button-remove").on('click', event => {
const selected = elements.find("tr.selected"); const selected = elements.find(".ban-entry.selected");
if(!selected) return; if(!selected) return;
cb_delete(parseInt(selected.attr("ban-id"))); cb_delete(parseInt(selected.attr("ban-id")));
}); });
const element_selected = element => { const element_selected = element => {
elements.find("tr").removeClass("selected"); elements.find(".ban-entry").removeClass("selected");
if(element.is(":visible")) if(element.is(":visible"))
element.addClass("selected"); element.addClass("selected");
@ -296,7 +296,7 @@ namespace Modals {
}; };
return () => { return () => {
elements.find("tr").each((_idx, _entry) => { elements.find(".ban-entry").each((_idx, _entry) => {
_entry.addEventListener("click", click_handler); _entry.addEventListener("click", click_handler);
_entry.addEventListener("contextmenu", context_handler) _entry.addEventListener("contextmenu", context_handler)
}); });

View file

@ -3,102 +3,123 @@
namespace Modals { namespace Modals {
export function spawnConnectModal(defaultHost: { url: string, enforce: boolean} = { url: "ts.TeaSpeak.de", enforce: false}, connect_profile?: { profile: profiles.ConnectionProfile, enforce: boolean}) { export function spawnConnectModal(defaultHost: { url: string, enforce: boolean} = { url: "ts.TeaSpeak.de", enforce: false}, connect_profile?: { profile: profiles.ConnectionProfile, enforce: boolean}) {
let selected_profile: profiles.ConnectionProfile; let selected_profile: profiles.ConnectionProfile;
const connectModal = createModal({
header: function() { const random_id = (() => {
let header = $.spawn("div"); const array = new Uint32Array(10);
header.text(tr("Create a new connection")); window.crypto.getRandomValues(array);
return header; return array.join("");
}, })();
body: function () {
let tag = $("#tmpl_connect").renderTag({ const connect_modal = $("#tmpl_connect").renderTag({
client: native_client, client: native_client,
forum_path: settings.static("forum_path") forum_path: settings.static("forum_path"),
password_id: random_id
}).modalize((header, body, footer) => {
const button_connect = footer.find(".button-connect");
const button_manage = body.find(".button-manage-profiles");
const input_profile = body.find(".container-select-profile select");
const input_address = body.find(".container-address input");
const input_nickname = body.find(".container-nickname input");
const input_password = body.find(".container-password input");
let updateFields = function () {
console.log("Updating");
if(selected_profile)
input_nickname.attr("placeholder", selected_profile.default_username);
else
input_nickname.attr("placeholder", "");
let address = input_address.val().toString();
settings.changeGlobal("connect_address", address);
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.DOMAIN);
let nickname = input_nickname.val().toString();
settings.changeGlobal("connect_name", nickname);
let flag_nickname = (nickname.length == 0 && selected_profile && selected_profile.default_username.length > 0) || nickname.length >= 3 && nickname.length <= 32;
input_address.attr('pattern', flag_address ? null : '^[a]{1000}$').toggleClass('is-invalid', !flag_address);
input_nickname.attr('pattern', flag_nickname ? null : '^[a]{1000}$').toggleClass('is-invalid', !flag_nickname);
if(!flag_nickname || !flag_address || !selected_profile || !selected_profile.valid()) {
button_connect.prop("disabled", true);
} else {
button_connect.prop("disabled", false);
}
};
input_nickname.val(settings.static_global("connect_name", undefined));
input_address.val(defaultHost.enforce ? defaultHost.url : settings.static_global("connect_address", defaultHost.url));
input_address
.on("keyup", () => updateFields())
.on('keydown', event => {
if(event.keyCode == JQuery.Key.Enter && !event.shiftKey)
button_connect.trigger('click');
}); });
let updateFields = function () { button_manage.on('click', event => {
if(selected_profile) tag.find(".connect_nickname").attr("placeholder", selected_profile.default_username); const modal = Modals.spawnSettingsModal();
else setTimeout(() => {
tag.find(".connect_nickname").attr(""); modal.htmlTag.find(".tab-profiles").parent(".entry").trigger('click');
}, 100);
let button = tag.parents(".modal-content").find(".connect_connect_button"); modal.close_listener.push(() => {
input_profile.trigger('change');
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 && selected_profile && selected_profile.default_username.length > 0) || nickname.length >= 3 && nickname.length <= 32;
if(flag_address) {
if(field_address.hasClass("invalid_input"))
field_address.removeClass("invalid_input");
} else {
if(!field_address.hasClass("invalid_input"))
field_address.addClass("invalid_input");
}
if(flag_nickname) {
if(field_nickname.hasClass("invalid_input"))
field_nickname.removeClass("invalid_input");
} else {
if(!field_nickname.hasClass("invalid_input"))
field_nickname.addClass("invalid_input");
}
if(!flag_nickname || !flag_address || !selected_profile || !selected_profile.valid()) {
button.prop("disabled", true);
} else {
button.prop("disabled", false);
}
};
tag.find(".connect_nickname").val(settings.static_global("connect_name", undefined));
tag.find(".connect_address").val(defaultHost.enforce ? defaultHost.url : settings.static_global("connect_address", defaultHost.url));
tag.find(".connect_address")
.on("keyup", () => updateFields())
.on('keydown', event => {
if(event.keyCode == JQuery.Key.Enter && !event.shiftKey)
tag.parents(".modal-content").find(".connect_connect_button").trigger('click');
});
tag.find(".button-manage-profiles").on('click', event => {
const modal = Modals.spawnSettingsModal();
setTimeout(() => {
modal.htmlTag.find(".tab-profiles").parent(".entry").trigger('click');
}, 100);
modal.close_listener.push(() => {
tag.find(".profile-select-container select").trigger('change');
});
return true;
}); });
return true;
});
{ {
const select_tag = tag.find(".profile-select-container select"); for(const profile of profiles.profiles()) {
const select_invalid_tag = tag.find(".profile-invalid"); input_profile.append(
$.spawn("option").text(profile.profile_name).val(profile.id)
for(const profile of profiles.profiles()) { );
select_tag.append(
$.spawn("option").text(profile.profile_name).val(profile.id)
);
}
select_tag.on('change', event => {
selected_profile = profiles.find_profile(select_tag.val() as string);
if(!selected_profile || !selected_profile.valid())
select_invalid_tag.show();
else
select_invalid_tag.hide();
updateFields();
});
select_tag.val(connect_profile && connect_profile.enforce ? connect_profile.profile.id : connect_profile && connect_profile.profile ? connect_profile.profile.id : 'default').trigger('change');
} }
tag.find(".connect_nickname").on("keyup", () => updateFields()); input_profile.on('change', event => {
selected_profile = profiles.find_profile(input_profile.val() as string);
input_profile.toggleClass("is-invalid", !selected_profile || !selected_profile.valid());
updateFields();
});
input_profile.val(connect_profile && connect_profile.enforce ? connect_profile.profile.id : connect_profile && connect_profile.profile ? connect_profile.profile.id : 'default').trigger('change');
}
input_nickname.on("keyup", () => updateFields());
setTimeout(() => updateFields(), 100);
button_connect.on('click', event => {
connect_modal.close();
globalClient.startConnection(
input_address.val().toString(),
selected_profile,
input_nickname.val().toString() || selected_profile.default_username,
{password: input_password.val().toString(), hashed: false}
);
});
}, {
width: '70%'
});
connect_modal.open();
return;
const connectModal = createModal({
header: (tr("Create a new connection")),
body: function () {
const random_id = (() => {
const array = new Uint32Array(10);
window.crypto.getRandomValues(array);
return array.join("");
})();
let tag = $("#tmpl_connect").renderTag({
client: native_client,
forum_path: settings.static("forum_path"),
password_id: random_id
});
setTimeout(() => updateFields(), 100);
//connect_address //connect_address
return tag; return tag;
}, },

View file

@ -10,7 +10,6 @@ namespace Modals {
channel_flag_maxfamilyclients_unlimited: true, channel_flag_maxfamilyclients_unlimited: true,
channel_flag_maxclients_unlimited: true channel_flag_maxclients_unlimited: true
} as ChannelProperties); } as ChannelProperties);
template = $.spawn("div").append(template);
return template.tabify(); return template.tabify();
}, },
footer: () => { footer: () => {
@ -36,7 +35,7 @@ namespace Modals {
applyGeneralListener(properties, modal.htmlTag.find(".general_properties"), modal.htmlTag.find(".button_ok"), !channel); applyGeneralListener(properties, modal.htmlTag.find(".general_properties"), modal.htmlTag.find(".button_ok"), !channel);
applyStandardListener(properties, modal.htmlTag.find(".settings_standard"), modal.htmlTag.find(".button_ok"), parent, !channel); applyStandardListener(properties, modal.htmlTag.find(".settings_standard"), modal.htmlTag.find(".button_ok"), parent, !channel);
applyPermissionListener(properties, modal.htmlTag.find(".settings_permissions"), modal.htmlTag.find(".button_ok"), permissions, channel); applyPermissionListener(properties, modal.htmlTag.find(".settings_permissions"), modal.htmlTag.find(".button_ok"), permissions, channel);
applyAudioListener(properties, modal.htmlTag.find(".settings_audio"), modal.htmlTag.find(".button_ok"), channel); applyAudioListener(properties, modal.htmlTag.find(".container-channel-settings-audio"), modal.htmlTag.find(".button_ok"), channel);
applyAdvancedListener(properties, modal.htmlTag.find(".settings_advanced"), modal.htmlTag.find(".button_ok"), channel); applyAdvancedListener(properties, modal.htmlTag.find(".settings_advanced"), modal.htmlTag.find(".button_ok"), channel);
let updated: PermissionValue[] = []; let updated: PermissionValue[] = [];
@ -144,11 +143,11 @@ namespace Modals {
properties.channel_flag_default = this.checked; properties.channel_flag_default = this.checked;
let elements = tag.find("input[name=\"channel_type\"]"); let elements = tag.find("input[name=\"channel_type\"]");
elements.prop("disabled", this.checked);
if(this.checked) { if(this.checked) {
elements.prop("enabled", false);
elements.prop("checked", false); elements.prop("checked", false);
tag.find("input[name=\"channel_type\"][value=\"perm\"]").prop("checked", true).trigger("change"); tag.find("input[name=\"channel_type\"][value=\"perm\"]").prop("checked", true).trigger("change");
} else elements.removeProp("enabled"); }
}).prop("disabled", }).prop("disabled",
!globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) || !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
!globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DEFAULT : PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1)); !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DEFAULT : PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1));
@ -158,7 +157,7 @@ namespace Modals {
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER : PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1)); }).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER : PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1));
let orderTag = tag.find(".order_id"); let orderTag = tag.find(".order_id");
for(let channel of (parent ? parent.siblings() : globalClient.channelTree.rootChannel())) for(let channel of (parent ? parent.children() : globalClient.channelTree.rootChannel()))
$.spawn("option").attr("channelId", channel.channelId.toString()).text(channel.channelName()).appendTo(orderTag); $.spawn("option").attr("channelId", channel.channelId.toString()).text(channel.channelName()).appendTo(orderTag);
orderTag.change(function (this: HTMLSelectElement) { orderTag.change(function (this: HTMLSelectElement) {
@ -176,7 +175,7 @@ namespace Modals {
for(let cperm of channel_permissions) for(let cperm of channel_permissions)
if(cperm.type.name == PermissionType.I_CHANNEL_NEEDED_MODIFY_POWER) { if(cperm.type.name == PermissionType.I_CHANNEL_NEEDED_MODIFY_POWER) {
required_power = cperm.value; required_power = cperm.value;
return; break;
} }
tag.find("input[permission]").each((index, _element) => { tag.find("input[permission]").each((index, _element) => {
@ -203,14 +202,14 @@ namespace Modals {
}); });
if(!permissions.neededPermission(PermissionType.I_CHANNEL_MODIFY_POWER).granted(required_power, false)) { if(!permissions.neededPermission(PermissionType.I_CHANNEL_MODIFY_POWER).granted(required_power, false)) {
tag.find("input[permission]").prop("enabled", false); //No permissions tag.find("input[permission]").prop("disabled", false); //No permissions
} }
}; };
if(channel) { if(channel) {
permissions.requestChannelPermissions(channel.getChannelId()).then(apply_permissions).catch((error) => { permissions.requestChannelPermissions(channel.getChannelId()).then(apply_permissions).catch((error) => {
tag.find("input[permission]").prop("enabled", false); tag.find("input[permission]").prop("disabled", true);
console.log(error); console.log("Failed to receive channel permissions (%o)", error);
}); });
} else apply_permissions([]); } else apply_permissions([]);
} }

File diff suppressed because it is too large Load diff

View file

@ -83,7 +83,6 @@ namespace Modals {
header: tr("Edit playlist"), header: tr("Edit playlist"),
body: () => { body: () => {
let template = $("#tmpl_playlist_edit").renderTag().tabify(); let template = $("#tmpl_playlist_edit").renderTag().tabify();
template = $.spawn("div").append(template);
callback_permission_update = apply_permissions(template, client, playlist, (key, value) => { callback_permission_update = apply_permissions(template, client, playlist, (key, value) => {
console.log("Change permission %o => %o", key, value); console.log("Change permission %o => %o", key, value);
@ -299,8 +298,8 @@ namespace Modals {
const owns_playlist = playlist.playlist_owner_dbid == client.getClient().properties.client_database_id; const owns_playlist = playlist.playlist_owner_dbid == client.getClient().properties.client_database_id;
client.serverConnection.helper.request_playlist_info(playlist.playlist_id).then(info => { client.serverConnection.helper.request_playlist_info(playlist.playlist_id).then(info => {
tag.find(".property-owner .value") tag.find(".property-owner input")
.text(info.playlist_owner_name + " (" + info.playlist_owner_dbid + ")"); .val(info.playlist_owner_name + " (" + info.playlist_owner_dbid + ")");
tag.find(".property-title input") tag.find(".property-title input")
.val(info.playlist_title) .val(info.playlist_title)
@ -337,8 +336,8 @@ namespace Modals {
change_property("playlist_flag_delete_played", (<HTMLInputElement>event.target).checked ? "1" : "0"); change_property("playlist_flag_delete_played", (<HTMLInputElement>event.target).checked ? "1" : "0");
}); });
tag.find(".property-current-song .value") tag.find(".property-current-song input")
.text(info.playlist_current_song_id); .val(info.playlist_current_song_id);
callback_current_song(info.playlist_current_song_id); callback_current_song(info.playlist_current_song_id);
tag.find(".property-flag-finished input") tag.find(".property-flag-finished input")

View file

@ -81,7 +81,6 @@ namespace Modals {
header: tr("Manage playlists"), header: tr("Manage playlists"),
body: () => { body: () => {
let template = $("#tmpl_playlist_list").renderTag(); let template = $("#tmpl_playlist_list").renderTag();
template = $.spawn("div").append(template);
/* first open the modal */ /* first open the modal */
setTimeout(() => { setTimeout(() => {

View file

@ -54,10 +54,10 @@ namespace Modals {
export function spawnQueryCreated(credentials: { export function spawnQueryCreated(credentials: {
username: string, username: string,
password: string password: string
}, yust_created: boolean) { }, just_created: boolean) {
let modal; let modal;
modal = createModal({ modal = createModal({
header: yust_created ? tr("Server query credentials") : tr("New server query credentials"), header: just_created ? tr("Server query credentials") : tr("New server query credentials"),
body: () => { body: () => {
let template = $("#tmpl_query_created").renderTag(credentials); let template = $("#tmpl_query_created").renderTag(credentials);
template = $.spawn("div").append(template); template = $.spawn("div").append(template);

View file

@ -3,35 +3,17 @@
namespace Modals { namespace Modals {
export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => any) { export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => any) {
let properties: ServerProperties = {} as ServerProperties; //The changes properties let properties: ServerProperties = {} as ServerProperties; //The changes properties
const modal = createModal({
header: tr("Manager the Virtual Server"),
body: () => {
let template = $("#tmpl_server_edit").renderTag(server.properties);
template = $.spawn("div").append(template);
return template.tabify();
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin", "5px");
let buttonCancel = $.spawn("button"); const modal_template = $("#tmpl_server_edit").renderTag(server.properties);
buttonCancel.text(tr("Cancel")).addClass("button_cancel"); const modal = modal_template.modalize((header, body, footer) => {
return {
let buttonOk = $.spawn("button"); body: body.tabify()
buttonOk.text(tr("Ok")).addClass("button_ok"); }
footer.append(buttonCancel);
footer.append(buttonOk);
return footer;
},
width: 750
}); });
server_applyGeneralListener(properties, modal.htmlTag.find(".properties_general"), modal.htmlTag.find(".button_ok")); server_applyGeneralListener(properties, modal.htmlTag.find(".properties_general"), modal.htmlTag.find(".button_ok"));
server_applyTransferListener(properties, server, modal.htmlTag.find('.container-file-transfer')); server_applyTransferListener(properties, server, modal.htmlTag.find('.properties_transfer'));
server_applyHostListener(properties, server.properties, modal.htmlTag.find(".properties_host"), modal.htmlTag.find(".button_ok")); server_applyHostListener(server, properties, server.properties, modal.htmlTag.find(".properties_host"), modal.htmlTag.find(".button_ok"));
server_applyMessages(properties, server, modal.htmlTag.find(".properties_messages")); server_applyMessages(properties, server, modal.htmlTag.find(".properties_messages"));
server_applyFlood(properties, server, modal.htmlTag.find(".properties_flood")); server_applyFlood(properties, server, modal.htmlTag.find(".properties_flood"));
server_applySecurity(properties, server, modal.htmlTag.find(".properties_security")); server_applySecurity(properties, server, modal.htmlTag.find(".properties_security"));
@ -102,7 +84,7 @@ namespace Modals {
} }
function server_applyHostListener(properties: ServerProperties, original_properties: ServerProperties, tag: JQuery, button: JQuery) { function server_applyHostListener(server: ServerEntry, properties: ServerProperties, original_properties: ServerProperties, tag: JQuery, button: JQuery) {
tag.find(".virtualserver_host").change(function (this: HTMLInputElement) { tag.find(".virtualserver_host").change(function (this: HTMLInputElement) {
properties.virtualserver_host = this.value; properties.virtualserver_host = this.value;
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOST).granted(1)); }).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOST).granted(1));
@ -152,6 +134,10 @@ namespace Modals {
properties.virtualserver_hostbutton_gfx_url = this.value; properties.virtualserver_hostbutton_gfx_url = this.value;
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBUTTON).granted(1)); }).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBUTTON).granted(1));
server.updateProperties().then(() => {
tag.find(".virtualserver_host").val(server.properties.virtualserver_host);
tag.find(".virtualserver_port").val(server.properties.virtualserver_port);
});
} }
function server_applyMessages(properties: ServerProperties, server: ServerEntry, tag: JQuery) { function server_applyMessages(properties: ServerProperties, server: ServerEntry, tag: JQuery) {

View file

@ -22,11 +22,11 @@ namespace Modals {
let active; let active;
const button_start_stop = template.find(".button-start-stop"); const button_start_stop = template.find(".button-start-stop");
const button_close = template.find(".button-close"); const button_close = template.find(".button-close");
const input_current_level = template.find(".property.identity-level input"); const input_current_level = template.find(".identity-level input");
const input_target_level = template.find(".property.identity-target-level input"); const input_target_level = template.find(".identity-target-level input");
const input_threads = template.find(".property.threads input"); const input_threads = template.find(".threads input");
const input_hash_rate = template.find(".property.hash-rate input"); const input_hash_rate = template.find(".hash-rate input");
const input_elapsed = template.find(".property.time-elapsed input"); const input_elapsed = template.find(".time-elapsed input");
button_close.on('click', event => { button_close.on('click', event => {
if(active) if(active)
@ -37,10 +37,10 @@ namespace Modals {
}); });
button_start_stop.on('click', event => { button_start_stop.on('click', event => {
if(active) button_start_stop
button_start_stop.text(tr("Start")); .toggleClass('btn-success', active)
else .toggleClass('btn-danger', !active)
button_start_stop.text(tr("Stop")); .text(active ? tr("Start") : tr("Stop"));
input_threads.prop("disabled", !active); input_threads.prop("disabled", !active);
input_target_level.prop("disabled", !active); input_target_level.prop("disabled", !active);
@ -58,6 +58,8 @@ namespace Modals {
if(target_level == 0) { if(target_level == 0) {
identity.improve_level(-1, threads, () => active, current_level => { identity.improve_level(-1, threads, () => active, current_level => {
input_current_level.val(current_level); input_current_level.val(current_level);
}, hash_rate => {
input_hash_rate.val(hash_rate);
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
createErrorModal(tr("Failed to improve identity"), tr("Failed to improve identity.<br>Error:") + error).open(); createErrorModal(tr("Failed to improve identity"), tr("Failed to improve identity.<br>Error:") + error).open();
@ -67,6 +69,8 @@ namespace Modals {
} else { } else {
identity.improve_level(target_level, threads, () => active, current_level => { identity.improve_level(target_level, threads, () => active, current_level => {
input_current_level.val(current_level); input_current_level.val(current_level);
}, hash_rate => {
input_hash_rate.val(hash_rate);
}).then(success => { }).then(success => {
if(success) { if(success) {
identity.level().then(level => { identity.level().then(level => {
@ -103,7 +107,7 @@ namespace Modals {
}); });
template.find(".property.identity-unique-id input").val(identity.uid()); template.find(".identity-unique-id input").val(identity.uid());
identity.level().then(level => { identity.level().then(level => {
input_current_level.val(level); input_current_level.val(level);
}).catch(error => { }).catch(error => {
@ -208,7 +212,6 @@ namespace Modals {
forum_path: settings.static("forum_path"), forum_path: settings.static("forum_path"),
}); });
template = $.spawn("div").append(template);
initialiseVoiceListeners(modal, (template = template.tabify()).find(".settings_audio")); initialiseVoiceListeners(modal, (template = template.tabify()).find(".settings_audio"));
initialise_translations(template.find(".settings-translations")); initialise_translations(template.find(".settings-translations"));
initialise_profiles(modal, template.find(".settings-profiles")); initialise_profiles(modal, template.find(".settings-profiles"));
@ -216,20 +219,7 @@ namespace Modals {
return template; return template;
}, },
footer: () => { footer: undefined,
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
footer.css("margin-bottom", "5px");
footer.css("text-align", "right");
let buttonOk = $.spawn("button");
buttonOk.text(tr("Ok"));
buttonOk.click(() => modal.close());
footer.append(buttonOk);
return footer;
},
width: 750 width: 750
}); });
modal.open(); modal.open();
@ -295,7 +285,7 @@ namespace Modals {
globalClient.voiceConnection.voiceRecorder.update(true); globalClient.voiceConnection.voiceRecorder.update(true);
vad.percentage_listener = per => { vad.percentage_listener = per => {
vad_tag.find(".vad_vad_bar_filler") vad_tag.find(".vad_vad_bar_filler")
.css("width", per + "%"); .css("width", (100 - per) + "%");
}; };
break; break;
} }
@ -372,15 +362,24 @@ namespace Modals {
setTimeout(() => target_tag.trigger('change'), 0); setTimeout(() => target_tag.trigger('change'), 0);
} }
const display_error = (message: string) => {
const alert = tag.find(".settings-device-error").first();
alert.clone()
.alert()
.css("display", "block")
.insertAfter(alert)
.find(".message")
.text(message);
};
{ //Initialize microphone { //Initialize microphone
const setting_tag = tag.find(".settings-microphone"); const setting_tag = tag.find(".settings-microphone");
const tag_select = setting_tag.find(".audio-select-microphone"); const tag_select = setting_tag.find(".audio-select-microphone");
console.log(setting_tag);
console.log(setting_tag.find(".settings-device-error"));
console.log(setting_tag.find(".settings-device-error").html());
{ //List devices const update_devices = () => { //List devices
tag_select.empty();
$.spawn("option") $.spawn("option")
.attr("device-id", "") .attr("device-id", "")
.attr("device-group", "") .attr("device-group", "")
@ -391,7 +390,7 @@ namespace Modals {
const active_device = globalClient.voiceConnection.voiceRecorder.device_id(); const active_device = globalClient.voiceConnection.voiceRecorder.device_id();
for(const device of devices) { for(const device of devices) {
console.debug(tr("Got device %s (%s): %s"), device.deviceId, device.kind, device.label); console.debug(tr("Got device %s (%s): %s (%o)"), device.deviceId, device.kind, device.label);
if(device.kind !== 'audioinput') continue; if(device.kind !== 'audioinput') continue;
$.spawn("option") $.spawn("option")
@ -404,15 +403,13 @@ namespace Modals {
}).catch(error => { }).catch(error => {
console.error(tr("Could not enumerate over devices!")); console.error(tr("Could not enumerate over devices!"));
console.error(error); console.error(error);
setting_tag.find(".settings-device-error") display_error(tr("Could not get microphone device list!"));
.text(tr("Could not get device list!"))
.css("display", "block");
}); });
if(tag_select.find("option:selected").length == 0) if(tag_select.find("option:selected").length == 0)
tag_select.find("option").prop("selected", true); tag_select.find("option").prop("selected", true);
} };
{ {
tag_select.on('change', event => { tag_select.on('change', event => {
@ -423,47 +420,53 @@ namespace Modals {
globalClient.voiceConnection.voiceRecorder.change_device(deviceId, groupId); globalClient.voiceConnection.voiceRecorder.change_device(deviceId, groupId);
}); });
} }
update_devices();
setting_tag.find(".button-device-update").on('click', event => update_devices());
} }
{ //Initialize speaker { //Initialize speaker
const setting_tag = tag.find(".settings-speaker"); const setting_tag = tag.find(".settings-speaker");
const tag_select = setting_tag.find(".audio-select-speaker"); const tag_select = setting_tag.find(".audio-select-speaker");
const active_device = audio.player.current_device();
audio.player.available_devices().then(devices => {
for(const device of devices) {
$.spawn("option")
.attr("device-id", device.device_id)
.text(device.name)
.prop("selected", device.device_id == active_device.device_id)
.appendTo(tag_select);
}
}).catch(error => {
console.error(tr("Could not enumerate over devices!"));
console.error(error);
setting_tag.find(".settings-device-error")
.text(tr("Could not get device list!"))
.css("display", "block");
});
if(tag_select.find("option:selected").length == 0) const update_devices = () => {
tag_select.find("option").prop("selected", true); tag_select.empty();
const active_device = audio.player.current_device();
audio.player.available_devices().then(devices => {
for(const device of devices) {
$.spawn("option")
.attr("device-id", device.device_id)
.text(device.name)
.prop("selected", device.device_id == active_device.device_id)
.appendTo(tag_select);
}
}).catch(error => {
console.error(tr("Could not enumerate over devices!"));
console.error(error);
display_error(tr("Could not get speaker device list!"));
});
if(tag_select.find("option:selected").length == 0)
tag_select.find("option").prop("selected", true);
}
{ {
const error_tag = setting_tag.find(".settings-device-error");
tag_select.on('change', event => { tag_select.on('change', event => {
let selected_tag = tag_select.find("option:selected"); let selected_tag = tag_select.find("option:selected");
let deviceId = selected_tag.attr("device-id"); let deviceId = selected_tag.attr("device-id");
console.log(tr("Selected speaker device: id: %o"), deviceId); console.log(tr("Selected speaker device: id: %o"), deviceId);
audio.player.set_device(deviceId).then(() => error_tag.css("display", "none")).catch(error => { audio.player.set_device(deviceId).catch(error => {
console.error(error); console.error(error);
error_tag display_error(tr("Failed to change device!"));
.text(tr("Failed to change device!"))
.css("display", "block");
}); });
}); });
} }
update_devices();
setting_tag.find(".button-device-update").on('click', event => update_devices());
} }
{ /* initialize sounds */ { /* initialize sounds */
@ -857,9 +860,9 @@ namespace Modals {
const display_error = (error?: string) => { const display_error = (error?: string) => {
if(error){ if(error){
settings_tag.find(".error-message").show().html(error); settings_tag.find(".settings-profile-error").show().find(".message").html(error);
} else } else
settings_tag.find(".error-message").hide(); settings_tag.find(".settings-profile-error").hide();
status_listener(); status_listener();
}; };
@ -954,8 +957,8 @@ namespace Modals {
teamspeak_tag.find(".identity-undefined").hide(); teamspeak_tag.find(".identity-undefined").hide();
button_export.prop("disabled", false); button_export.prop("disabled", false);
identity_info_tag.find(".property.unique-id input").val(profile.uid()); identity_info_tag.find(".unique-id input").val(profile.uid());
const input_level = identity_info_tag.find(".property.level input").val("loading..."); const input_level = identity_info_tag.find(".level input").val("loading...");
profile.level().then(level => input_level.val(level.toString())).catch(error => input_level.val("error: " + error)); profile.level().then(level => input_level.val(level.toString())).catch(error => input_level.val("error: " + error));
} }
display_error(); display_error();

View file

@ -1,38 +1,44 @@
/// <reference path="../../utils/modal.ts" /> /// <reference path="../../utils/modal.ts" />
namespace Modals { namespace Modals {
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any) { export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: {
let modal; text_yes?: string,
modal = createModal({ text_no?: string
header: header, }) {
body: body, properties = properties || {};
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
footer.css("margin-bottom", "5px");
footer.css("text-align", "right");
let button_yes = $.spawn("button"); const props = ModalFunctions.warpProperties({});
button_yes.text(tr("Yes")); props.template_properties || (props.template_properties = {});
button_yes.click(() => { props.template_properties.text_yes = properties.text_yes || tr("Yes");
modal.close(); props.template_properties.text_no = properties.text_no || tr("No");
callback(true); props.template = "#tmpl_modal_yesno";
});
footer.append(button_yes);
let button_no = $.spawn("button"); props.header = header;
button_no.text(tr("No")); props.template_properties.question = ModalFunctions.jqueriefy(body);
button_no.click(() => {
modal.close();
callback(false);
});
footer.append(button_no);
return footer; const modal = createModal(props);
}, let submited = false;
width: 750 const button_yes = modal.htmlTag.find(".button-yes");
const button_no = modal.htmlTag.find(".button-no");
button_yes.on('click', event => {
if(!submited) {
submited = true;
callback(true);
}
modal.close();
}); });
button_no.on('click', event => {
if(!submited) {
submited = true;
callback(false);
}
modal.close();
});
modal.close_listener.push(() => button_no.trigger('click'));
modal.open(); modal.open();
return modal;
} }
} }

View file

@ -147,7 +147,7 @@ class ChannelTree {
let previous_channel = null; let previous_channel = null;
if(channel.hasParent()) { if(channel.hasParent()) {
let parent = channel.parent_channel(); let parent = channel.parent_channel();
let siblings = parent.siblings(); let siblings = parent.children();
if(siblings.length == 0) { if(siblings.length == 0) {
elm = parent.rootTag(); elm = parent.rootTag();
previous_channel = null; previous_channel = null;
@ -242,7 +242,7 @@ class ChannelTree {
channel.channel_next.channel_previous = channel; channel.channel_next.channel_previous = channel;
} else { } else {
if(parent) { if(parent) {
let siblings = parent.siblings(); let siblings = parent.children();
if(siblings.length <= 1) { //Self should be already in there if(siblings.length <= 1) { //Self should be already in there
let left = channel.rootTag(); let left = channel.rootTag();
left.appendTo(parent.siblingTag()); left.appendTo(parent.siblingTag());
@ -630,7 +630,7 @@ class ChannelTree {
} }
} }
const children = channel.siblings(); const children = channel.children();
if(children.length > 0) { if(children.length > 0) {
this.onSelect(children[0], true); this.onSelect(children[0], true);
return; return;
@ -664,7 +664,7 @@ class ChannelTree {
if(previous) { if(previous) {
while(true) { while(true) {
const siblings = previous.siblings(); const siblings = previous.children();
if(siblings.length == 0) break; if(siblings.length == 0) break;
previous = siblings.last(); previous = siblings.last();
} }
@ -742,4 +742,8 @@ class ChannelTree {
for(const channel of channels) for(const channel of channels)
channel.adjustSize(); channel.adjustSize();
} }
get_first_channel?() : ChannelEntry {
return this.channel_first;
}
} }

View file

@ -1,8 +1,8 @@
$(document).on("mousedown",function (e) { enum ElementType {
if($(e.target).parents("#contextMenu").length == 0 && $(e.target).parents(".modal").length == 0){ HEADER,
$(".modal:visible").last().find(".close").trigger("click"); BODY,
} FOOTER
}); }
type BodyCreator = (() => JQuery | JQuery[] | string) | string | JQuery | JQuery[]; type BodyCreator = (() => JQuery | JQuery[] | string) | string | JQuery | JQuery[];
const ModalFunctions = { const ModalFunctions = {
@ -11,20 +11,22 @@ const ModalFunctions = {
return val; return val;
}, },
jqueriefy: function(val: BodyCreator) : JQuery { jqueriefy: function(val: BodyCreator, type?: ElementType) : JQuery {
if($.isFunction(val)) val = val(); if($.isFunction(val)) val = val();
if($.isArray(val)) { if($.isArray(val)) {
let result = $.spawn("div"); let result = $.spawn("div");
for(let element of val) for(let element of val)
this.jqueriefy(element).appendTo(result); this.jqueriefy(element, type).appendTo(result);
return result; return result;
} }
switch (typeof val){ switch (typeof val){
case "string": return $("<div>" + val + "</div>"); case "string":
if(type == ElementType.HEADER)
return $.spawn("h5").addClass("modal-title").text(val);
return $("<div>" + val + "</div>");
case "object": return val as JQuery; case "object": return val as JQuery;
case "undefined": case "undefined":
console.warn(tr("Got undefined type!")); return undefined;
return $.spawn("div");
default: default:
console.error(("Invalid type %o"), typeof val); console.error(("Invalid type %o"), typeof val);
return $(); return $();
@ -34,8 +36,8 @@ const ModalFunctions = {
warpProperties(data: ModalProperties | any) : ModalProperties { warpProperties(data: ModalProperties | any) : ModalProperties {
if(data instanceof ModalProperties) return data; if(data instanceof ModalProperties) return data;
else { else {
let props = new ModalProperties(); const props = new ModalProperties();
for(let key in data) for(const key of Object.keys(data))
props[key] = data[key]; props[key] = data[key];
return props; return props;
} }
@ -43,6 +45,7 @@ const ModalFunctions = {
}; };
class ModalProperties { class ModalProperties {
template?: string;
header: BodyCreator = () => "HEADER"; header: BodyCreator = () => "HEADER";
body: BodyCreator = () => "BODY"; body: BodyCreator = () => "BODY";
footer: BodyCreator = () => "FOOTER"; footer: BodyCreator = () => "FOOTER";
@ -69,9 +72,14 @@ class ModalProperties {
else else
this.closeListener(); this.closeListener();
} }
template_properties?: any = {};
trigger_tab: boolean = true;
full_size?: boolean = false;
} }
class Modal { class Modal {
private _htmlTag: JQuery; private _htmlTag: JQuery;
properties: ModalProperties; properties: ModalProperties;
shown: boolean; shown: boolean;
@ -89,50 +97,51 @@ class Modal {
} }
private _create() { private _create() {
let modal = $.spawn("div"); const header = ModalFunctions.jqueriefy(this.properties.header, ElementType.HEADER);
modal.addClass("modal"); const body = ModalFunctions.jqueriefy(this.properties.body, ElementType.BODY);
const footer = ModalFunctions.jqueriefy(this.properties.footer, ElementType.FOOTER);
let content = $.spawn("div"); //FIXME: cache template
content.addClass("modal-content"); const template = $(this.properties.template || "#tmpl_modal");
if(this.properties.width)
content.css("width", this.properties.width);
if(this.properties.height)
content.css("height", this.properties.height);
let header = ModalFunctions.divify(ModalFunctions.jqueriefy(this.properties.header)).addClass("modal-header"); const properties = {
if(this.properties.closeable) header.append("<span class=\"close\">&times;</span>"); modal_header: header,
modal_body: body,
modal_footer: footer,
let body = ModalFunctions.divify(ModalFunctions.jqueriefy(this.properties.body)).addClass("modal-body"); closeable: this.properties.closeable,
let footer = ModalFunctions.divify(ModalFunctions.jqueriefy(this.properties.footer)).addClass("modal-footer"); full_size: this.properties.full_size
};
content.append(header); if(this.properties.template_properties)
content.append(body); Object.assign(properties, this.properties.template_properties);
content.append(footer);
modal.append(content); const tag = template.renderTag(properties);
modal.find(".close").click(function () { this._htmlTag = tag;
if(this.properties.closeable) this._htmlTag.on('hide.bs.modal', event => !this.properties.closeable || this.close());
this.close(); this._htmlTag.on('hidden.bs.modal', event => this._htmlTag.detach());
}.bind(this));
this._htmlTag = modal;
} }
open() { open() {
this.shown = true; this.shown = true;
this.htmlTag.appendTo($("body")); this.htmlTag.appendTo($("body"));
this.htmlTag.show();
console.log(this.properties.closeable);
this.htmlTag.bootstrapMaterialDesign().modal(this.properties.closeable ? 'show' : {
backdrop: 'static',
keyboard: false,
});
if(this.properties.trigger_tab)
this.htmlTag.one('shown.bs.modal', () => this.htmlTag.find(".tab").trigger('tab.resize'));
} }
close() { close() {
if(!this.shown) return; if(!this.shown) return;
this.shown = false; this.shown = false;
const _this = this; this.htmlTag.modal('hide');
this.htmlTag.animate({opacity: 0}, () => {
_this.htmlTag.detach();
});
this.properties.triggerClose(); this.properties.triggerClose();
for(const listener of this.close_listener) for(const listener of this.close_listener)
listener(); listener();
@ -144,107 +153,152 @@ function createModal(data: ModalProperties | any) : Modal {
} }
class InputModalProperties extends ModalProperties { class InputModalProperties extends ModalProperties {
maxLength: number; maxLength?: number;
field_title?: string;
field_label?: string;
field_placeholder?: string;
error_message?: string;
} }
function createInputModal(headMessage: BodyCreator, question: BodyCreator, validator: (input: string) => boolean, callback: (flag: boolean | string) => void, props: InputModalProperties | any = {}) : Modal { function createInputModal(headMessage: BodyCreator, question: BodyCreator, validator: (input: string) => boolean, callback: (flag: boolean | string) => void, props: InputModalProperties | any = {}) : Modal {
props = ModalFunctions.warpProperties(props); props = ModalFunctions.warpProperties(props);
props.template_properties || (props.template_properties = {});
props.template_properties.field_title = props.field_title;
props.template_properties.field_label = props.field_label;
props.template_properties.field_placeholder = props.field_placeholder;
props.template_properties.error_message = props.error_message;
let head = $.spawn("div"); props.template = "#tmpl_modal_input";
head.css("border-bottom", "grey solid");
head.css("border-width", "1px");
ModalFunctions.jqueriefy(headMessage).appendTo(head);
props.header = headMessage;
props.template_properties.question = ModalFunctions.jqueriefy(question);
let body = $.spawn("div"); const modal = createModal(props);
ModalFunctions.divify(ModalFunctions.jqueriefy(question)).appendTo(body);
let input = $.spawn("input");
input.css("width", "100%");
input.appendTo(body);
console.log(input);
let footer = $.spawn("div"); const input = modal.htmlTag.find(".container-value input");
footer.addClass("modal-button-group"); const button_cancel = modal.htmlTag.find(".button-cancel");
footer.css("margin-top", "5px"); const button_submit = modal.htmlTag.find(".button-submit");
let buttonCancel = $.spawn("button"); let submited = false;
buttonCancel.text("Cancel"); input.on('keyup change', event => {
const str = input.val() as string;
const valid = str !== undefined && validator(str);
let buttonOk = $.spawn("button"); input.attr("pattern", valid ? null : "^[a]{1000}$").toggleClass("is-invalid", !valid);
buttonOk.text("Ok"); button_submit.prop("disabled", !valid);
footer.append(buttonCancel);
footer.append(buttonOk);
input.on("keydown", function (event) {
if(event.keyCode == JQuery.Key.Enter) {
buttonOk.trigger("click");
}
}); });
let updateValidation = function () { button_submit.on('click', event => {
let text = input.val().toString(); if(!submited) {
let flag = (!props.maxLength || text.length <= props.maxLength) && validator(text); submited = true;
if(flag) { const str = input.val() as string;
input.removeClass("invalid_input"); if(str !== undefined && validator(str))
buttonOk.removeAttr("disabled"); callback(str);
} else { else
if(!input.hasClass("invalid_input")) callback(false);
input.addClass("invalid_input");
buttonOk.attr("disabled", "true");
} }
};
input.on("keyup", updateValidation);
let callbackCalled = false;
let wrappedCallback = function (flag: boolean | string) {
if(callbackCalled) return;
callbackCalled = true;
callback(flag);
};
let modal;
buttonOk.on("click", () => {
wrappedCallback(input.val().toString());
modal.close(); modal.close();
}); }).prop("disabled", !validator("")); /* disabled if empty input isn't allowed */
buttonCancel.on("click", () => {
wrappedCallback(false); button_cancel.on('click', event => {
if(!submited) {
submited = true;
callback(false);
}
modal.close(); modal.close();
}); });
props.header = head; modal.close_listener.push(() => button_cancel.trigger('click'));
props.body = body;
props.footer = footer;
props.closeListener = () => wrappedCallback(false);
modal = createModal(props);
return modal; return modal;
} }
function createErrorModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: "" }) { function createErrorModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: undefined }) {
props = ModalFunctions.warpProperties(props); props = ModalFunctions.warpProperties(props);
(props.template_properties || (props.template_properties = {})).header_class = "modal-header-error";
let head = $.spawn("div"); props.header = header;
head.addClass("modal-head-error"); props.body = message;
ModalFunctions.divify(ModalFunctions.jqueriefy(header)).appendTo(head); return createModal(props);
props.header = head; }
props.body = $.spawn("div").append(ModalFunctions.divify(ModalFunctions.jqueriefy(message))); function createInfoModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: undefined }) {
props.footer = ModalFunctions.divify(ModalFunctions.jqueriefy("")); props = ModalFunctions.warpProperties(props);
(props.template_properties || (props.template_properties = {})).header_class = "modal-header-info";
props.header = header;
props.body = message;
return createModal(props); return createModal(props);
} }
function createInfoModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any = { footer: "" }) { /* extend jquery */
props = ModalFunctions.warpProperties(props);
interface ModalElements {
header?: BodyCreator;
body?: BodyCreator;
footer?: BodyCreator;
}
interface JQuery<TElement = HTMLElement> {
modalize(entry_callback?: (header: JQuery, body: JQuery, footer: JQuery) => ModalElements | void, properties?: ModalProperties | any) : Modal;
}
$.fn.modalize = function (this: JQuery, entry_callback?: (header: JQuery, body: JQuery, footer: JQuery) => ModalElements | void, properties?: ModalProperties | any) : Modal {
properties = properties || {} as ModalProperties;
entry_callback = entry_callback || ((a,b,c) => undefined);
let tag_modal = this[0].tagName.toLowerCase() == "modal" ? this : undefined; /* TODO may throw exception? */
let tag_head = tag_modal ? tag_modal.find("modal-header") : ModalFunctions.jqueriefy(properties.header);
let tag_body = tag_modal ? tag_modal.find("modal-body") : this;
let tag_footer = tag_modal ? tag_modal.find("modal-footer") : ModalFunctions.jqueriefy(properties.footer);
const result = entry_callback(tag_head, tag_body, tag_footer) || {};
properties.header = result.header || tag_head;
properties.body = result.body || tag_body;
properties.footer = result.footer || tag_footer;
return createModal(properties);
};
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

@ -43,6 +43,28 @@ var TabFunctions = {
let silentContent = $.spawn("div"); let silentContent = $.spawn("div");
silentContent.addClass("tab-content-invisible"); silentContent.addClass("tab-content-invisible");
/* add some kind of min height */
const update_height = () => {
const entries: JQuery = tag.find("> .tab-content-invisible x-content, > .tab-content x-content");
console.error(entries);
let max_height = 0;
entries.each((_, _e) => {
const entry = $(_e);
const height = entry.visible_height();
if(height > max_height)
max_height = height;
});
console.error("HIGHT: " + max_height);
entries.each((_, _e) => {
const entry = $(_e);
entry.animate({
'min-height': max_height + "px"
}, 250);
})
};
template.find("x-entry").each( (_, _entry) => { template.find("x-entry").each( (_, _entry) => {
const entry = $(_entry); const entry = $(_entry);
@ -74,6 +96,7 @@ var TabFunctions = {
}; };
show_next(0); show_next(0);
tag_content.trigger('show');
tag_content.show(); tag_content.show();
}); });
@ -81,11 +104,13 @@ var TabFunctions = {
header.append(tag_header); header.append(tag_header);
}); });
header.find(".entry").first().trigger("click"); setTimeout(() => header.find(".entry").first().trigger("click"), 0);
tag.append(header); tag.append(header);
tag.append(content); tag.append(content);
tag.append(silentContent); tag.append(silentContent);
tag.on('tab.resize', update_height);
return tag; return tag;
} }
} }
@ -101,14 +126,12 @@ if(!$.fn.asTabWidget) {
} }
if(!$.fn.tabify) { if(!$.fn.tabify) {
$.fn.tabify = function (copy?: boolean) { $.fn.tabify = function (this: JQuery, copy?: boolean) {
try { const wrapped_tag = $.spawn("div").append(this);
let self = this.asTabWidget(copy); wrapped_tag.find("x-tab").each((_, _element) => {
this.replaceWith(self); const element = $(_element);
} catch(object) {} element.replaceWith(element.asTabWidget(copy));
this.find("x-tab").each(function () {
$(this).replaceWith($(this).asTabWidget(copy));
}); });
return this; return wrapped_tag.children();
} }
} }

2
vendor/bbcode vendored

@ -1 +1 @@
Subproject commit 0c9d48b2e1d37ddefa6bafb3e2d0c7d04ad4dac6 Subproject commit 23f9aca6b6dc1ffccd20d6da04953776a1882f2b

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,342 +0,0 @@
/*!
* Bootstrap Reboot v4.0.0-beta.2 (https://getbootstrap.com)
* Copyright 2011-2017 The Bootstrap Authors
* Copyright 2011-2017 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-ms-overflow-style: scrollbar;
-webkit-tap-highlight-color: transparent;
}
@-ms-viewport {
width: device-width;
}
article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}
[tabindex="-1"]:focus {
outline: none !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
dfn {
font-style: italic;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]):not([tabindex]) {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus {
outline: 0;
}
pre,
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
-ms-overflow-style: scrollbar;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg:not(:root) {
overflow: hidden;
}
a,
area,
button,
[role="button"],
input:not([type="range"]),
label,
select,
summary,
textarea {
-ms-touch-action: manipulation;
touch-action: manipulation;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #868e96;
text-align: left;
caption-side: bottom;
}
th {
text-align: inherit;
}
label {
display: inline-block;
margin-bottom: .5rem;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
html [type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

View file

@ -1,8 +0,0 @@
/*!
* Bootstrap Reboot v4.0.0-beta.2 (https://getbootstrap.com)
* Copyright 2011-2017 The Bootstrap Authors
* Copyright 2011-2017 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input:not([type=range]),label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long