From 63683eadba3130f21672eb46bd8e1ba33b5ae127 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 31 Aug 2019 18:31:01 +0200 Subject: [PATCH] save --- files.php | 46 +- shared/css/static/modal-bookmarks.scss | 594 +++++++++++++----- shared/css/static/modal-serverinfo.scss | 2 +- shared/html/index.php | 80 ++- shared/html/manifest.json | 5 +- shared/html/templates.html | 273 ++++---- shared/js/ConnectionHandler.ts | 2 +- shared/js/bookmarks.ts | 25 +- shared/js/log.ts | 10 +- shared/js/main.ts | 7 +- shared/js/settings.ts | 34 +- shared/js/ui/channel.ts | 4 +- shared/js/ui/elements/context_divider.ts | 1 + shared/js/ui/modal/ModalBookmarks.ts | 466 ++++++++------ shared/js/ui/modal/ModalServerInfo.ts | 29 +- shared/loader/app.ts | 52 ++ shared/loader/certaccept.ts | 30 + shared/loader/loader.ts | 24 +- shared/popup/certaccept/html/index.html | 91 +++ shared/popup/certaccept/js/main.ts | 59 ++ .../{dtsconfig.json => dtsconfig_app.json} | 2 +- .../tsconfig/dtsconfig_loader_certaccept.json | 7 + shared/tsconfig/dtsconfig_packed.json | 9 - shared/tsconfig/tsconfig_certaccept.json | 16 + shared/tsconfig/tsconfig_packed.json | 1 + .../tsconfig/tsconfig_packed_certaccept.json | 18 + .../tsconfig_packed_loader_certaccept.json | 13 + 27 files changed, 1322 insertions(+), 578 deletions(-) create mode 100644 shared/loader/certaccept.ts create mode 100644 shared/popup/certaccept/html/index.html create mode 100644 shared/popup/certaccept/js/main.ts rename shared/tsconfig/{dtsconfig.json => dtsconfig_app.json} (65%) create mode 100644 shared/tsconfig/dtsconfig_loader_certaccept.json delete mode 100644 shared/tsconfig/dtsconfig_packed.json create mode 100644 shared/tsconfig/tsconfig_certaccept.json create mode 100644 shared/tsconfig/tsconfig_packed_certaccept.json create mode 100644 shared/tsconfig/tsconfig_packed_loader_certaccept.json diff --git a/files.php b/files.php index 97b7dd72..f1a703f4 100644 --- a/files.php +++ b/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: diff --git a/shared/css/static/modal-bookmarks.scss b/shared/css/static/modal-bookmarks.scss index 69186daa..867fc894 100644 --- a/shared/css/static/modal-bookmarks.scss +++ b/shared/css/static/modal-bookmarks.scss @@ -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; + } + } + } + } } \ No newline at end of file diff --git a/shared/css/static/modal-serverinfo.scss b/shared/css/static/modal-serverinfo.scss index c874e944..820743f1 100644 --- a/shared/css/static/modal-serverinfo.scss +++ b/shared/css/static/modal-serverinfo.scss @@ -211,7 +211,7 @@ display: flex; flex-direction: row; - justify-content: flex-end; + justify-content: space-between; button { min-width: 8em; diff --git a/shared/html/index.php b/shared/html/index.php index 0ee6701f..1f67af08 100644 --- a/shared/html/index.php +++ b/shared/html/index.php @@ -14,23 +14,31 @@ - + + + + + + - TeaClient"; + echo "\t\tTeaClient" . PHP_EOL; + echo "\t\t" . PHP_EOL; } else { - echo "TeaSpeak-Web"; - echo ''; + echo "\t\tTeaSpeak-Web" . PHP_EOL; + echo "\t\t" . PHP_EOL; + echo "\t\t" . PHP_EOL; + // } - ?> +?> - +?> + + + - + @@ -134,13 +167,13 @@
- -

-

+ +

+

- +
@@ -179,7 +212,7 @@ - +
- - -
-
-
-
-
-
-
-
- -
+ - -
\ No newline at end of file diff --git a/shared/html/manifest.json b/shared/html/manifest.json index 61415110..0948d7bc 100644 --- a/shared/html/manifest.json +++ b/shared/html/manifest.json @@ -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" } \ No newline at end of file diff --git a/shared/html/templates.html b/shared/html/templates.html index 7684159e..eaa26820 100644 --- a/shared/html/templates.html +++ b/shared/html/templates.html @@ -4374,143 +4374,167 @@ - - - - - @@ -5175,6 +5199,7 @@
+
diff --git a/shared/js/ConnectionHandler.ts b/shared/js/ConnectionHandler.ts index a7eca860..53c815a7 100644 --- a/shared/js/ConnectionHandler.ts +++ b/shared/js/ConnectionHandler.ts @@ -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) { diff --git a/shared/js/bookmarks.ts b/shared/js/bookmarks.ts index dda6729d..8737a75d 100644 --- a/shared/js/bookmarks.ts +++ b/shared/js/bookmarks.ts @@ -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); diff --git a/shared/js/log.ts b/shared/js/log.ts index b6f50290..0e43cbb4 100644 --- a/shared/js/log.ts +++ b/shared/js/log.ts @@ -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: ?log.i18n.enabled=0 //Level Example A: ?log.level.trace.enabled=0 //Level Example B: ?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("log." + category_name.toLowerCase() + ".enabled", enabled_mapping.get(category))); } - const base_level = settings.static_global("log.level", app.type === app.Type.CLIENT_DEBUG || app.type === app.Type.WEB_DEBUG ? LogType.TRACE : LogType.INFO); + const base_level = settings.static_global("log.level", default_level); for(const level of Object.keys(LogType).map(e => parseInt(e))) { if(isNaN(level)) continue; diff --git a/shared/js/main.ts b/shared/js/main.ts index aa01cb5a..4a848694 100644 --- a/shared/js/main.ts +++ b/shared/js/main.ts @@ -9,8 +9,6 @@ /// /// -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 = { diff --git a/shared/js/settings.ts b/shared/js/settings.ts index 694dd226..3938e3bc 100644 --- a/shared/js/settings.ts +++ b/shared/js/settings.ts @@ -293,9 +293,9 @@ class Settings extends StaticSettings { key: "font_size" }; - static readonly FN_SERVER_CHANNEL_SUBSCRIBE_MODE: (channel: ChannelEntry) => SettingsKey = channel => { + static readonly FN_SERVER_CHANNEL_SUBSCRIBE_MODE: (channel_id: number) => SettingsKey = 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(); } } -} \ No newline at end of file +} + +let settings: Settings; \ No newline at end of file diff --git a/shared/js/ui/channel.ts b/shared/js/ui/channel.ts index 0339ff2e..0b584a5c 100644 --- a/shared/js/ui/channel.ts +++ b/shared/js/ui/channel.ts @@ -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) { diff --git a/shared/js/ui/elements/context_divider.ts b/shared/js/ui/elements/context_divider.ts index 282f89a6..6dd46de1 100644 --- a/shared/js/ui/elements/context_divider.ts +++ b/shared/js/ui/elements/context_divider.ts @@ -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); diff --git a/shared/js/ui/modal/ModalBookmarks.ts b/shared/js/ui/modal/ModalBookmarks.ts index 8918145f..f84f3452 100644 --- a/shared/js/ui/modal/ModalBookmarks.ts +++ b/shared/js/ui/modal/ModalBookmarks.ts @@ -3,40 +3,6 @@ /// 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 = 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 = 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 = 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", (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 = selected_bookmark; - const element = 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 = selected_bookmark; - const element = 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 = selected_bookmark; - const element = 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 = selected_bookmark; - const element = 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 = selected_bookmark; - const element = 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 = selected_bookmark; - const element = 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 = selected_bookmark; - const element = 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 = 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(); diff --git a/shared/js/ui/modal/ModalServerInfo.ts b/shared/js/ui/modal/ModalServerInfo.ts index aae9ba13..98861402 100644 --- a/shared/js/ui/modal/ModalServerInfo.ts +++ b/shared/js/ui/modal/ModalServerInfo.ts @@ -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(); }, diff --git a/shared/loader/app.ts b/shared/loader/app.ts index 6bc9bd5e..2ef06252 100644 --- a/shared/loader/app.ts +++ b/shared/loader/app.ts @@ -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) { diff --git a/shared/loader/certaccept.ts b/shared/loader/certaccept.ts new file mode 100644 index 00000000..578a4f87 --- /dev/null +++ b/shared/loader/certaccept.ts @@ -0,0 +1,30 @@ +/// + +/* 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(); +} \ No newline at end of file diff --git a/shared/loader/loader.ts b/shared/loader/loader.ts index e854fb1d..fcbff7ce 100644 --- a/shared/loader/loader.ts +++ b/shared/loader/loader.ts @@ -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; diff --git a/shared/popup/certaccept/html/index.html b/shared/popup/certaccept/html/index.html new file mode 100644 index 00000000..9fa1d363 --- /dev/null +++ b/shared/popup/certaccept/html/index.html @@ -0,0 +1,91 @@ + + + + + + Certificate callback + +
+ +
+ + +
+ + + +
+ + + + + + +
+
+
+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+
+ + +
+
+ +

+

+
+
+ + \ No newline at end of file diff --git a/shared/popup/certaccept/js/main.ts b/shared/popup/certaccept/js/main.ts new file mode 100644 index 00000000..0b19944c --- /dev/null +++ b/shared/popup/certaccept/js/main.ts @@ -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 +}; \ No newline at end of file diff --git a/shared/tsconfig/dtsconfig.json b/shared/tsconfig/dtsconfig_app.json similarity index 65% rename from shared/tsconfig/dtsconfig.json rename to shared/tsconfig/dtsconfig_app.json index 50cc1d6e..3b78ff87 100644 --- a/shared/tsconfig/dtsconfig.json +++ b/shared/tsconfig/dtsconfig_app.json @@ -5,5 +5,5 @@ "exclude": [ "../js/workers/**/*.ts" ], - "target_file": "../declarations/exports.d.ts" + "target_file": "../declarations/exports_app.d.ts" } diff --git a/shared/tsconfig/dtsconfig_loader_certaccept.json b/shared/tsconfig/dtsconfig_loader_certaccept.json new file mode 100644 index 00000000..a52a4d85 --- /dev/null +++ b/shared/tsconfig/dtsconfig_loader_certaccept.json @@ -0,0 +1,7 @@ +{ + "source_files": [ + "../loader/loader.ts", + "../loader/certaccept.ts" + ], + "target_file": "../declarations/exports_loader_certaccept.d.ts" +} \ No newline at end of file diff --git a/shared/tsconfig/dtsconfig_packed.json b/shared/tsconfig/dtsconfig_packed.json deleted file mode 100644 index 0da6c7c6..00000000 --- a/shared/tsconfig/dtsconfig_packed.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "source_files": [ - "../js/**/*.ts" - ], - "exclude": [ - "../js/workers/**/*.ts" - ], - "target_file": "../declarations/exports_packed.d.ts" -} diff --git a/shared/tsconfig/tsconfig_certaccept.json b/shared/tsconfig/tsconfig_certaccept.json new file mode 100644 index 00000000..d4e1b999 --- /dev/null +++ b/shared/tsconfig/tsconfig_certaccept.json @@ -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" + ] +} \ No newline at end of file diff --git a/shared/tsconfig/tsconfig_packed.json b/shared/tsconfig/tsconfig_packed.json index 7bec7c94..85bfe0e1 100644 --- a/shared/tsconfig/tsconfig_packed.json +++ b/shared/tsconfig/tsconfig_packed.json @@ -5,6 +5,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "target": "es6", "module": "none", "outFile": "../generated/shared.js", "plugins": [ /* ttypescript */ diff --git a/shared/tsconfig/tsconfig_packed_certaccept.json b/shared/tsconfig/tsconfig_packed_certaccept.json new file mode 100644 index 00000000..bcc0b2f1 --- /dev/null +++ b/shared/tsconfig/tsconfig_packed_certaccept.json @@ -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" + ] +} \ No newline at end of file diff --git a/shared/tsconfig/tsconfig_packed_loader_certaccept.json b/shared/tsconfig/tsconfig_packed_loader_certaccept.json new file mode 100644 index 00000000..30df9e8a --- /dev/null +++ b/shared/tsconfig/tsconfig_packed_loader_certaccept.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "none", + "sourceMap": true, + "outFile": "../generated/loader_certaccept.js" + }, + "include": [ + "../types", + "../loader/loader.ts", + "../loader/certaccept.ts" + ] +} \ No newline at end of file