save
This commit is contained in:
parent
3b3430db5e
commit
63683eadba
27 changed files with 1322 additions and 578 deletions
46
files.php
46
files.php
|
@ -316,12 +316,50 @@
|
|||
]
|
||||
];
|
||||
|
||||
$CERTACCEPT_FILE_LIST = [
|
||||
[ /* html files */
|
||||
"type" => "html",
|
||||
"search-pattern" => "/^([a-zA-Z]+)\.(html|php|json)$/",
|
||||
"build-target" => "dev|rel",
|
||||
|
||||
"path" => "./popup/certaccept/",
|
||||
"local-path" => "./shared/popup/certaccept/html/"
|
||||
],
|
||||
[ /* javascript loader (debug) */
|
||||
"type" => "js",
|
||||
"search-pattern" => "/.*\.js$/",
|
||||
"build-target" => "dev",
|
||||
|
||||
"path" => "./popup/certaccept/loader/",
|
||||
"local-path" => "./shared/loader/"
|
||||
],
|
||||
[ /* javascript loader for releases */
|
||||
"type" => "js",
|
||||
"search-pattern" => "/.*loader_certaccept.min.js$/",
|
||||
"build-target" => "rel",
|
||||
|
||||
"path" => "./popup/certaccept/loader/",
|
||||
"local-path" => "./shared/generated/"
|
||||
],
|
||||
|
||||
[ /* javascript for debug */
|
||||
"type" => "js",
|
||||
"search-pattern" => "/^.*\.js$/",
|
||||
"build-target" => "dev",
|
||||
|
||||
"path" => "./popup/certaccept/js/",
|
||||
"local-path" => "./shared/js/"
|
||||
],
|
||||
];
|
||||
|
||||
$APP_FILE_LIST = array_merge(
|
||||
$APP_FILE_LIST_SHARED_SOURCE,
|
||||
$APP_FILE_LIST_SHARED_VENDORS,
|
||||
$APP_FILE_LIST_CLIENT_SOURCE,
|
||||
$APP_FILE_LIST_WEB_SOURCE,
|
||||
$APP_FILE_LIST_WEB_TEASPEAK
|
||||
$APP_FILE_LIST_WEB_TEASPEAK,
|
||||
|
||||
$CERTACCEPT_FILE_LIST
|
||||
);
|
||||
|
||||
function systemify_path($path) {
|
||||
|
@ -472,8 +510,8 @@
|
|||
$file = new AppFile;
|
||||
|
||||
$f_info = pathinfo($f_entry);
|
||||
$file->target_path = systemify_path($entry["path"]) . DIRECTORY_SEPARATOR . $f_info["dirname"] . DIRECTORY_SEPARATOR;
|
||||
$file->local_path = getcwd() . DIRECTORY_SEPARATOR . systemify_path($entry["local-path"]) . DIRECTORY_SEPARATOR . $f_info["dirname"] . DIRECTORY_SEPARATOR;
|
||||
$file->target_path = realpath(systemify_path($entry["path"]) . DIRECTORY_SEPARATOR . $f_info["dirname"] . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
$file->local_path = realpath(getcwd() . DIRECTORY_SEPARATOR . systemify_path($entry["local-path"]) . DIRECTORY_SEPARATOR . $f_info["dirname"] . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$file->name = $f_info["basename"];
|
||||
$file->type = $entry["type"];
|
||||
|
@ -481,7 +519,7 @@
|
|||
|
||||
if(strlen($file->hash) > 0) {
|
||||
foreach ($result as $e)
|
||||
if($e->hash == $file->hash) goto ignore;
|
||||
if($e->hash == $file->hash && $e->target_path == $file->target_path) goto ignore;
|
||||
}
|
||||
array_push($result, $file);
|
||||
ignore:
|
||||
|
|
|
@ -1,162 +1,5 @@
|
|||
.modal .modal-bookmarks {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
.bookmark-list {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: 75px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: start;
|
||||
|
||||
overflow-y: auto;
|
||||
|
||||
.entry {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
> .name {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.bookmark {
|
||||
&.selected {
|
||||
background-color: #0000FF77;
|
||||
}
|
||||
}
|
||||
|
||||
&.directory {
|
||||
&.selected {
|
||||
> .name {
|
||||
background-color: #0000FF77;
|
||||
}
|
||||
}
|
||||
|
||||
> .name {
|
||||
border: 0 solid gray;
|
||||
border-bottom: 1px solid #ad9d9d33;
|
||||
}
|
||||
.members {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
|
||||
margin-top: 5px;
|
||||
text-align: right;
|
||||
|
||||
button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
|
||||
.button-large {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
.buttons {
|
||||
.button-large {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group_box {
|
||||
flex-shrink: 1;
|
||||
|
||||
.header {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
&.gb-settings {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&.gb-list {
|
||||
min-height: 100px; /* 25px header + 75px body */
|
||||
}
|
||||
}
|
||||
|
||||
.bookmark-setting {
|
||||
.group_box {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.property {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
input, select, .default-channel-container {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
.default-channel-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
button {
|
||||
margin-left: 5px;
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.key {
|
||||
width: 160px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.container-default-channel-select {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
.container-default-channel {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "properties";
|
||||
@import "mixin";
|
||||
|
||||
.modal .modal-bookmark-create {
|
||||
.property {
|
||||
|
@ -188,4 +31,437 @@
|
|||
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-body.modal-bookmarks {
|
||||
padding: 0!important;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row!important;
|
||||
justify-content: stretch!important;
|
||||
|
||||
min-width: 30em!important;
|
||||
height: 60em;
|
||||
width: 80em;
|
||||
|
||||
.container-tooltip {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
position: relative;
|
||||
width: 1.6em;
|
||||
margin-left: .5em;
|
||||
font-size: .9em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
|
||||
align-self: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.input-boxed {
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.left {
|
||||
min-width: 12em;
|
||||
width: 30%;
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
padding: .5em;
|
||||
background-color: #212125;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
.title {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
font-size: 1.5em;
|
||||
color: #557edc;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.container-bookmarks {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
|
||||
min-height: 6em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
overflow: auto;
|
||||
@include chat-scrollbar-vertical();
|
||||
@include chat-scrollbar-horizontal();
|
||||
|
||||
.bookmark, .directory {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
border-radius: $border_radius_middle;
|
||||
padding: .25em .5em;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
.icon-container {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
align-self: center;
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
min-width: 5em;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #2c2d2f;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: #1a1a1b;
|
||||
}
|
||||
|
||||
.link {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
position: relative;
|
||||
width: 1.5em;
|
||||
|
||||
$line_width: 2px;
|
||||
$color: hsla(0, 0%, 35%, 1);
|
||||
&:not(.hidden) {
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
||||
height: 2.25em; /* connect with the previous one */
|
||||
width: .75em;
|
||||
|
||||
left: .5em; /* icons have a width of 1em */
|
||||
bottom: calc(.75em - #{$line_width / 2});
|
||||
|
||||
border-left: $line_width solid $color;
|
||||
}
|
||||
|
||||
&.connected {
|
||||
&:before {
|
||||
border-bottom: $line_width solid $color;
|
||||
|
||||
border-bottom-left-radius: .3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.link-start {
|
||||
.link.connected {
|
||||
&:before {
|
||||
height: 1.25em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.directory {
|
||||
.name {
|
||||
//color: #557edc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
padding-top: .5em;
|
||||
|
||||
button {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
min-width: 25em;
|
||||
width: 30%;
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
background-color: #2f2f35;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
.header {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
height: 10em;
|
||||
|
||||
background: url('../../../img/bookmark_background.png'), url('../../img/bookmark_background.png') no-repeat;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
|
||||
padding: .5em;
|
||||
|
||||
.container-name {
|
||||
font-size: 2em;
|
||||
color: #fcfcfc;
|
||||
}
|
||||
|
||||
.container-address {
|
||||
font-size: 1.5em;
|
||||
color: #fcfcfc;
|
||||
}
|
||||
}
|
||||
|
||||
.container-settings {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: 10em;
|
||||
|
||||
padding: .5em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
.group {
|
||||
padding: .5em;
|
||||
|
||||
border-radius: .2em;
|
||||
border: 1px solid #1f2122;
|
||||
|
||||
background-color: #28292b;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
> .row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
.key {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
|
||||
width: 15em;
|
||||
min-width: 2em;
|
||||
|
||||
align-self: center;
|
||||
|
||||
color: #557edc;
|
||||
|
||||
text-transform: uppercase;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.value {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
min-width: 2em;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
&.info {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.container-image {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 100;
|
||||
|
||||
max-width: 15em;
|
||||
max-height: 9em; /* minus one padding */
|
||||
width: 15em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@include transition(.25s ease-in-out);
|
||||
}
|
||||
|
||||
.container-properties {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
|
||||
min-width: 23em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
height: inherit;
|
||||
|
||||
.row {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
height: 1.8em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
|
||||
.key {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
color: #557edc;
|
||||
text-transform: uppercase;
|
||||
align-self: center;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #d6d6d7;
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.server-region {
|
||||
> div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.country {
|
||||
margin-right: .25em;
|
||||
}
|
||||
}
|
||||
|
||||
.connect-count, .connect-never {
|
||||
display: inline-block;
|
||||
|
||||
color: #7a3131;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-network {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
|
||||
.container-button {
|
||||
margin-right: 1em;
|
||||
|
||||
flex-shrink: 1;
|
||||
min-width: 5em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
|
||||
button {
|
||||
height: 2.5em;
|
||||
width: 12em;
|
||||
|
||||
max-width: 100%;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
padding: .5em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
|
||||
button {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -211,7 +211,7 @@
|
|||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
min-width: 8em;
|
||||
|
|
|
@ -14,23 +14,31 @@
|
|||
<meta charset="UTF-8">
|
||||
<!-- App min width: 450px -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, min-zoom=1, max-zoom: 1, user-scalable=no">
|
||||
<meta name="description" content="TeaSpeak Web Client, connect to any TeaSpeak server without installing anything." />
|
||||
<meta name="description" content="The TeaSpeak Web client is a in the browser running client for the VoIP communication software TeaSpeak." />
|
||||
<meta name="keywords" content="TeaSpeak, TeaWeb, TeaSpeak-Web,Web client TeaSpeak, веб клієнт TeaSpeak, TSDNS, багатомовність, мультимовність, теми, функціонал"/>
|
||||
|
||||
<meta name="og:description" content="The TeaSpeak Web client is a in the browser running client for the VoIP communication software TeaSpeak." />
|
||||
<meta name="og:url" content="https://web.teaspeak.de/">
|
||||
<meta name="og:image" content="https://www.whatsapp.com/img/whatsapp-promo.png">
|
||||
|
||||
<!-- TODO Needs some fix -->
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<?php
|
||||
<?php
|
||||
if(!$WEB_CLIENT) {
|
||||
echo "<title>TeaClient</title>";
|
||||
echo "\t\t<title>TeaClient</title>" . PHP_EOL;
|
||||
echo "\t\t<meta name='og:title' content='TeaClient'>" . PHP_EOL;
|
||||
} else {
|
||||
echo "<title>TeaSpeak-Web</title>";
|
||||
echo '<link rel="icon" href="img/favicon/teacup.png" type="image/x-icon">';
|
||||
echo "\t\t<title>TeaSpeak-Web</title>" . PHP_EOL;
|
||||
echo "\t\t<meta name='og:title' content='TeaSpeak-Web'>" . PHP_EOL;
|
||||
echo "\t\t<link rel='shortcut icon' href='img/favicon/teacup.png' type='image/x-icon'>" . PHP_EOL;
|
||||
//<link rel="apple-touch-icon" sizes="194x194" href="/apple-touch-icon.png" type="image/png">
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
<!-- PHP generated properties -->
|
||||
<x-properties id="properties">
|
||||
<?php
|
||||
<?php
|
||||
function spawn_property($name, $value, $element_id = null)
|
||||
{
|
||||
if(isset($value))
|
||||
|
@ -44,9 +52,12 @@
|
|||
if ($version === false)
|
||||
$version = "unknown";
|
||||
spawn_property("version", $version, "app_version");
|
||||
?>
|
||||
?>
|
||||
</x-properties>
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-113151733-4"></script>
|
||||
<script>
|
||||
|
@ -79,9 +90,29 @@
|
|||
.fulloverlay .container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
top: 30%;
|
||||
|
||||
max-width: unset!important; /* override bootstrap */
|
||||
top: 20%;
|
||||
}
|
||||
|
||||
#critical-load.shown {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-height: 750px) {
|
||||
#critical-load .container {
|
||||
top: unset;
|
||||
}
|
||||
|
||||
#critical-load {
|
||||
font-size: .8rem;
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#critical-load.shown {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.no-js {
|
||||
|
@ -92,10 +123,12 @@
|
|||
<div id="style">
|
||||
<link rel="stylesheet" href="css/loader/loader.css">
|
||||
</div>
|
||||
|
||||
<meta name="app-loader-target" content="app">
|
||||
<div id="scripts">
|
||||
<script type="application/javascript" src="loader/loader_app.min.js" defer></script>
|
||||
<script type="application/javascript" src="loader/loader_app.js" defer></script>
|
||||
<script type="application/javascript" src="loader/loader.js" defer></script>
|
||||
<script type="application/javascript" src="loader/loader.js?_<?php echo time() ?>" defer></script>
|
||||
</div>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -134,13 +167,13 @@
|
|||
<!-- Critical load error -->
|
||||
<div class="fulloverlay" id="critical-load">
|
||||
<div class="container">
|
||||
<img src="img/loading_error_right.svg" height="192px">
|
||||
<h1 class="error" style="color: red"></h1>
|
||||
<h3 class="detail"></h3>
|
||||
<img src="img/loading_error_right.svg" style="height: 12em">
|
||||
<h1 class="error" style="color: red; margin-bottom: 0"></h1>
|
||||
<h3 class="detail" style="margin-top: .5em"></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if($localhost && false) { ?>
|
||||
<?php if($localhost && true) { ?>
|
||||
<div id="spoiler-style" style="z-index: 1000000; position: absolute; display: block; background: white; right: 5px; left: 5px; top: 34px;">
|
||||
<!-- <img src="https://www.chromatic-solutions.de/teaspeak/window/connect_opened.png"> -->
|
||||
<!-- <img src="http://puu.sh/DZDgO/9149c0a1aa.png"> -->
|
||||
|
@ -179,7 +212,7 @@
|
|||
|
||||
<!-- <img src="http://puu.sh/E6NXv/eb2f19c7c3.png"> -->
|
||||
<!-- <img src="http://puu.sh/E9jT6/302912ae34.png"> -->
|
||||
<img src="http://puu.sh/E9jYi/3003c58a2f.png">
|
||||
<img src="http://puu.sh/Eb5w4/8d38fe5b8f.png">
|
||||
</div>
|
||||
<button class="toggle-spoiler-style" style="height: 30px; width: 100px; z-index: 100000000; position: absolute; bottom: 2px;">toggle style</button>
|
||||
<script>
|
||||
|
@ -190,19 +223,6 @@
|
|||
});
|
||||
}, 2500);
|
||||
</script>
|
||||
<?php } ?>
|
||||
|
||||
<div id="music-test"></div>
|
||||
<div id="templates"></div>
|
||||
<div id="sounds"></div>
|
||||
<div id="mouse-move">
|
||||
<div class="container">
|
||||
</div>
|
||||
</div>
|
||||
<div id="global-tooltip">
|
||||
<a></a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</body>
|
||||
|
||||
<div id="top-menu-bar"></div>
|
||||
</html>
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"short_name": "TeaWeb",
|
||||
"name": "TeaSpeak Web",
|
||||
"description": "The TeaSpeak Web client is a in the browser running client for the VoIP communication software TeaSpeak.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "img/favicon/teacup.png",
|
||||
|
@ -8,8 +9,8 @@
|
|||
"sizes": "256x256"
|
||||
}
|
||||
],
|
||||
"start_url": "/?",
|
||||
"start_url": "./?",
|
||||
"background_color": "#18BC9C",
|
||||
"display": "standalone",
|
||||
"display": "fullscreen",
|
||||
"theme_color": "#18BC9C"
|
||||
}
|
|
@ -4374,143 +4374,167 @@
|
|||
</script>
|
||||
|
||||
<script class="jsrender-template" id="tmpl_manage_bookmarks" type="text/html">
|
||||
<div class="modal-bookmarks">
|
||||
<div class="group_box gb-list">
|
||||
<div class="header">{{tr "Bookmarks" /}}</div>
|
||||
<div class="content bookmark-list">
|
||||
<div class="list">
|
||||
<div class="entry bookmark">
|
||||
<div class="name">TeaSpeak official</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="left">
|
||||
<div class="title">{{tr "Your bookmarks" /}}</div>
|
||||
<div class="container-bookmarks">
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-danger button-delete">{{tr "Delete" /}}</button>
|
||||
<button class="btn btn-purple button-add-folder">{{tr "Add Folder" /}}</button>
|
||||
<button class="btn btn-success button-add-bookmark">{{tr "Add Bookmark" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="button-large btn btn-raised btn-secondary button-create">{{tr "Create new
|
||||
bookmark/directory" /}}
|
||||
</button>
|
||||
<button class="button-large btn btn-danger button-delete">{{tr "Delete selected bookmark/directory"
|
||||
/}}
|
||||
</button>
|
||||
|
||||
<button class="button-small btn btn-raised btn-secondary button-create">{{tr "Create" /}}</button>
|
||||
<button class="button-small btn btn-danger button-delete">{{tr "Delete" /}}</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="group_box gb-settings">
|
||||
<div class="header">{{tr "Bookmark settings" /}}</div>
|
||||
<div class="content">
|
||||
<div class="bookmark-setting bookmark-setting-bookmark">
|
||||
<div class="form-group">
|
||||
<label for="input-bookmark-name" class="bmd-label-static">{{tr "Bookmark name:"
|
||||
/}}</label>
|
||||
<input id="input-bookmark-name" class="form-control setting-bookmark-name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="input-bookmark-profile" class="bmd-label-static">{{tr "Connect profile:"
|
||||
/}}</label>
|
||||
<select id="input-bookmark-profile"
|
||||
class="form-control setting-bookmark-profile"></select>
|
||||
</div>
|
||||
<div class="group_box">
|
||||
<div class="header">{{tr "Server Properties" /}}</div>
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<label for="input-bookmark-server-host" class="bmd-label-static">{{tr "Server
|
||||
address:" /}}</label>
|
||||
<input id="input-bookmark-server-host" class="form-control setting-server-host">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="input-bookmark-server-port" class="bmd-label-static">{{tr "Server
|
||||
port:" /}}</label>
|
||||
<input type="number" min="1" max="65665" id="input-bookmark-server-port"
|
||||
class="form-control setting-server-port">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<!-- TODO generated id because of password field (id="bookmark_server_password_{{rnd '0~13377331'/}}") -->
|
||||
<label for="input-bookmark-server-password" class="bmd-label-floating">{{tr
|
||||
"Server password" /}}</label>
|
||||
<input id="input-bookmark-server-password"
|
||||
class="form-control setting-server-password" autocomplete="nope"
|
||||
type="password">
|
||||
<div class="container-seperator vertical" seperator-id="seperator-bookmarks"></div>
|
||||
<div class="right">
|
||||
<div class="header">
|
||||
<div class="container-name">{{tr "Your bookmarks" /}}</div>
|
||||
<div class="container-address"></div>
|
||||
</div>
|
||||
<div class="container-settings">
|
||||
<div class="group">
|
||||
<div class="row">
|
||||
<div class="key">{{tr "Bookmark Name" /}}</div>
|
||||
<div class="value">
|
||||
<div class="input-boxed">
|
||||
<input class="input-bookmark-name">
|
||||
<!--
|
||||
<div class="container-tooltip">
|
||||
<img src="img/icon_tooltip.svg"/>
|
||||
<div class="tooltip">
|
||||
<a>{{tr "The displayed name of this bookmark." /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
<div class="group_box">
|
||||
<div class="header">{{tr "Connect Properties (Not yet supported)" /}}</div>
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<label for="input-bookmark-username" class="bmd-label-floating">{{tr "Default Username" /}}</label>
|
||||
<input id="input-bookmark-username" class="form-control setting-username" disabled>
|
||||
</div>
|
||||
<div class="form-row container-default-channel-select">
|
||||
<div class="form-group container-default-channel">
|
||||
<label for="input-bookmark-channel" class="bmd-label-floating">{{tr "Default Channel" /}}</label>
|
||||
<input id="input-bookmark-channel" class="form-control setting-channel" disabled>
|
||||
<div class="row">
|
||||
<div class="key">{{tr "Connect Profile" /}}</div>
|
||||
<div class="value">
|
||||
<div class="input-boxed">
|
||||
<select class="input-connect-profile">
|
||||
</select>
|
||||
<!--
|
||||
<div class="container-tooltip">
|
||||
<img src="img/icon_tooltip.svg"/>
|
||||
<div class="tooltip">
|
||||
<a>{{tr "The profile which you're connection with when you're using the bookmark." /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group bmd-form-group">
|
||||
<button class="btn btn-primary button-set-to-current" disabled>{{tr "Current Channel" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<!- TODO generated id because of password field (id="bookmark_server_password_{{rnd '0~13377331'/}}") ->
|
||||
<label for="input-bookmark-channel-password" class="bmd-label-floating">{{tr "Default channel password" /}}</label>
|
||||
<input id="input-bookmark-channel-password" class="form-control setting-channel-password" type="password" disabled>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
<div class="bookmark-setting bookmark-setting-directory">
|
||||
<div class="form-group">
|
||||
<label for="input-bookmark-dirname" class="bmd-label-static">{{tr "Directory name:"
|
||||
/}}</label>
|
||||
<input id="input-bookmark-dirname" class="form-control setting-bookmark-name">
|
||||
<div class="group">
|
||||
<div class="row">
|
||||
<div class="key">{{tr "Server Address" /}}</div>
|
||||
<div class="value">
|
||||
<div class="input-boxed">
|
||||
<input class="input-server-address">
|
||||
<!--
|
||||
<div class="container-tooltip">
|
||||
<img src="img/icon_tooltip.svg"/>
|
||||
<div class="tooltip">
|
||||
<a>{{tr "The server address of the bookmark. The port is separated via a colon" /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="key">{{tr "Server Password" /}}</div>
|
||||
<div class="value">
|
||||
<div class="input-boxed">
|
||||
<input type="password" class="input-server-password">
|
||||
<!--
|
||||
<div class="container-tooltip">
|
||||
<img src="img/icon_tooltip.svg"/>
|
||||
<div class="tooltip">
|
||||
<a>{{tr "The server port of the bookmark" /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="key">{{tr "Default Channel" /}}</div>
|
||||
<div class="value">
|
||||
<div class="input-boxed">
|
||||
<input class="input-default-channel" placeholder="{{tr 'Not yet implemented' /}}" disabled>
|
||||
<!--
|
||||
<div class="container-tooltip">
|
||||
<img src="img/icon_tooltip.svg"/>
|
||||
<div class="tooltip">
|
||||
<a>{{tr "The server port of the bookmark" /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="key">{{tr "Channel Password" /}}</div>
|
||||
<div class="value">
|
||||
<div class="input-boxed">
|
||||
<input type="password" class="input-default-channel-password" placeholder="{{tr 'Not yet implemented' /}}" disabled>
|
||||
<!--
|
||||
<div class="container-tooltip">
|
||||
<img src="img/icon_tooltip.svg"/>
|
||||
<div class="tooltip">
|
||||
<a>{{tr "The server port of the bookmark" /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group info">
|
||||
<div class="container-image">
|
||||
<img src="img/serveredit_1.png">
|
||||
</div>
|
||||
<div class="container-properties">
|
||||
<div class="row">
|
||||
<a class="key">{{tr "Server name" /}}</a>
|
||||
<div class="value server-name">
|
||||
error: name
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<a class="key">{{tr "Server region" /}}</a>
|
||||
<div class="value server-region">
|
||||
error: region
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<a class="key">{{tr "Last ping" /}}</a>
|
||||
<div class="value server-ping">
|
||||
error: ping
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<a class="key">{{tr "Last client count" /}}</a>
|
||||
<div class="value server-client-count">
|
||||
error: last client
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<a class="key">{{tr "Your connection" /}}</a>
|
||||
<div class="value server-connection-count">
|
||||
error: connection count
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script class="jsrender-template" id="tmpl_manage_bookmarks-list_entry" type="text/html">
|
||||
{{if type == "bookmark" }}
|
||||
<div class="entry bookmark">
|
||||
<div class="name">{{>name}}</div>
|
||||
</div>
|
||||
{{else type == "directory" }}
|
||||
<div class="entry directory">
|
||||
<div class="name">{{>name}}</div>
|
||||
<div class="members"></div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</script>
|
||||
|
||||
|
||||
<script class="jsrender-template" id="tmpl_manage_bookmarks-create" type="text/html">
|
||||
<div class="modal-bookmark-create">
|
||||
<div class="form-group">
|
||||
<label class="bmd-label-floating">{{tr "Bookmark type:" /}}</label>
|
||||
<select class="form-control bookmark-type">
|
||||
<option value="bookmark">Bookmark</option>
|
||||
<option value="directory">Directory</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="bmd-label-floating">{{tr "Parent directory:" /}}</label>
|
||||
<select class="form-control bookmark-parent">
|
||||
<option bookmark-uuid=""></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="bmd-label-floating">{{tr "Bookmark name" /}}</label>
|
||||
<input class="form-control bookmark-name">
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-success button-create">Create</button>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-success button-connect-tab">{{tr "Connect in a new tab" /}}</button>
|
||||
<button class="btn btn-success button-connect">{{tr "Connect" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
@ -5175,6 +5199,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="container-buttons">
|
||||
<button class="btn btn-success button-update">{{tr "Refresh" /}}</button>
|
||||
<button class="btn btn-danger button-close">{{tr "Close" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -300,7 +300,7 @@ class ConnectionHandler {
|
|||
|
||||
private initialize_server_settings() {
|
||||
let update_control = false;
|
||||
this.settings.setServer(this.channelTree.server);
|
||||
this.settings.setServer(this.channelTree.server.properties.virtualserver_unique_identifier);
|
||||
{
|
||||
const flag_subscribe = this.settings.server(Settings.KEY_CONTROL_CHANNEL_SUBSCRIBE_ALL, true);
|
||||
if(this.client_status.channel_subscribe_all != flag_subscribe) {
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace bookmarks {
|
|||
|
||||
export interface Bookmark {
|
||||
type: /* BookmarkType.ENTRY */ BookmarkType;
|
||||
/* readonly */ parent: DirectoryBookmark;
|
||||
|
||||
/* readonly directory: DirectoryBookmark; */
|
||||
server_properties: ServerProperties;
|
||||
display_name: string;
|
||||
unique_id: string;
|
||||
|
@ -72,6 +72,7 @@ namespace bookmarks {
|
|||
|
||||
export interface DirectoryBookmark {
|
||||
type: /* BookmarkType.DIRECTORY */ BookmarkType;
|
||||
readonly parent: DirectoryBookmark;
|
||||
|
||||
readonly content: (Bookmark | DirectoryBookmark)[];
|
||||
unique_id: string;
|
||||
|
@ -110,11 +111,25 @@ namespace bookmarks {
|
|||
|
||||
save_config();
|
||||
}
|
||||
|
||||
const fix_parent = (parent: DirectoryBookmark, entry: Bookmark | DirectoryBookmark) => {
|
||||
entry.parent = parent;
|
||||
if(entry.type === BookmarkType.DIRECTORY)
|
||||
for(const child of (entry as DirectoryBookmark).content)
|
||||
fix_parent(entry as DirectoryBookmark, child);
|
||||
};
|
||||
for(const entry of _bookmark_config.root_bookmark.content)
|
||||
fix_parent(_bookmark_config.root_bookmark, entry);
|
||||
|
||||
return _bookmark_config;
|
||||
}
|
||||
|
||||
function save_config() {
|
||||
localStorage.setItem("bookmarks", JSON.stringify(bookmark_config()));
|
||||
localStorage.setItem("bookmarks", JSON.stringify(bookmark_config(), (key, value) => {
|
||||
if(key === "parent")
|
||||
return undefined;
|
||||
return value;
|
||||
}));
|
||||
}
|
||||
|
||||
export function bookmarks() : DirectoryBookmark {
|
||||
|
@ -172,7 +187,8 @@ namespace bookmarks {
|
|||
nickname: nickname,
|
||||
type: BookmarkType.ENTRY,
|
||||
connect_profile: "default",
|
||||
unique_id: guid()
|
||||
unique_id: guid(),
|
||||
parent: directory
|
||||
} as Bookmark;
|
||||
|
||||
directory.content.push(bookmark);
|
||||
|
@ -185,7 +201,8 @@ namespace bookmarks {
|
|||
|
||||
display_name: name,
|
||||
content: [],
|
||||
unique_id: guid()
|
||||
unique_id: guid(),
|
||||
parent: parent
|
||||
} as DirectoryBookmark;
|
||||
|
||||
parent.content.push(bookmark);
|
||||
|
|
|
@ -73,23 +73,17 @@ namespace log {
|
|||
}
|
||||
const group_mode: GroupMode = GroupMode.PREFIX;
|
||||
|
||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
name: "log enabled initialisation",
|
||||
function: async () => initialize(),
|
||||
priority: 150
|
||||
});
|
||||
|
||||
//Category Example: <url>?log.i18n.enabled=0
|
||||
//Level Example A: <url>?log.level.trace.enabled=0
|
||||
//Level Example B: <url>?log.level=0
|
||||
export function initialize() {
|
||||
export function initialize(default_level: LogType) {
|
||||
for(const category of Object.keys(LogCategory).map(e => parseInt(e))) {
|
||||
if(isNaN(category)) continue;
|
||||
const category_name = LogCategory[category].toLowerCase();
|
||||
enabled_mapping.set(category, settings.static_global<boolean>("log." + category_name.toLowerCase() + ".enabled", enabled_mapping.get(category)));
|
||||
}
|
||||
|
||||
const base_level = settings.static_global<number>("log.level", app.type === app.Type.CLIENT_DEBUG || app.type === app.Type.WEB_DEBUG ? LogType.TRACE : LogType.INFO);
|
||||
const base_level = settings.static_global<number>("log.level", default_level);
|
||||
|
||||
for(const level of Object.keys(LogType).map(e => parseInt(e))) {
|
||||
if(isNaN(level)) continue;
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
/// <reference path="log.ts" />
|
||||
/// <reference path="PPTListener.ts" />
|
||||
|
||||
let settings: Settings;
|
||||
|
||||
const js_render = window.jsrender || $;
|
||||
const native_client = window.require !== undefined;
|
||||
|
||||
|
@ -117,7 +115,7 @@ function setup_jsrender() : boolean {
|
|||
}
|
||||
|
||||
async function initialize() {
|
||||
settings = new Settings();
|
||||
Settings.initialize();
|
||||
|
||||
try {
|
||||
await i18n.initialize();
|
||||
|
@ -425,8 +423,9 @@ function main() {
|
|||
// Modals.openServerInfo(connection.channelTree.server);
|
||||
//Modals.createServerModal(connection.channelTree.server, properties => Promise.resolve());
|
||||
}, 1000);
|
||||
Modals.spawnSettingsModal("identity-profiles");
|
||||
//Modals.spawnSettingsModal("identity-profiles");
|
||||
//Modals.spawnKeySelect(console.log);
|
||||
Modals.spawnBookmarkModal();
|
||||
}
|
||||
|
||||
const task_teaweb_starter: loader.Task = {
|
||||
|
|
|
@ -293,9 +293,9 @@ class Settings extends StaticSettings {
|
|||
key: "font_size"
|
||||
};
|
||||
|
||||
static readonly FN_SERVER_CHANNEL_SUBSCRIBE_MODE: (channel: ChannelEntry) => SettingsKey<ChannelSubscribeMode> = channel => {
|
||||
static readonly FN_SERVER_CHANNEL_SUBSCRIBE_MODE: (channel_id: number) => SettingsKey<number> = channel => {
|
||||
return {
|
||||
key: 'channel_subscribe_mode_' + channel.getChannelId()
|
||||
key: 'channel_subscribe_mode_' + channel
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -320,6 +320,10 @@ class Settings extends StaticSettings {
|
|||
return result;
|
||||
})();
|
||||
|
||||
static initialize() {
|
||||
settings = new Settings();
|
||||
}
|
||||
|
||||
private cacheGlobal = {};
|
||||
private saveWorker: NodeJS.Timer;
|
||||
private updated: boolean = false;
|
||||
|
@ -372,7 +376,7 @@ class Settings extends StaticSettings {
|
|||
|
||||
class ServerSettings extends SettingsBase {
|
||||
private cacheServer = {};
|
||||
private currentServer: ServerEntry;
|
||||
private _server_unique_id: string;
|
||||
private _server_save_worker: NodeJS.Timer;
|
||||
private _server_settings_updated: boolean = false;
|
||||
private _destroyed = false;
|
||||
|
@ -388,7 +392,7 @@ class ServerSettings extends SettingsBase {
|
|||
destroy() {
|
||||
this._destroyed = true;
|
||||
|
||||
this.currentServer = undefined;
|
||||
this._server_unique_id = undefined;
|
||||
this.cacheServer = undefined;
|
||||
|
||||
clearInterval(this._server_save_worker);
|
||||
|
@ -413,18 +417,17 @@ class ServerSettings extends SettingsBase {
|
|||
this.save();
|
||||
}
|
||||
|
||||
setServer(server: ServerEntry) {
|
||||
setServer(server_unique_id: string) {
|
||||
if(this._destroyed) throw "destroyed";
|
||||
if(this.currentServer) {
|
||||
if(this._server_unique_id) {
|
||||
this.save();
|
||||
this.cacheServer = {};
|
||||
this.currentServer = undefined;
|
||||
this._server_unique_id = undefined;
|
||||
}
|
||||
this.currentServer = server;
|
||||
this._server_unique_id = server_unique_id;
|
||||
|
||||
if(this.currentServer) {
|
||||
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
|
||||
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
|
||||
if(this._server_unique_id) {
|
||||
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + server_unique_id));
|
||||
if(!this.cacheServer)
|
||||
this.cacheServer = {};
|
||||
}
|
||||
|
@ -434,12 +437,13 @@ class ServerSettings extends SettingsBase {
|
|||
if(this._destroyed) throw "destroyed";
|
||||
this._server_settings_updated = false;
|
||||
|
||||
if(this.currentServer) {
|
||||
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
|
||||
if(this._server_unique_id) {
|
||||
let server = JSON.stringify(this.cacheServer);
|
||||
localStorage.setItem("settings.server_" + serverId, server);
|
||||
localStorage.setItem("settings.server_" + this._server_unique_id, server);
|
||||
if(localStorage.save)
|
||||
localStorage.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let settings: Settings;
|
|
@ -910,7 +910,7 @@ class ChannelEntry {
|
|||
}
|
||||
|
||||
get subscribe_mode() : ChannelSubscribeMode {
|
||||
return typeof(this._subscribe_mode) !== 'undefined' ? this._subscribe_mode : (this._subscribe_mode = this.channelTree.client.settings.server(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this), ChannelSubscribeMode.INHERITED));
|
||||
return typeof(this._subscribe_mode) !== 'undefined' ? this._subscribe_mode : (this._subscribe_mode = this.channelTree.client.settings.server(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId), ChannelSubscribeMode.INHERITED));
|
||||
}
|
||||
|
||||
set subscribe_mode(mode: ChannelSubscribeMode) {
|
||||
|
@ -918,7 +918,7 @@ class ChannelEntry {
|
|||
return;
|
||||
|
||||
this._subscribe_mode = mode;
|
||||
this.channelTree.client.settings.changeServer(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this), mode);
|
||||
this.channelTree.client.settings.changeServer(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId), mode);
|
||||
}
|
||||
|
||||
set flag_text_unread(flag: boolean) {
|
||||
|
|
|
@ -65,6 +65,7 @@ if(!$.fn.dividerfy) {
|
|||
}
|
||||
|
||||
|
||||
//console.log(min + " - " + max + " - " + current);
|
||||
const property = vertical ? "width" : "height";
|
||||
const previous_p = Math.ceil(previous * 100);
|
||||
const next_p = Math.ceil(next * 100);
|
||||
|
|
|
@ -3,40 +3,6 @@
|
|||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
function bookmark_tag(callback_select: (entry, tag) => any, bookmark: bookmarks.Bookmark | bookmarks.DirectoryBookmark) {
|
||||
const tag = $("#tmpl_manage_bookmarks-list_entry").renderTag({
|
||||
name: bookmark.display_name,
|
||||
type: bookmark.type == bookmarks.BookmarkType.DIRECTORY ? "directory" : "bookmark"
|
||||
});
|
||||
tag.find(".name").on('click', () => {
|
||||
callback_select(bookmark, tag);
|
||||
tag.addClass("selected");
|
||||
});
|
||||
|
||||
if(bookmark.type == bookmarks.BookmarkType.DIRECTORY) {
|
||||
const casted = <bookmarks.DirectoryBookmark>bookmark;
|
||||
for(const member of casted.content)
|
||||
tag.find("> .members").append(bookmark_tag(callback_select, member));
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
function parent_tag(select_tag: JQuery, prefix: string, bookmark: bookmarks.Bookmark | bookmarks.DirectoryBookmark) {
|
||||
if(bookmark.type == bookmarks.BookmarkType.DIRECTORY) {
|
||||
const casted = <bookmarks.DirectoryBookmark>bookmark;
|
||||
|
||||
select_tag.append(
|
||||
$.spawn("option")
|
||||
.val(casted.unique_id)
|
||||
.text(prefix + casted.display_name)
|
||||
);
|
||||
|
||||
for(const member of casted.content)
|
||||
parent_tag(select_tag, prefix + " ", member);
|
||||
}
|
||||
}
|
||||
|
||||
export function spawnBookmarkModal() {
|
||||
let modal: Modal;
|
||||
modal = createModal({
|
||||
|
@ -44,214 +10,302 @@ namespace Modals {
|
|||
body: () => {
|
||||
let template = $("#tmpl_manage_bookmarks").renderTag({ });
|
||||
let selected_bookmark: bookmarks.Bookmark | bookmarks.DirectoryBookmark | undefined;
|
||||
let update_name: () => any;
|
||||
|
||||
const update_bookmarks = () => { //list bookmarks
|
||||
template.find(".list").empty();
|
||||
const button_delete = template.find(".button-delete");
|
||||
const button_add_folder = template.find(".button-add-folder");
|
||||
const button_add_bookmark = template.find(".button-add-bookmark");
|
||||
|
||||
const callback_selected = (entry: bookmarks.Bookmark | bookmarks.DirectoryBookmark, tag: JQuery) => {
|
||||
template.find(".selected").removeClass("selected");
|
||||
if(selected_bookmark == entry) return;
|
||||
const button_connect = template.find(".button-connect");
|
||||
const button_connect_tab = template.find(".button-connect-tab");
|
||||
|
||||
selected_bookmark = entry;
|
||||
update_name = () => tag.find("> .name").text(entry.display_name);
|
||||
const label_bookmark_name = template.find(".header .container-name");
|
||||
const label_server_address = template.find(".header .container-address");
|
||||
|
||||
template.find(".bookmark-setting").hide();
|
||||
template.find(".setting-bookmark-name").val(selected_bookmark.display_name);
|
||||
const input_bookmark_name = template.find(".input-bookmark-name");
|
||||
const input_connect_profile = template.find(".input-connect-profile");
|
||||
|
||||
if(selected_bookmark.type == bookmarks.BookmarkType.ENTRY) {
|
||||
template.find(".bookmark-setting-bookmark").show();
|
||||
const input_server_address = template.find(".input-server-address");
|
||||
const input_server_password = template.find(".input-server-password");
|
||||
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const profile = profiles.find_profile(casted.connect_profile) || profiles.default_profile();
|
||||
template.find(".setting-bookmark-profile").val(profile.id);
|
||||
const label_server_name = template.find(".server-name");
|
||||
const label_server_region = template.find(".server-region");
|
||||
const label_last_ping = template.find(".server-ping");
|
||||
const label_client_count = template.find(".server-client-count");
|
||||
const label_connection_count = template.find(".server-connection-count");
|
||||
|
||||
template.find(".setting-server-host").val(casted.server_properties.server_address);
|
||||
template.find(".setting-server-port").val(casted.server_properties.server_port);
|
||||
template.find(".setting-server-password").val(casted.server_properties.server_password_hash || casted.server_properties.server_password);
|
||||
|
||||
template.find(".setting-username").val(casted.nickname);
|
||||
template.find(".setting-channel").val(casted.default_channel);
|
||||
template.find(".setting-channel-password").val(casted.default_channel_password_hash || casted.default_channel_password);
|
||||
} else {
|
||||
template.find(".bookmark-setting-directory").show();
|
||||
}
|
||||
};
|
||||
|
||||
for(const bookmark of bookmarks.bookmarks().content) {
|
||||
template.find(".list").append(bookmark_tag(callback_selected, bookmark));
|
||||
}
|
||||
console.log( template.find(".list").find(".bookmark, .directory"));
|
||||
template.find(".list").find(".bookmark, .directory").eq(0).find("> .name").trigger('click');
|
||||
const update_buttons = () => {
|
||||
button_delete.prop("disabled", !selected_bookmark);
|
||||
button_connect.prop("disabled", !selected_bookmark || selected_bookmark.type !== bookmarks.BookmarkType.ENTRY);
|
||||
button_connect_tab.prop("disabled", !selected_bookmark || selected_bookmark.type !== bookmarks.BookmarkType.ENTRY);
|
||||
};
|
||||
|
||||
{ //General buttons
|
||||
template.find(".button-create").on('click', event => {
|
||||
let create_modal: Modal;
|
||||
create_modal = createModal({
|
||||
header: tr("Create a new entry"),
|
||||
body: () => {
|
||||
let template = $("#tmpl_manage_bookmarks-create").renderTag({ });
|
||||
template = $.spawn("div").append(template);
|
||||
const update_connect_info = () => {
|
||||
if(selected_bookmark && selected_bookmark.type === bookmarks.BookmarkType.ENTRY) {
|
||||
const entry = selected_bookmark as bookmarks.Bookmark;
|
||||
|
||||
for(const bookmark of bookmarks.bookmarks().content)
|
||||
parent_tag(template.find(".bookmark-parent"), "", bookmark);
|
||||
const history = connection_log.history().find(e => e.address.hostname === entry.server_properties.server_address && e.address.port === entry.server_properties.server_port);
|
||||
if(history) {
|
||||
label_server_name.text(history.name);
|
||||
label_server_region.empty().append(
|
||||
$.spawn("div").addClass("country flag-" + history.country.toLowerCase()),
|
||||
$.spawn("div").text(i18n.country_name(history.country, tr("Global")))
|
||||
);
|
||||
label_client_count.text(history.clients_online + "/" + history.clients_total);
|
||||
label_connection_count.empty().append(
|
||||
...MessageHelper.formatMessage(tr("You've connected {} times"), $.spawn("div").addClass("connect-count").text(history.total_connection))
|
||||
);
|
||||
} else {
|
||||
label_server_name.text(tr("Unknown"));
|
||||
label_server_region.empty().text(tr("Unknown"));
|
||||
label_client_count.text(tr("Unknown"));
|
||||
label_connection_count.empty().append(
|
||||
...MessageHelper.formatMessage(tr("You {} connected to that server address"), $.spawn("div").addClass("connect-never").text("never"))
|
||||
);
|
||||
}
|
||||
label_last_ping.text(tr("Average ping isn't yet supported"));
|
||||
} else {
|
||||
label_server_name.text("--");
|
||||
label_server_region.text("--");
|
||||
label_last_ping.text("--");
|
||||
label_client_count.text("--");
|
||||
label_connection_count.text("--");
|
||||
}
|
||||
};
|
||||
|
||||
if(selected_bookmark) {
|
||||
const parent = selected_bookmark.type == bookmarks.BookmarkType.ENTRY ?
|
||||
bookmarks.parent_bookmark(selected_bookmark as bookmarks.Bookmark) :
|
||||
selected_bookmark;
|
||||
if(parent)
|
||||
template.find(".bookmark-parent").val(parent.unique_id);
|
||||
}
|
||||
const update_selected = () => {
|
||||
input_bookmark_name.prop("disabled", !selected_bookmark);
|
||||
input_connect_profile.prop("disabled", !selected_bookmark || selected_bookmark.type !== bookmarks.BookmarkType.ENTRY);
|
||||
input_server_address.prop("disabled", !selected_bookmark || selected_bookmark.type !== bookmarks.BookmarkType.ENTRY);
|
||||
input_server_password.prop("disabled", !selected_bookmark || selected_bookmark.type !== bookmarks.BookmarkType.ENTRY);
|
||||
|
||||
template.find(".bookmark-name").on('change, keyup', event => {
|
||||
template.find(".button-create").prop("disabled", (<HTMLInputElement>event.target).value.length < 3);
|
||||
});
|
||||
if(selected_bookmark) {
|
||||
input_bookmark_name.val(selected_bookmark.display_name);
|
||||
label_bookmark_name.text(selected_bookmark.display_name);
|
||||
}
|
||||
|
||||
template.find(".button-create").prop("disabled", true).on('click', event => {
|
||||
const name = template.find(".bookmark-name").val() as string;
|
||||
const parent_uuid = template.find(".bookmark-parent").val() as string;
|
||||
if(selected_bookmark && selected_bookmark.type === bookmarks.BookmarkType.ENTRY) {
|
||||
const entry = selected_bookmark as bookmarks.Bookmark;
|
||||
|
||||
const parent = bookmarks.find_bookmark(parent_uuid);
|
||||
const address = entry.server_properties.server_address + (entry.server_properties.server_port == 9987 ? "" : (" " + entry.server_properties.server_port));
|
||||
label_server_address.text(address);
|
||||
input_server_address.val(address);
|
||||
|
||||
let bookmark;
|
||||
if(template.find(".bookmark-type").val() == "directory") {
|
||||
bookmark = bookmarks.create_bookmark_directory(parent as bookmarks.DirectoryBookmark || bookmarks.bookmarks(), name);
|
||||
} else {
|
||||
bookmark = bookmarks.create_bookmark(name, parent as bookmarks.DirectoryBookmark || bookmarks.bookmarks(), {
|
||||
server_port: 9987,
|
||||
server_address: "ts.teaspeak.de"
|
||||
}, "Another TeaSpeak user");
|
||||
}
|
||||
bookmarks.save_bookmark(bookmark);
|
||||
create_modal.close();
|
||||
update_bookmarks();
|
||||
});
|
||||
let profile = input_connect_profile.find("option[value='" + entry.connect_profile + "']");
|
||||
if(profile.length == 0)
|
||||
profile = input_connect_profile.find("option[value=default]");
|
||||
profile.prop("selected", true);
|
||||
|
||||
return template;
|
||||
},
|
||||
footer: 400
|
||||
input_server_password.val(entry.server_properties.server_password_hash || entry.server_properties.server_password ? "WolverinDEV" : "");
|
||||
} else {
|
||||
input_server_password.val("");
|
||||
input_server_address.val("");
|
||||
input_connect_profile.find("option[value='no-value']").prop('selected', true);
|
||||
label_server_address.text(" ");
|
||||
}
|
||||
|
||||
update_connect_info();
|
||||
};
|
||||
|
||||
const container_bookmarks = template.find(".container-bookmarks");
|
||||
const update_bookmark_list = () => {
|
||||
container_bookmarks.empty();
|
||||
selected_bookmark = undefined;
|
||||
update_selected();
|
||||
|
||||
const hide_links: boolean[] = [];
|
||||
const build_entry = (entry: bookmarks.Bookmark | bookmarks.DirectoryBookmark, sibling_data: {first: boolean; last: boolean;}, index: number) => {
|
||||
let container = $.spawn("div")
|
||||
.addClass(entry.type === bookmarks.BookmarkType.ENTRY ? "bookmark" : "directory")
|
||||
.addClass(index > 0 ? "linked" : "")
|
||||
.addClass(sibling_data.first ? "link-start" : "");
|
||||
for (let i = 0; i < index; i++) {
|
||||
container.append(
|
||||
$.spawn("div")
|
||||
.addClass("link")
|
||||
.addClass(i + 1 === index ? " connected" : "")
|
||||
.addClass(hide_links[i + 1] ? "hidden" : "")
|
||||
);
|
||||
}
|
||||
|
||||
if (entry.type === bookmarks.BookmarkType.ENTRY) {
|
||||
const bookmark = entry as bookmarks.Bookmark;
|
||||
container.append(
|
||||
bookmark.last_icon_id ?
|
||||
IconManager.generate_tag(IconManager.load_cached_icon(bookmark.last_icon_id || 0), {animate: false}) :
|
||||
$.spawn("div").addClass("icon-container icon_em")
|
||||
);
|
||||
} else {
|
||||
container.append(
|
||||
$.spawn("div").addClass("icon-container icon_em client-folder")
|
||||
);
|
||||
}
|
||||
|
||||
container.append(
|
||||
$.spawn("div").addClass("name").text(entry.display_name)
|
||||
);
|
||||
|
||||
container.appendTo(container_bookmarks);
|
||||
container.on('click', event => {
|
||||
if(selected_bookmark === entry)
|
||||
return;
|
||||
|
||||
selected_bookmark = entry;
|
||||
container_bookmarks.find(".selected").removeClass("selected");
|
||||
container.addClass("selected");
|
||||
update_buttons();
|
||||
update_selected();
|
||||
});
|
||||
|
||||
create_modal.open();
|
||||
});
|
||||
hide_links.push(sibling_data.last);
|
||||
let cindex = 0;
|
||||
const children = (entry as bookmarks.DirectoryBookmark).content || [];
|
||||
for (const child of children)
|
||||
build_entry(child, {first: cindex++ == 0, last: cindex == children.length}, index + 1);
|
||||
hide_links.pop();
|
||||
};
|
||||
|
||||
template.find(".button-delete").on('click', event => {
|
||||
let cindex = 0;
|
||||
const children = bookmarks.bookmarks().content;
|
||||
for (const bookmark of children)
|
||||
build_entry(bookmark, {first: cindex++ == 0, last: cindex == children.length}, 0);
|
||||
};
|
||||
|
||||
/* generate profile list */
|
||||
{
|
||||
input_connect_profile.append(
|
||||
$.spawn("option")
|
||||
.attr("value", "no-value")
|
||||
.text("")
|
||||
.css("display", "none")
|
||||
);
|
||||
for(const profile of profiles.profiles()) {
|
||||
input_connect_profile.append(
|
||||
$.spawn("option")
|
||||
.attr("value", profile.id)
|
||||
.text(profile.profile_name)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
{
|
||||
button_delete.on('click', event => {
|
||||
if(!selected_bookmark) return;
|
||||
|
||||
spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this entry?"), result => {
|
||||
if(result) {
|
||||
bookmarks.delete_bookmark(selected_bookmark);
|
||||
bookmarks.save_bookmark(selected_bookmark); /* save the deleted state */
|
||||
update_bookmarks();
|
||||
}
|
||||
});
|
||||
if(selected_bookmark.type === bookmarks.BookmarkType.DIRECTORY && (selected_bookmark as bookmarks.DirectoryBookmark).content.length > 0) {
|
||||
Modals.spawnYesNo(tr("Are you sure"), tr("Do you really want to delete this non empty directory?"), answer => {
|
||||
if(answer) {
|
||||
bookmarks.delete_bookmark(selected_bookmark);
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
update_bookmark_list();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bookmarks.delete_bookmark(selected_bookmark);
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
update_bookmark_list();
|
||||
}
|
||||
});
|
||||
|
||||
/* bookmark listener */
|
||||
{
|
||||
template.find(".setting-bookmark-profile").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.connect_profile = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
|
||||
template.find(".setting-server-host").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.server_properties.server_address = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
|
||||
template.find(".setting-server-port").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.server_properties.server_port = parseInt(element.value);
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
|
||||
template.find(".setting-server-password").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.server_properties.server_password = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
|
||||
|
||||
template.find(".setting-username").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.nickname = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
|
||||
template.find(".setting-channel").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.default_channel = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
|
||||
template.find(".setting-channel-password").on('change', event => {
|
||||
if(!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY) return;
|
||||
const casted = <bookmarks.Bookmark>selected_bookmark;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
casted.default_channel_password = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
});
|
||||
}
|
||||
|
||||
/* listener for both */
|
||||
{
|
||||
template.find(".setting-bookmark-name").on('change', event => {
|
||||
if(!selected_bookmark) return;
|
||||
const element = <HTMLInputElement>event.target;
|
||||
|
||||
if(element.value.length >= 3) {
|
||||
selected_bookmark.display_name = element.value;
|
||||
bookmarks.save_bookmark(selected_bookmark);
|
||||
if(update_name)
|
||||
update_name();
|
||||
button_add_folder.on('click', event => {
|
||||
createInputModal(tr("Enter a folder name"), tr("Enter the folder name"), text => {
|
||||
return true;
|
||||
}, result => {
|
||||
if(result) {
|
||||
const mark = bookmarks.create_bookmark_directory(
|
||||
selected_bookmark ?
|
||||
selected_bookmark.type === bookmarks.BookmarkType.DIRECTORY ?
|
||||
selected_bookmark as bookmarks.DirectoryBookmark :
|
||||
selected_bookmark.parent :
|
||||
bookmarks.bookmarks(),
|
||||
result as string
|
||||
);
|
||||
bookmarks.save_bookmark(mark);
|
||||
update_bookmark_list();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).open();
|
||||
});
|
||||
|
||||
button_add_bookmark.on('click', event => {
|
||||
createInputModal(tr("Enter a bookmark name"), tr("Enter the bookmark name"), text => {
|
||||
return true;
|
||||
}, result => {
|
||||
if(result) {
|
||||
const mark = bookmarks.create_bookmark(result as string,
|
||||
selected_bookmark ?
|
||||
selected_bookmark.type === bookmarks.BookmarkType.DIRECTORY ?
|
||||
selected_bookmark as bookmarks.DirectoryBookmark :
|
||||
selected_bookmark.parent :
|
||||
bookmarks.bookmarks(), {
|
||||
server_password: "",
|
||||
server_port: 9987,
|
||||
server_address: "",
|
||||
server_password_hash: ""
|
||||
}, "");
|
||||
bookmarks.save_bookmark(mark);
|
||||
update_bookmark_list();
|
||||
}
|
||||
}).open();
|
||||
});
|
||||
|
||||
button_connect_tab.on('click', event => {
|
||||
bookmarks.boorkmak_connect(selected_bookmark, true);
|
||||
modal.close();
|
||||
}).toggle(!settings.static_global(Settings.KEY_DISABLE_MULTI_SESSION));
|
||||
|
||||
button_connect.on('click', event => {
|
||||
bookmarks.boorkmak_connect(selected_bookmark, false);
|
||||
modal.close();
|
||||
});
|
||||
}
|
||||
|
||||
/* connect profile initialisation */
|
||||
/* inputs */
|
||||
{
|
||||
const list = template.find(".setting-bookmark-profile");
|
||||
for(const profile of profiles.profiles()) {
|
||||
const tag = $.spawn("option").val(profile.id).text(profile.profile_name);
|
||||
if(profile.id == "default")
|
||||
tag.css("font-weight", "bold");
|
||||
input_bookmark_name.on('change keydown', event => {
|
||||
const name = input_bookmark_name.val() as string;
|
||||
const valid = name.length > 3;
|
||||
input_bookmark_name.firstParent(".input-boxed").toggleClass("is-invalid", !valid);
|
||||
|
||||
list.append(tag);
|
||||
}
|
||||
if(event.type === "change" && valid) {
|
||||
selected_bookmark.display_name = name;
|
||||
label_bookmark_name.text(name);
|
||||
}
|
||||
});
|
||||
|
||||
input_server_address.on('change keydown', event => {
|
||||
const address = input_server_address.val() as string;
|
||||
const valid = !!address.match(Regex.IP_V4) || !!address.match(Regex.IP_V6) || !!address.match(Regex.DOMAIN);
|
||||
input_server_address.firstParent(".input-boxed").toggleClass("is-invalid", !valid);
|
||||
|
||||
if(valid) {
|
||||
const entry = selected_bookmark as bookmarks.Bookmark;
|
||||
let _v6_end = address.indexOf(']');
|
||||
let idx = address.lastIndexOf(':');
|
||||
if(idx != -1 && idx > _v6_end) {
|
||||
entry.server_properties.server_port = parseInt(address.substr(idx + 1));
|
||||
entry.server_properties.server_address = address.substr(0, idx);
|
||||
} else {
|
||||
entry.server_properties.server_address = address;
|
||||
entry.server_properties.server_port = 9987;
|
||||
}
|
||||
|
||||
label_server_address.text(entry.server_properties.server_address + (entry.server_properties.server_port == 9987 ? "" : (" " + entry.server_properties.server_port)));
|
||||
update_connect_info();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update_bookmarks();
|
||||
update_bookmark_list();
|
||||
update_buttons();
|
||||
|
||||
template.find(".button-close").on('click', event => modal.close());
|
||||
return template;
|
||||
return template.children();
|
||||
},
|
||||
footer: undefined,
|
||||
width: 750
|
||||
});
|
||||
|
||||
modal.htmlTag.dividerfy().find(".modal-body").addClass("modal-bookmarks");
|
||||
modal.close_listener.push(() => {
|
||||
control_bar.update_bookmarks();
|
||||
top_menu.rebuild_bookmarks();
|
||||
|
|
|
@ -9,11 +9,32 @@ namespace Modals {
|
|||
body: () => {
|
||||
const template = $("#tmpl_server_info").renderTag();
|
||||
|
||||
apply_hostbanner(server, template.find(".container-top"));
|
||||
apply_category_1(server, template, update_callbacks);
|
||||
apply_category_2(server, template, update_callbacks);
|
||||
apply_category_3(server, template, update_callbacks);
|
||||
const children = template.children();
|
||||
const top = template.find(".container-top");
|
||||
const update_values = () => {
|
||||
apply_hostbanner(server, top);
|
||||
apply_category_1(server, children, update_callbacks);
|
||||
apply_category_2(server, children, update_callbacks);
|
||||
apply_category_3(server, children, update_callbacks);
|
||||
};
|
||||
|
||||
const button_update = template.find(".button-update");
|
||||
button_update.on('click', event => {
|
||||
button_update.prop("disabled", true);
|
||||
server.updateProperties().then(() => {
|
||||
update_callbacks = [];
|
||||
update_values();
|
||||
}).catch(error => {
|
||||
log.warn(LogCategory.CLIENT, tr("Failed to refresh server properties: %o"), error);
|
||||
if(error instanceof CommandResult)
|
||||
error = error.extra_message || error.message;
|
||||
createErrorModal(tr("Refresh failed"), MessageHelper.formatMessage(tr("Failed to refresh server properties.{:br:}Error: {}"), error)).open();
|
||||
}).then(() => {
|
||||
button_update.prop("disabled", false);
|
||||
});
|
||||
});
|
||||
|
||||
update_values();
|
||||
tooltip(template);
|
||||
return template.children();
|
||||
},
|
||||
|
|
|
@ -581,6 +581,58 @@ loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
|||
priority: 10
|
||||
});
|
||||
|
||||
loader.register_task(loader.Stage.SETUP, {
|
||||
name: "page setup",
|
||||
function: async () => {
|
||||
const body = document.body;
|
||||
/* top menu */
|
||||
{
|
||||
const container = document.createElement("div");
|
||||
container.setAttribute('id', "top-menu-bar");
|
||||
body.append(container);
|
||||
}
|
||||
/* template containers */
|
||||
{
|
||||
const container = document.createElement("div");
|
||||
container.setAttribute('id', "templates");
|
||||
body.append(container);
|
||||
}
|
||||
/* sounds container */
|
||||
{
|
||||
const container = document.createElement("div");
|
||||
container.setAttribute('id', "sounds");
|
||||
body.append(container);
|
||||
}
|
||||
/* mouse move container */
|
||||
{
|
||||
const container = document.createElement("div");
|
||||
container.setAttribute('id', "mouse-move");
|
||||
|
||||
const inner_container = document.createElement("div");
|
||||
inner_container.classList.add("container");
|
||||
container.append(inner_container);
|
||||
|
||||
body.append(container);
|
||||
}
|
||||
/* tooltip container */
|
||||
{
|
||||
const container = document.createElement("div");
|
||||
container.setAttribute('id', "global-tooltip");
|
||||
|
||||
container.append(document.createElement("a"));
|
||||
|
||||
body.append(container);
|
||||
}
|
||||
},
|
||||
priority: 10
|
||||
});
|
||||
|
||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
name: "log enabled initialisation",
|
||||
function: async () => log.initialize(app.type === app.Type.CLIENT_DEBUG || app.type === app.Type.WEB_DEBUG ? LogType.TRACE : LogType.INFO),
|
||||
priority: 150
|
||||
});
|
||||
|
||||
window["Module"] = (window["Module"] || {}) as any;
|
||||
/* TeaClient */
|
||||
if(window.require) {
|
||||
|
|
30
shared/loader/certaccept.ts
Normal file
30
shared/loader/certaccept.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/// <reference path="loader.ts" />
|
||||
|
||||
/* register tasks */
|
||||
loader.register_task(loader.Stage.INITIALIZING, {
|
||||
name: "safari fix",
|
||||
function: async () => {
|
||||
/* safari remove "fix" */
|
||||
if(Element.prototype.remove === undefined)
|
||||
Object.defineProperty(Element.prototype, "remove", {
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
value: function(){
|
||||
this.parentElement.removeChild(this);
|
||||
}
|
||||
});
|
||||
},
|
||||
priority: 50
|
||||
});
|
||||
|
||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
name: "log enabled initialisation",
|
||||
function: async () => log.initialize(app.type === app.Type.CLIENT_DEBUG || app.type === app.Type.WEB_DEBUG ? LogType.TRACE : LogType.INFO),
|
||||
priority: 150
|
||||
});
|
||||
|
||||
if(!loader.running()) {
|
||||
/* we know that we want to load the app */
|
||||
loader.execute_managed();
|
||||
}
|
|
@ -214,9 +214,7 @@ namespace loader {
|
|||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
if(config.error) {
|
||||
console.error("App loading failed: %o", error);
|
||||
}
|
||||
console.error("App loading failed: %o", error);
|
||||
loader.critical_error("Failed to execute loader", "Lookup the console for more detail");
|
||||
});
|
||||
}
|
||||
|
@ -489,6 +487,7 @@ namespace loader {
|
|||
return;
|
||||
}
|
||||
|
||||
_callback_critical_called = true;
|
||||
if(_callback_critical_error) {
|
||||
_callback_critical_error(message, detail);
|
||||
return;
|
||||
|
@ -507,7 +506,7 @@ namespace loader {
|
|||
node_detail.innerHTML = detail;
|
||||
}
|
||||
|
||||
tag.style.display = "block";
|
||||
tag.classList.add("shown");
|
||||
}
|
||||
|
||||
export function critical_error_handler(handler?: ErrorHandler, override?: boolean) : ErrorHandler {
|
||||
|
@ -614,11 +613,20 @@ setTimeout(() => {
|
|||
priority: 100,
|
||||
function: async () => {
|
||||
let loader_type;
|
||||
/*
|
||||
location.search.replace(/(?:^\?|&)([a-zA-Z_]+)=([.a-zA-Z0-9]+)(?=$|&)/g, (_, key: string, value: string) => {
|
||||
if(key.toLowerCase() == "loader_target")
|
||||
loader_type = value;
|
||||
return "";
|
||||
});
|
||||
*/
|
||||
for(const node of document.head.getElementsByTagName("meta")) {
|
||||
if(node.name === "app-loader-target") {
|
||||
loader_type = node.content;
|
||||
if(loader_type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
loader_type = loader_type || "app";
|
||||
if(loader_type === "app") {
|
||||
try {
|
||||
|
@ -628,6 +636,14 @@ setTimeout(() => {
|
|||
loader.critical_error("Failed to load main app script", error);
|
||||
throw "app loader failed";
|
||||
}
|
||||
} else if(loader_type === "certaccept") {
|
||||
try {
|
||||
await loader.load_scripts(["loader/certaccept.js"]);
|
||||
} catch (error) {
|
||||
console.error("Failed to load cert accept script: %o", error);
|
||||
loader.critical_error("Failed to load cert accept script", error);
|
||||
throw "app loader failed";
|
||||
}
|
||||
} else {
|
||||
loader.critical_error("Missing loader target: " + loader_type);
|
||||
throw "Missing loader target: " + loader_type;
|
||||
|
|
91
shared/popup/certaccept/html/index.html
Normal file
91
shared/popup/certaccept/html/index.html
Normal file
|
@ -0,0 +1,91 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Certificate callback</title>
|
||||
|
||||
<div id="style">
|
||||
<link rel="stylesheet" href="css/loader/loader.css">
|
||||
</div>
|
||||
|
||||
<meta name="app-loader-target" content="certaccept">
|
||||
<div id="scripts">
|
||||
<script type="application/javascript" src="loader/loader_certaccept.min.js" defer></script>
|
||||
<script type="application/javascript" src="loader/loader_certaccept.js" defer></script>
|
||||
<script type="application/javascript" src="loader/loader.js?_<?php echo time() ?>" defer></script>
|
||||
</div>
|
||||
|
||||
<!-- required static style for the critical page and the enable javascript page -->
|
||||
<style>
|
||||
.fulloverlay {
|
||||
z-index: 10000;
|
||||
display: none;
|
||||
position: fixed;
|
||||
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
background-color: gray;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fulloverlay .container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
top: 20%;
|
||||
}
|
||||
|
||||
#critical-load.shown {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-height: 750px) {
|
||||
#critical-load .container {
|
||||
top: unset;
|
||||
}
|
||||
|
||||
#critical-load {
|
||||
font-size: .8rem;
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#critical-load.shown {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Loading screen -->
|
||||
<div class="loader" id="loader-overlay">
|
||||
<div class="half right"></div>
|
||||
<div class="half left"></div>
|
||||
<div class="bookshelf_wrapper">
|
||||
<ul class="books_list">
|
||||
<li class="book_item first"></li>
|
||||
<li class="book_item second"></li>
|
||||
<li class="book_item third"></li>
|
||||
<li class="book_item fourth"></li>
|
||||
<li class="book_item fifth"></li>
|
||||
<li class="book_item sixth"></li>
|
||||
</ul>
|
||||
<div class="shelf"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Critical load error -->
|
||||
<div class="fulloverlay" id="critical-load">
|
||||
<div class="container">
|
||||
<img src="img/loading_error_right.svg" style="height: 12em">
|
||||
<h1 class="error" style="color: red; margin-bottom: 0"></h1>
|
||||
<h3 class="detail" style="margin-top: .5em"></h3>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
59
shared/popup/certaccept/js/main.ts
Normal file
59
shared/popup/certaccept/js/main.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
function tr(text: string) { return text; }
|
||||
|
||||
const task_certificate_callback: loader.Task = {
|
||||
name: "certificate accept tester",
|
||||
function: async () => {
|
||||
Settings.initialize();
|
||||
|
||||
const certificate_accept = settings.static_global(Settings.KEY_CERTIFICATE_CALLBACK, undefined);
|
||||
if(!certificate_accept) {
|
||||
loader.critical_error("Missing certificate callback data");
|
||||
throw "missing data";
|
||||
}
|
||||
|
||||
log.info(LogCategory.IPC, tr("Using this instance as certificate callback. ID: %s"), certificate_accept);
|
||||
try {
|
||||
try {
|
||||
await bipc.get_handler().post_certificate_accpected(certificate_accept);
|
||||
} catch(e) {} //FIXME remove!
|
||||
log.info(LogCategory.IPC, tr("Other instance has acknowledged out work. Closing this window."));
|
||||
|
||||
const seconds_tag = $.spawn("a");
|
||||
|
||||
let seconds = 5;
|
||||
let interval_id;
|
||||
interval_id = setInterval(() => {
|
||||
seconds--;
|
||||
seconds_tag.text(seconds.toString());
|
||||
|
||||
if(seconds <= 0) {
|
||||
clearTimeout(interval_id);
|
||||
log.info(LogCategory.GENERAL, tr("Closing window"));
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
const message =
|
||||
"You've successfully accepted the certificate.{:br:}" +
|
||||
"This page will close in {0} seconds.";
|
||||
/*
|
||||
createInfoModal(
|
||||
tr("Certificate acccepted successfully"),
|
||||
MessageHelper.formatMessage(tr(message), seconds_tag),
|
||||
{
|
||||
closeable: false,
|
||||
footer: undefined
|
||||
}
|
||||
).open();
|
||||
*/
|
||||
//TODO!
|
||||
return;
|
||||
} catch(error) {
|
||||
log.warn(LogCategory.IPC, tr("Failed to successfully post certificate accept status: %o"), error);
|
||||
//TODO!
|
||||
}
|
||||
},
|
||||
priority: 10
|
||||
};
|
|
@ -5,5 +5,5 @@
|
|||
"exclude": [
|
||||
"../js/workers/**/*.ts"
|
||||
],
|
||||
"target_file": "../declarations/exports.d.ts"
|
||||
"target_file": "../declarations/exports_app.d.ts"
|
||||
}
|
7
shared/tsconfig/dtsconfig_loader_certaccept.json
Normal file
7
shared/tsconfig/dtsconfig_loader_certaccept.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"source_files": [
|
||||
"../loader/loader.ts",
|
||||
"../loader/certaccept.ts"
|
||||
],
|
||||
"target_file": "../declarations/exports_loader_certaccept.d.ts"
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"source_files": [
|
||||
"../js/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"../js/workers/**/*.ts"
|
||||
],
|
||||
"target_file": "../declarations/exports_packed.d.ts"
|
||||
}
|
16
shared/tsconfig/tsconfig_certaccept.json
Normal file
16
shared/tsconfig/tsconfig_certaccept.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* general shared project config */
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"plugins": [ ]
|
||||
},
|
||||
"include": [
|
||||
"../types",
|
||||
"../declarations/exports_loader_certaccept.d.ts",
|
||||
"../popup/certaccept/js/**/*.ts",
|
||||
"../js/BrowserIPC.ts"
|
||||
]
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "none",
|
||||
"outFile": "../generated/shared.js",
|
||||
"plugins": [ /* ttypescript */
|
||||
|
|
18
shared/tsconfig/tsconfig_packed_certaccept.json
Normal file
18
shared/tsconfig/tsconfig_packed_certaccept.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* general shared project config */
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "none",
|
||||
"outFile": "../generated/certaccept.js",
|
||||
"plugins": [ ]
|
||||
},
|
||||
"include": [
|
||||
"../types",
|
||||
"../declarations/exports_loader_certaccept.d.ts",
|
||||
"../popup/certaccept/js/**/*.ts",
|
||||
"../js/BrowserIPC.ts",
|
||||
"../js/settings.ts",
|
||||
"../js/proto.ts",
|
||||
"../js/log.ts"
|
||||
]
|
||||
}
|
13
shared/tsconfig/tsconfig_packed_loader_certaccept.json
Normal file
13
shared/tsconfig/tsconfig_packed_loader_certaccept.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "none",
|
||||
"sourceMap": true,
|
||||
"outFile": "../generated/loader_certaccept.js"
|
||||
},
|
||||
"include": [
|
||||
"../types",
|
||||
"../loader/loader.ts",
|
||||
"../loader/certaccept.ts"
|
||||
]
|
||||
}
|
Loading…
Add table
Reference in a new issue