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

View file

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

View file

@ -50,7 +50,7 @@
}
/* The Modal (background) */
.modal {
.modal_disabled {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
@ -61,74 +61,74 @@
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Header */
.modal-header {
padding: 2px 16px;
min-height: 30px;
vertical-align: middle;
display: flex;
align-items: center;
/* Modal Header */
.modal-header {
padding: 2px 16px;
min-height: 30px;
vertical-align: middle;
display: flex;
align-items: center;
border: grey solid;
border-width: 0 0 1px 0;
border: grey solid;
border-width: 0 0 1px 0;
background-color: lightgreen;
}
background-color: lightgreen;
}
/* Modal Body */
.modal-body:not(:empty) {
display: flex;
padding: 2px 16px;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
}
/* Modal Body */
.modal-body:not(:empty) {
display: flex;
padding: 2px 16px;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
}
/* Modal Footer */
.modal-footer:not(:empty) {
padding: 2px 16px;
}
/* Modal Footer */
.modal-footer:not(:empty) {
padding: 2px 16px;
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
position: absolute;
top: 0px;
right: 4px;
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
position: absolute;
top: 0px;
right: 4px;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
/* Modal Content */
.modal-content:not(:empty) {
position: absolute;
display: inline-flex;
flex-direction: column;
justify-content: stretch;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 2px solid #888;
width: auto;
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);
animation-name: modalFlyIn;
animation-duration: 0.4s;
top: 10%;
max-height: 80%;
/* Modal Content */
.modal-content:not(:empty) {
position: absolute;
display: inline-flex;
flex-direction: column;
justify-content: stretch;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 2px solid #888;
width: auto;
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);
animation-name: modalFlyIn;
animation-duration: 0.4s;
top: 10%;
max-height: 80%;
left: 0;
right: 0;
left: 0;
right: 0;
}
}
/* Add Animation */
@ -191,50 +191,6 @@ fieldset {
border-width: 2px;
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 {
background-color: lightgray;
padding: 2px;
@ -378,6 +334,11 @@ html, body {
overflow: hidden;
}
body {
padding: 8px;
background: darkgray!important;
}
.icon-playlist-manage {
display: inline-block;
width: 32px;
@ -393,4 +354,9 @@ x-content {
flex-shrink: 1;
display: flex;
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;
flex-direction: column;
.container {
display: block;
flex-shrink: 0;
select.form-control {
height: 2rem!important;
}
.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;
a {
display: block;
}
input, textarea {
width: 100%;
}
textarea {
resize: vertical;
max-height: 100%;
overflow-y: auto;
}
&:not(:first-of-type) {
margin-top: 5px;
}
flex-shrink: 0;
&.container-reason {
max-height: 500px;
display: flex;
flex-direction: column;
}
flex-grow: 1;
flex-shrink: 1;
.container-name-type {
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;
overflow-y: auto;
}
}

View file

@ -38,104 +38,113 @@
}
.entry-container {
display: inline-flex;
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
margin-bottom: 5px;
position: relative;
width: 100%;
height: 100%;
.table-container {
.entries {
width: 100%;
}
min-height: 300px;
.ban-entry.selected {
background: blue;
}
overflow-y: scroll;
overflow-x: hidden;
.ban-entry-global {
color: red;
display: flex;
flex-direction: column;
}
.ban-entry {
.field-properties {
a {
display: block;
flex-grow: 0;
flex-shrink: 0;
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;
white-space: pre-wrap;
&:not(.header) {
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 {
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 {
@ -159,6 +168,13 @@
input {
vertical-align: bottom;
}
.bmd-form-group {
padding-top: 0;
align-self: center;
margin-left: 20px;
}
}
}
}

View file

@ -105,6 +105,17 @@
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 {
/*
margin-top: 5px;
> div:not(:first-of-type) {
@ -27,4 +29,45 @@
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;
flex-direction: column;
.container {
.header, .footer {
flex-grow: 0;
flex-shrink: 0;
}
.header {
display: flex;
flex-direction: row;
justify-content: stretch;
.buttons {
flex-grow: 0;
}
.search {
margin-left: 5px;
flex-grow: 1;
input {
width: 100%;
}
}
}
.playlist-list {
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
.header, .footer {
flex-grow: 0;
flex-shrink: 0;
$width_id: 80px;
$width_type: 150px;
$width_used: 40px;
.column {
&.column-id {
width: 80px;
text-align: center;
}
&.column-title {
width: calc(50% - 95px - 40px);
}
&.column-creator {
width: calc(50% - 95px - 40px);
text-align: center;
}
&.column-type {
width: 150px;
flex-grow: 0;
text-align: center;
}
&.column-used {
width: 40px;
flex-grow: 0;
text-align: center;
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
}
}
.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;
flex-direction: row;
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;
}
.search {
margin-left: 5px;
.value {
flex-grow: 1;
flex-shrink: 1;
}
.checkbox-container {
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;
display: flex;
@ -41,49 +249,51 @@
flex-direction: column;
justify-content: stretch;
$width_id: 80px;
$width_type: 150px;
$width_used: 40px;
.column {
&.column-id {
width: 80px;
text-align: center;
width: 50px;
}
&.column-title {
width: calc(50% - 95px - 40px);
&.column-url {
width: calc(100% - 140px)
}
&.column-creator {
width: calc(50% - 95px - 40px);
text-align: center;
}
&.column-type {
width: 150px;
&.column-loaded {
width: 50px;
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;
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-shrink: 0;
display: flex;
flex-direction: row;
height: 20px;
justify-content: center;
.column {
border: 1px solid lightgray;
@ -91,7 +301,7 @@
}
}
.playlist-list-entries-container {
.song-list-entries-container {
flex-grow: 1;
display: flex;
flex-direction: column;
@ -113,269 +323,37 @@
background-color: blue;
}
&.highlighted {
font-weight: bold;
&.playing {
background-color: lightgreen;
}
}
&.scrollbar {
.column-title {
width: calc(50% - 95px - 40px + 30px)
}
.column-creator {
width: calc(50% - 95px - 40px + 30px)
&.column-url {
width: calc(100% - 140px + 30px)
}
}
}
}
.footer {
margin-top: 5px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.buttons {
display: flex;
flex-direction: row;
justify-content: stretch;
.highlight-own {
display: flex;
flex-direction: row;
justify-content: stretch;
margin-right: 10px;
align-self: center;
}
}
flex-grow: 0;
flex-shrink: 0;
margin-top: 5px;
}
}
}
.playlist-edit {
display: flex;
flex-direction: column;
justify-content: stretch;
> .buttons {
margin-top: 5px;
align-self: flex-end;
.container {
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;
}
.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;
}
button {
width: 100px;
}
}
}

View file

@ -26,35 +26,28 @@
display: flex;
flex-direction: column;
.property-row {
width: 100%;
.buttons {
text-align: right;
}
.form-row {
margin-right: 0!important;
margin-left: 0!important;
display: flex;
flex-direction: row;
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;
}
}
.buttons {
margin-top: 5px;
text-align: right;
.form-group {
flex-grow: 1;
}
}
}
@ -63,111 +56,104 @@
display: flex;
flex-direction: column;
.container {
.header, .footer {
flex-grow: 0;
flex-shrink: 0;
}
.header {
display: flex;
flex-direction: row;
justify-content: stretch;
.buttons {
flex-grow: 0;
}
.search {
margin-left: 5px;
flex-grow: 1;
input {
width: 100%;
}
}
}
.query-list {
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column;
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-shrink: 0;
}
.header {
display: flex;
flex-direction: row;
justify-content: stretch;
.buttons {
flex-grow: 0;
}
.search {
margin-left: 5px;
flex-grow: 1;
input {
width: 100%;
}
}
}
.query-list {
margin-top: 5px;
display: flex;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
.column {
&.column-username {
width: calc(50% - 75px)
}
&.column-unique-id {
width: calc(50% - 75px)
}
&.column-bound-server {
width: 150px;
flex-grow: 0;
}
border: 1px solid lightgray;
text-align: center;
}
}
.query-list-header {
flex-grow: 0;
flex-shrink: 0;
.query-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;
height: 20px;
.column {
border: 1px solid lightgray;
text-align: center;
margin-left: 2px;
}
cursor: pointer;
&.selected {
background-color: blue;
}
}
.query-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;
}
&.scrollbar {
.column-username {
width: calc(50% - 75px + 30px)
}
&.scrollbar {
.column-username {
width: calc(50% - 75px + 30px)
}
.column-unique-id {
width: calc(50% - 75px + 30px)
}
.column-unique-id {
width: calc(50% - 75px + 30px)
}
}
}
.footer {
margin-top: 5px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
.footer {
margin-top: 5px;
display: flex;
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 {
display: flex;
flex-direction: column;
@ -7,6 +10,7 @@
user-select: none;
margin: 3px;
> div {
margin: 2px;
}
@ -15,6 +19,10 @@
align-self: center;
}
.settings-device-error {
display: none;
}
.group_box {
display: flex;
flex-direction: column;
@ -24,7 +32,7 @@
flex-shrink: 1;
.content {
display: flex;
display: block;
flex-direction: column;
}
}
@ -32,34 +40,19 @@
.settings-device {
display: flex;
flex-direction: column;
width: 100%;
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;
}
flex-direction: row;
justify-items: stretch;
.settings-device-select {
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: row;
justify-content: stretch;
margin-right: 5px;
> div {
flex-grow: 1;
flex-shrink: 1;
@ -75,11 +68,35 @@
.settings-vad-container {
display: flex;
flex-direction: row;
margin-top: 5px;
min-height: 150px;
flex-direction: column;
width: 100%;
> 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 {
@ -94,6 +111,12 @@
}
.settings-vad-impl {
.setting-vad-ppt {
@media (min-width: $small_device) {
margin-bottom: -35px;
}
}
display: flex;
justify-content: space-around;
padding: 5px;
@ -105,6 +128,74 @@
.settings-vad-impl-entry {
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 {
@ -116,8 +207,19 @@
margin-right: 5px;
}
&.ppt-key {
.key {
align-self: center;
}
button {
min-width: 100px;
}
}
&.ppt-delay {
margin-top: 5px;
.value {
display: inline-block;
position: relative;
@ -156,11 +258,14 @@
justify-content: stretch;
.key {
width: 150px;
/*
width: 250px;
&.muted-sounds {
width: 230px;
}
*/
margin-right: 10px;
}
.value {
@ -182,6 +287,19 @@
text-align: right;
}
}
.bmd-form-group {
padding: 0;
label {
margin: 0;
top: -7px;
}
.bmd-switch-track {
top: 0;
}
}
}
}
@ -202,8 +320,17 @@
width: 150px;
flex-grow: 0;
input {
margin-left: 75px;
.bmd-form-group {
padding: 0;
label {
margin: 0 0 0 75px;
top: -7px;
}
.bmd-switch-track {
top: 0;
}
}
}
}
@ -213,7 +340,7 @@
flex-shrink: 0;
display: flex;
flex-direction: row;
height: 20px;
align-items: center;
.column {
border: 1px solid lightgray;
@ -264,6 +391,7 @@
}
}
/*
.sound-list-filter {
margin-top: 3px;
@ -280,11 +408,13 @@
margin-right: 8px;
}
}
*/
}
}
.modal .settings-translations {
margin: 5px;
.setting-list {
user-select: none;
@ -311,7 +441,8 @@
flex-direction: row;
justify-content: stretch;
.default { }
.default {
}
.name {
flex-grow: 1;
@ -423,6 +554,7 @@
display: flex;
flex-direction: column;
}
.contributor {
display: block;
}
@ -508,6 +640,7 @@
.modal .settings-profiles {
margin: 5px;
> div:not(:first-of-type) {
margin-top: 5px;
}
@ -620,10 +753,6 @@
flex-grow: 1;
flex-shrink: 1;
}
.select-container {
text-align: right;
}
}
}
@ -643,6 +772,26 @@
}
&.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 {
&:not(:first-of-type) {
margin-top: 5px;
@ -664,18 +813,6 @@
width: 100%;
}
}
&.level {
.value {
display: flex;
flex-direction: row;
justify-content: stretch;
button {
margin-left: 5px;
}
}
}
}
.identity-undefined {
@ -739,45 +876,15 @@
display: flex;
flex-direction: column;
.property {
&:not(:first-of-type) {
margin-top: 5px;
}
.bmd-label-static {
display: flex;
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 {
display: flex;
flex-direction: row;
.form-row {
margin-right: 0!important;
margin-left: 0!important;
justify-content: space-between;
.property {
margin-top: 0px;
}
}
.buttons {
@ -787,7 +894,7 @@
flex-direction: row;
justify-content: space-between;
button {
button {
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 {
//General style
.properties {
@ -13,42 +31,12 @@
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 {
border-radius: 1px;
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 {
.complains {
display: grid;
@ -62,34 +50,78 @@
.container {
padding: 6px;
}
}
.modal-dialog {
max-height: 80%;
display: flex;
flex-direction: column;
justify-content: stretch;
.container-file-transfer {
.settings {
.setting {
&.modal-dialog-centered {
justify-content: space-around;
}
}
.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;
flex-direction: row;
justify-content: stretch;
flex-direction: column;
&:not(:first-of-type) {
margin-top: 5px;
input.is-invalid {
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 {
flex-grow: 0;
&.suffix {
width: 50px;
margin-left: 5px;
&.modal-body-input {
.form-group:not(.with-title) {
padding-top: .75rem;
}
&:first-of-type {
width: 130px;
input.is-invalid ~ .container-help-feedback > .invalid-feedback {
display: block;
}
.container-help-feedback {
position: absolute;
}
}
}
input {
flex-grow: 1;
.modal-footer {
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;
}
.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 {
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-list {
border: lightgray solid 1px;

View file

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

View file

@ -9,101 +9,115 @@
flex-direction: column;
flex-grow: 1;
}
#chat div {
vertical-align: middle;
}
div, a {
vertical-align: middle;
}
#chat .messages {
border-color: #6f6f6f;
border-radius: 2px 2px 2px 0px;
border-style: solid;
overflow-y: auto;
flex-grow: 1;
}
.messages {
border-color: #6f6f6f;
border-radius: 2px 2px 2px 0;
border-style: solid;
overflow-y: auto;
flex-grow: 1;
#chat .message_box {
flex-wrap: wrap;
display: flex;
align-items: flex-start;
height: auto;
}
.message_box {
flex-wrap: wrap;
display: flex;
align-items: flex-start;
height: auto;
#chat .message {
width: 100%;
display: inline-block;
}
.message {
width: 100%;
display: inline-block;
#chat .message *{
display: inline-block;
vertical-align: top;
}
* {
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;
}
.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 .active {
background: #11111111;
}
.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;
#chat a {
vertical-align: middle;
}
&.active {
background: #11111111;
}
#chat .btn_close {
float: none;
margin-right: -5px;
margin-left: 8px;
}
.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;
}
&:hover, &:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
}
}
}
#chat .input {
width: 100%;
margin-top: 2px;
display: flex;
height: auto;
position: relative;
flex-shrink: 0;
}
.input {
display: flex;
flex-direction: row;
justify-content: stretch;
#chat .input .input_box {
width: 100%;
height: auto;
width: 100%;
margin-top: 2px;
position: relative;
flex-shrink: 0;
display:inline-block;
border: solid 1px #000;
height: 22px;
min-height: 22px;
max-height: 80px;
overflow-y: auto;
resize: vertical;
.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;
}
}
}

View file

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

View file

@ -32,6 +32,8 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<?php
if(!$WEB_CLIENT) {
echo "<title>TeaClient</title>";
@ -51,12 +53,15 @@
<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-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-playlist.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-settings.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/music/info_plate.css" type="text/css">
<link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css">
@ -100,6 +105,15 @@
gtag('js', new Date());
gtag('config', 'UA-113151733-4');
</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>
//const exports = {};
</script>

File diff suppressed because it is too large Load diff

View file

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

View file

@ -1,5 +1,8 @@
let context_menu: JQuery;
$(document).bind("mousedown", function (e) {
let menu = $(".context-menu");
let menu = context_menu || (context_menu = $(".context-menu"));
if(!menu.is(":visible")) return;
if ($(e.target).parents(".context-menu").length == 0) {
@ -9,7 +12,8 @@ $(document).bind("mousedown", function (e) {
let contextMenuCloseFn = undefined;
function despawn_context_menu() {
let menu = $(".context-menu");
let menu = context_menu || (context_menu = $(".context-menu"));
if(!menu.is(":visible")) return;
menu.hide(100);
if(contextMenuCloseFn) contextMenuCloseFn();
@ -102,7 +106,9 @@ function generate_tag(entry: ContextMenuEntry) : JQuery {
}
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;
for(let entry of entries){

View file

@ -261,7 +261,7 @@ const loader_javascript = {
*/
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_scripts([

View file

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

View file

@ -346,6 +346,11 @@ class PermissionInfo {
name: string;
id: number;
description: string;
is_boolean() { return this.name.startsWith("b_"); }
id_grant() : number {
return this.id | (1 << 15);
}
}
class PermissionGroup {
@ -369,7 +374,7 @@ class PermissionValue {
flag_negate: boolean;
granted_value: number;
constructor(type, value) {
constructor(type, value?) {
this.type = type;
this.value = value;
}
@ -382,7 +387,10 @@ class PermissionValue {
}
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[] {
let permissions: PermissionValue[] = [];
for(let perm of json) {
if(perm["permid"] === undefined) continue;
let perm_id = parseInt(perm["permid"]);
let perm_grant = (perm_id & (1 << 15)) > 0;
if(perm_grant)

View file

@ -580,7 +580,7 @@ namespace profiles.identities {
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)
throw "not initialized";
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;
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 {
result = await new Promise<boolean>((resolve, reject) => {
let active = true;
@ -644,6 +662,8 @@ namespace profiles.identities {
const promise = worker.mine(next_hash(), iterations, target_level);
const p = promise.then(result => {
update_hashrate();
worker_promise.remove(p);
if(result.valueOf()) {

View file

@ -14,6 +14,14 @@ interface JQuery<TElement = HTMLElement> {
render(values?: any) : string;
renderTag(values?: any) : JQuery<TElement>;
hasScrollBar() : boolean;
visible_height() : number;
/* bootstrap */
alert() : JQuery<TElement>;
modal(properties: any) : this;
bootstrapMaterialDesign() : this;
}
interface JQueryStatic<TElement extends Node = HTMLElement> {
@ -133,6 +141,20 @@ if(typeof ($) !== "undefined") {
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) {

View file

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

View file

@ -511,7 +511,6 @@ class MusicInfoManager extends ClientInfoManager {
}).catch(error => {
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"),
body: () => {
let template = $("#tmpl_ban_create").renderTag();
template = $.spawn("div").append(template);
const input_name = template.find(".input-name");
const input_name_type = template.find(".input-name-type");

View file

@ -180,10 +180,9 @@ namespace Modals {
header: tr("Banlist"),
body: () => {
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"));
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-refresh").on('click', () => callback_update());
return template;
@ -195,17 +194,18 @@ namespace Modals {
modal.open();
modal.close_listener.push(() => entries = []);
const template_entry = $("#tmpl_ban_entry");
result.addbans = (bans: BanEntry[]) => {
for(const entry of bans) {
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");
update_function();
};
result.clear = () => {
entries = [];
modal.htmlTag.find(".ban-entry-list").children().detach();
modal.htmlTag.find(".entry-container .entries").children().detach();
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 {
const update = () => {
console.log(elements.find("tr.selected").length);
$(".button-edit, .button-remove").prop("disabled", elements.find("tr.selected").length == 0);
console.log(elements.find(".ban-entry.selected").length);
$(".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-edit").on('click', event => {
const selected = elements.find("tr.selected");
const selected = elements.find(".ban-entry.selected");
if(!selected) return;
cb_edit(parseInt(selected.attr("ban-id")));
});
tag.find(".button-remove").on('click', event => {
const selected = elements.find("tr.selected");
const selected = elements.find(".ban-entry.selected");
if(!selected) return;
cb_delete(parseInt(selected.attr("ban-id")));
});
const element_selected = element => {
elements.find("tr").removeClass("selected");
elements.find(".ban-entry").removeClass("selected");
if(element.is(":visible"))
element.addClass("selected");
@ -296,7 +296,7 @@ namespace Modals {
};
return () => {
elements.find("tr").each((_idx, _entry) => {
elements.find(".ban-entry").each((_idx, _entry) => {
_entry.addEventListener("click", click_handler);
_entry.addEventListener("contextmenu", context_handler)
});

View file

@ -3,102 +3,123 @@
namespace Modals {
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;
const connectModal = createModal({
header: function() {
let header = $.spawn("div");
header.text(tr("Create a new connection"));
return header;
},
body: function () {
let tag = $("#tmpl_connect").renderTag({
client: native_client,
forum_path: settings.static("forum_path")
const random_id = (() => {
const array = new Uint32Array(10);
window.crypto.getRandomValues(array);
return array.join("");
})();
const connect_modal = $("#tmpl_connect").renderTag({
client: native_client,
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 () {
if(selected_profile) tag.find(".connect_nickname").attr("placeholder", selected_profile.default_username);
else
tag.find(".connect_nickname").attr("");
let button = tag.parents(".modal-content").find(".connect_connect_button");
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;
button_manage.on('click', event => {
const modal = Modals.spawnSettingsModal();
setTimeout(() => {
modal.htmlTag.find(".tab-profiles").parent(".entry").trigger('click');
}, 100);
modal.close_listener.push(() => {
input_profile.trigger('change');
});
return true;
});
{
const select_tag = tag.find(".profile-select-container select");
const select_invalid_tag = tag.find(".profile-invalid");
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');
{
for(const profile of profiles.profiles()) {
input_profile.append(
$.spawn("option").text(profile.profile_name).val(profile.id)
);
}
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
return tag;
},

View file

@ -10,7 +10,6 @@ namespace Modals {
channel_flag_maxfamilyclients_unlimited: true,
channel_flag_maxclients_unlimited: true
} as ChannelProperties);
template = $.spawn("div").append(template);
return template.tabify();
},
footer: () => {
@ -36,7 +35,7 @@ namespace Modals {
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);
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);
let updated: PermissionValue[] = [];
@ -144,11 +143,11 @@ namespace Modals {
properties.channel_flag_default = this.checked;
let elements = tag.find("input[name=\"channel_type\"]");
elements.prop("disabled", this.checked);
if(this.checked) {
elements.prop("enabled", false);
elements.prop("checked", false);
tag.find("input[name=\"channel_type\"][value=\"perm\"]").prop("checked", true).trigger("change");
} else elements.removeProp("enabled");
}
}).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_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));
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);
orderTag.change(function (this: HTMLSelectElement) {
@ -176,7 +175,7 @@ namespace Modals {
for(let cperm of channel_permissions)
if(cperm.type.name == PermissionType.I_CHANNEL_NEEDED_MODIFY_POWER) {
required_power = cperm.value;
return;
break;
}
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)) {
tag.find("input[permission]").prop("enabled", false); //No permissions
tag.find("input[permission]").prop("disabled", false); //No permissions
}
};
if(channel) {
permissions.requestChannelPermissions(channel.getChannelId()).then(apply_permissions).catch((error) => {
tag.find("input[permission]").prop("enabled", false);
console.log(error);
tag.find("input[permission]").prop("disabled", true);
console.log("Failed to receive channel permissions (%o)", error);
});
} 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"),
body: () => {
let template = $("#tmpl_playlist_edit").renderTag().tabify();
template = $.spawn("div").append(template);
callback_permission_update = apply_permissions(template, client, playlist, (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;
client.serverConnection.helper.request_playlist_info(playlist.playlist_id).then(info => {
tag.find(".property-owner .value")
.text(info.playlist_owner_name + " (" + info.playlist_owner_dbid + ")");
tag.find(".property-owner input")
.val(info.playlist_owner_name + " (" + info.playlist_owner_dbid + ")");
tag.find(".property-title input")
.val(info.playlist_title)
@ -337,8 +336,8 @@ namespace Modals {
change_property("playlist_flag_delete_played", (<HTMLInputElement>event.target).checked ? "1" : "0");
});
tag.find(".property-current-song .value")
.text(info.playlist_current_song_id);
tag.find(".property-current-song input")
.val(info.playlist_current_song_id);
callback_current_song(info.playlist_current_song_id);
tag.find(".property-flag-finished input")

View file

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

View file

@ -54,10 +54,10 @@ namespace Modals {
export function spawnQueryCreated(credentials: {
username: string,
password: string
}, yust_created: boolean) {
}, just_created: boolean) {
let modal;
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: () => {
let template = $("#tmpl_query_created").renderTag(credentials);
template = $.spawn("div").append(template);

View file

@ -3,35 +3,17 @@
namespace Modals {
export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => any) {
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");
buttonCancel.text(tr("Cancel")).addClass("button_cancel");
let buttonOk = $.spawn("button");
buttonOk.text(tr("Ok")).addClass("button_ok");
footer.append(buttonCancel);
footer.append(buttonOk);
return footer;
},
width: 750
const modal_template = $("#tmpl_server_edit").renderTag(server.properties);
const modal = modal_template.modalize((header, body, footer) => {
return {
body: body.tabify()
}
});
server_applyGeneralListener(properties, modal.htmlTag.find(".properties_general"), modal.htmlTag.find(".button_ok"));
server_applyTransferListener(properties, server, modal.htmlTag.find('.container-file-transfer'));
server_applyHostListener(properties, server.properties, modal.htmlTag.find(".properties_host"), modal.htmlTag.find(".button_ok"));
server_applyTransferListener(properties, server, modal.htmlTag.find('.properties_transfer'));
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_applyFlood(properties, server, modal.htmlTag.find(".properties_flood"));
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) {
properties.virtualserver_host = this.value;
}).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;
}).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) {

View file

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

View file

@ -1,38 +1,44 @@
/// <reference path="../../utils/modal.ts" />
namespace Modals {
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any) {
let modal;
modal = createModal({
header: header,
body: body,
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");
export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: {
text_yes?: string,
text_no?: string
}) {
properties = properties || {};
let button_yes = $.spawn("button");
button_yes.text(tr("Yes"));
button_yes.click(() => {
modal.close();
callback(true);
});
footer.append(button_yes);
const props = ModalFunctions.warpProperties({});
props.template_properties || (props.template_properties = {});
props.template_properties.text_yes = properties.text_yes || tr("Yes");
props.template_properties.text_no = properties.text_no || tr("No");
props.template = "#tmpl_modal_yesno";
let button_no = $.spawn("button");
button_no.text(tr("No"));
button_no.click(() => {
modal.close();
callback(false);
});
footer.append(button_no);
props.header = header;
props.template_properties.question = ModalFunctions.jqueriefy(body);
return footer;
},
width: 750
const modal = createModal(props);
let submited = false;
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();
return modal;
}
}

View file

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

View file

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

View file

@ -43,6 +43,28 @@ var TabFunctions = {
let silentContent = $.spawn("div");
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) => {
const entry = $(_entry);
@ -74,6 +96,7 @@ var TabFunctions = {
};
show_next(0);
tag_content.trigger('show');
tag_content.show();
});
@ -81,11 +104,13 @@ var TabFunctions = {
header.append(tag_header);
});
header.find(".entry").first().trigger("click");
setTimeout(() => header.find(".entry").first().trigger("click"), 0);
tag.append(header);
tag.append(content);
tag.append(silentContent);
tag.on('tab.resize', update_height);
return tag;
}
}
@ -101,14 +126,12 @@ if(!$.fn.asTabWidget) {
}
if(!$.fn.tabify) {
$.fn.tabify = function (copy?: boolean) {
try {
let self = this.asTabWidget(copy);
this.replaceWith(self);
} catch(object) {}
this.find("x-tab").each(function () {
$(this).replaceWith($(this).asTabWidget(copy));
$.fn.tabify = function (this: JQuery, copy?: boolean) {
const wrapped_tag = $.spawn("div").append(this);
wrapped_tag.find("x-tab").each((_, _element) => {
const element = $(_element);
element.replaceWith(element.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