Improved the initial page load
parent
479168c26e
commit
702f0bae43
|
@ -4,7 +4,9 @@
|
|||
- Saving last away state and message
|
||||
- Saving last query show state
|
||||
- Removing the hostbutton when we're disconnected from the server
|
||||
|
||||
- Improved main pages loader speed as well inlining the initial js/css sources
|
||||
This ensures that the error & loading animation loads properly regardless of any errors
|
||||
|
||||
* **04.03.20**
|
||||
- Implemented the new music bot playlist song list
|
||||
- Implemented the missing server log message builders
|
||||
|
|
18
file.ts
18
file.ts
|
@ -40,12 +40,28 @@ const APP_FILE_LIST_SHARED_SOURCE: ProjectResource[] = [
|
|||
},
|
||||
{ /* javascript files as manifest.json */
|
||||
"type": "js",
|
||||
"search-pattern": /.*$/,
|
||||
"search-pattern": /.*\.(js|json)$/,
|
||||
"build-target": "dev|rel",
|
||||
|
||||
"path": "js/",
|
||||
"local-path": "./dist/"
|
||||
},
|
||||
{ /* javascript files as manifest.json */
|
||||
"type": "html",
|
||||
"search-pattern": /.*\.html$/,
|
||||
"build-target": "dev|rel",
|
||||
|
||||
"path": "./",
|
||||
"local-path": "./dist/"
|
||||
},
|
||||
{ /* Loader css file (only required in dev mode. In release it gets inlined) */
|
||||
"type": "css",
|
||||
"search-pattern": /.*\.css$/,
|
||||
"build-target": "dev",
|
||||
|
||||
"path": "css/",
|
||||
"local-path": "./loader/css/"
|
||||
},
|
||||
{ /* shared developer single css files */
|
||||
"type": "css",
|
||||
"search-pattern": /.*\.css$/,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as loader from "./targets/app";
|
||||
import * as loader_base from "./loader/loader";
|
||||
|
||||
window["loader"] = loader_base;
|
||||
/* let the loader register himself at the window first */
|
||||
setTimeout(loader.run, 0);
|
||||
|
|
|
@ -309,85 +309,78 @@ export const templates = template_loader;
|
|||
/* Hello World message */
|
||||
{
|
||||
|
||||
const hello_world = () => {
|
||||
const clog = console.log;
|
||||
const print_security = () => {
|
||||
{
|
||||
const css = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 42px",
|
||||
"font-weight: bold",
|
||||
"-webkit-text-stroke: 2px black",
|
||||
"color: red"
|
||||
].join(";");
|
||||
clog("%c ", "font-size: 100px;");
|
||||
clog("%cSecurity warning:", css);
|
||||
}
|
||||
{
|
||||
const css = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 18px",
|
||||
"font-weight: bold"
|
||||
].join(";");
|
||||
|
||||
clog("%cPasting anything in here could give attackers access to your data.", css);
|
||||
clog("%cUnless you understand exactly what you are doing, close this window and stay safe.", css);
|
||||
clog("%c ", "font-size: 100px;");
|
||||
}
|
||||
};
|
||||
|
||||
/* print the hello world */
|
||||
const clog = console.log;
|
||||
const print_security = () => {
|
||||
{
|
||||
const css = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 72px",
|
||||
"font-size: 42px",
|
||||
"font-weight: bold",
|
||||
"-webkit-text-stroke: 2px black",
|
||||
"color: #18BC9C"
|
||||
"color: red"
|
||||
].join(";");
|
||||
clog("%cHey, hold on!", css);
|
||||
clog("%c ", "font-size: 100px;");
|
||||
clog("%cSecurity warning:", css);
|
||||
}
|
||||
{
|
||||
const css = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 26px",
|
||||
"font-size: 18px",
|
||||
"font-weight: bold"
|
||||
].join(";");
|
||||
|
||||
const css_2 = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 26px",
|
||||
"font-weight: bold",
|
||||
"color: blue"
|
||||
].join(";");
|
||||
|
||||
const display_detect = /./;
|
||||
display_detect.toString = function() { print_security(); return ""; };
|
||||
|
||||
clog("%cLovely to see you using and debugging the TeaSpeak-Web client.", css);
|
||||
clog("%cIf you have some good ideas or already done some incredible changes,", css);
|
||||
clog("%cyou'll be may interested to share them here: %chttps://github.com/TeaSpeak/TeaWeb", css, css_2);
|
||||
clog("%c ", display_detect);
|
||||
clog("%cPasting anything in here could give attackers access to your data.", css);
|
||||
clog("%cUnless you understand exactly what you are doing, close this window and stay safe.", css);
|
||||
clog("%c ", "font-size: 100px;");
|
||||
}
|
||||
};
|
||||
|
||||
try { /* lets try to print it as VM code :)*/
|
||||
let hello_world_code = hello_world.toString();
|
||||
hello_world_code = hello_world_code.substr(hello_world_code.indexOf('() => {') + 8);
|
||||
hello_world_code = hello_world_code.substring(0, hello_world_code.lastIndexOf("}"));
|
||||
|
||||
//Look aheads are not possible with firefox
|
||||
//hello_world_code = hello_world_code.replace(/(?<!const|let)(?<=^([^"'/]|"[^"]*"|'[^']*'|`[^`]*`|\/[^/]*\/)*) /gm, ""); /* replace all spaces */
|
||||
hello_world_code = hello_world_code.replace(/[\n\r]/g, ""); /* replace as new lines */
|
||||
|
||||
eval(hello_world_code);
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
hello_world();
|
||||
/* print the hello world */
|
||||
{
|
||||
const css = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 72px",
|
||||
"font-weight: bold",
|
||||
"-webkit-text-stroke: 2px black",
|
||||
"color: #18BC9C"
|
||||
].join(";");
|
||||
clog("%cHey, hold on!", css);
|
||||
}
|
||||
}
|
||||
{
|
||||
const css = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 26px",
|
||||
"font-weight: bold"
|
||||
].join(";");
|
||||
|
||||
const css_2 = [
|
||||
"display: block",
|
||||
"text-align: center",
|
||||
"font-size: 26px",
|
||||
"font-weight: bold",
|
||||
"color: blue"
|
||||
].join(";");
|
||||
|
||||
const display_detect = /./;
|
||||
display_detect.toString = function() { print_security(); return ""; };
|
||||
|
||||
clog("%cLovely to see you using and debugging the TeaSpeak-Web client.", css);
|
||||
clog("%cIf you have some good ideas or already done some incredible changes,", css);
|
||||
clog("%cyou'll be may interested to share them here: %chttps://github.com/TeaSpeak/TeaWeb", css, css_2);
|
||||
clog("%c ", display_detect);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading error image (async) */
|
||||
const init_error_image = () => {
|
||||
const node = document.getElementById("load-error-image");
|
||||
const image = document.createElement("img");
|
||||
image.src = node.getAttribute("x-src");
|
||||
image.style.height = "12em";
|
||||
node.replaceWith(image);
|
||||
};
|
||||
setTimeout(init_error_image, 100);
|
|
@ -152,6 +152,15 @@
|
|||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/clean-css": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.1.tgz",
|
||||
"integrity": "sha512-A1HQhQ0hkvqqByJMgg+Wiv9p9XdoYEzuwm11SVo1mX2/4PSdhjcrUlilJQoqLscIheC51t1D5g+EFWCXZ2VTQQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/dompurify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.0.1.tgz",
|
||||
|
@ -161,6 +170,12 @@
|
|||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"@types/ejs": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.0.2.tgz",
|
||||
"integrity": "sha512-+nriFZYDz+C+6SWzJp0jHrGvyzL3Sg63u1vRlH1AfViyaT4oTod+MtfZ0YMNYXzO7ybFkdx4ZaBwBtLwdYkReQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/emscripten": {
|
||||
"version": "1.39.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.2.tgz",
|
||||
|
@ -201,6 +216,17 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/html-minifier": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-3.5.3.tgz",
|
||||
"integrity": "sha512-j1P/4PcWVVCPEy5lofcHnQ6BtXz9tHGiFPWzqm7TtGuWZEfCHEP446HlkSNc9fQgNJaJZ6ewPtp2aaFla/Uerg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/clean-css": "*",
|
||||
"@types/relateurl": "*",
|
||||
"@types/uglify-js": "*"
|
||||
}
|
||||
},
|
||||
"@types/html-minifier-terser": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.0.0.tgz",
|
||||
|
@ -274,6 +300,12 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/relateurl": {
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.28.tgz",
|
||||
"integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/sha256": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/sha256/-/sha256-0.2.0.tgz",
|
||||
|
@ -2385,9 +2417,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"ejs": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
|
||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.2.tgz",
|
||||
"integrity": "sha512-IncmUpn1yN84hy2shb0POJ80FWrfGNY0cxO9f4v+/sG7qcBvAtVWUA1IdzY/8EYUmOVhoKJVdJjNd3AZcnxOjA==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
|
@ -4940,6 +4972,57 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"html-minifier": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
|
||||
"integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camel-case": "^3.0.0",
|
||||
"clean-css": "^4.2.1",
|
||||
"commander": "^2.19.0",
|
||||
"he": "^1.2.0",
|
||||
"param-case": "^2.1.1",
|
||||
"relateurl": "^0.2.7",
|
||||
"uglify-js": "^3.5.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"camel-case": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
|
||||
"integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"no-case": "^2.2.0",
|
||||
"upper-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"lower-case": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
||||
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
|
||||
"dev": true
|
||||
},
|
||||
"no-case": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
|
||||
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lower-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"param-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
||||
"integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-minifier-terser": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.0.5.tgz",
|
||||
|
@ -9676,6 +9759,16 @@
|
|||
"integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.1.tgz",
|
||||
"integrity": "sha512-W7KxyzeaQmZvUFbGj4+YFshhVrMBGSg2IbcYAjGWGvx8DHvJMclbTDMpffdxFUGPBHjIytk7KJUR/KUXstUGDw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "~2.20.3",
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"unc-path-regex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
|
@ -9815,6 +9908,12 @@
|
|||
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
|
||||
"dev": true
|
||||
},
|
||||
"upper-case": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
||||
"integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
|
@ -10882,6 +10981,12 @@
|
|||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"ejs": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
|
||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
|
|
10
package.json
10
package.json
|
@ -5,21 +5,17 @@
|
|||
"main": "main.js",
|
||||
"directories": {},
|
||||
"scripts": {
|
||||
"compile-sass": "sass --update shared/css/:shared/css/ web/css/:web/css/ client/css/:client/css/ vendor/:vendor/",
|
||||
"compile-sass": "sass --update shared/css/:shared/css/ loader/css/:loader/css/ web/css/:web/css/ client/css/:client/css/ vendor/:vendor/",
|
||||
"compile-project-base": "tsc -p tsbaseconfig.json",
|
||||
|
||||
"dtsgen": "node tools/dtsgen/index.js",
|
||||
"trgen": "node tools/trgen/index.js",
|
||||
"sass": "sass",
|
||||
"tsc": "tsc",
|
||||
|
||||
"start": "npm run compile-project-base && node file.js ndevelop",
|
||||
|
||||
"build-web": "webpack --config webpack-web.config.js",
|
||||
"watch-web": "webpack --watch --config webpack-web.config.js",
|
||||
"build-client": "webpack --config webpack-client.config.js",
|
||||
"watch-client": "webpack --watch --config webpack-client.config.js",
|
||||
|
||||
"generate-i18n-gtranslate": "node shared/generate_i18n_gtranslate.js"
|
||||
},
|
||||
"author": "TeaSpeak (WolverinDEV)",
|
||||
|
@ -27,8 +23,10 @@
|
|||
"devDependencies": {
|
||||
"@google-cloud/translate": "^5.3.0",
|
||||
"@types/dompurify": "^2.0.1",
|
||||
"@types/ejs": "^3.0.2",
|
||||
"@types/emscripten": "^1.38.0",
|
||||
"@types/fs-extra": "^8.0.1",
|
||||
"@types/html-minifier": "^3.5.3",
|
||||
"@types/jquery": "^3.3.34",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/moment": "^2.13.0",
|
||||
|
@ -42,10 +40,12 @@
|
|||
"clean-webpack-plugin": "^3.0.0",
|
||||
"css-loader": "^3.4.2",
|
||||
"csso-cli": "^2.0.2",
|
||||
"ejs": "^3.0.2",
|
||||
"exports-loader": "^0.7.0",
|
||||
"fs-extra": "latest",
|
||||
"gulp": "^4.0.2",
|
||||
"html-loader": "^1.0.0",
|
||||
"html-minifier": "^4.0.0",
|
||||
"html-webpack-plugin": "^4.0.3",
|
||||
"mime-types": "^2.1.24",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@import "./mixin";
|
||||
@import "./properties";
|
||||
@import "mixin";
|
||||
@import "properties";
|
||||
|
||||
//$color_client_normal: #bebebe;
|
||||
$color_client_normal: #cccccc;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "./mixin.scss";
|
||||
@import "mixin";
|
||||
|
||||
.hostbanner {
|
||||
.container-hostbanner {
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
<%
|
||||
/* given build compile */
|
||||
var build_target;
|
||||
var initial_script;
|
||||
var initial_css;
|
||||
%>
|
||||
|
||||
$WEB_CLIENT = (!isset($CLIENT) || !$CLIENT) && http_response_code() !== false || (defined("TEA_SERVE") && TEA_SERVE);
|
||||
$localhost = false;
|
||||
if(gethostname() == "WolverinDEV")
|
||||
$localhost = true;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
@ -25,39 +22,22 @@
|
|||
<!-- TODO Needs some fix -->
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<?php
|
||||
if(!$WEB_CLIENT) {
|
||||
echo "\t\t<title>TeaClient</title>" . PHP_EOL;
|
||||
echo "\t\t<meta name='og:title' content='TeaClient'>" . PHP_EOL;
|
||||
} else {
|
||||
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">
|
||||
}
|
||||
?>
|
||||
<% if(build_target === "client") { %>
|
||||
<title>TeaClient</title>
|
||||
<meta name='og:title' content='TeaClient'>
|
||||
<% } else { %>
|
||||
<title>TeaSpeak-Web</title>
|
||||
<meta name='og:title' content='TeaSpeak-Web'>
|
||||
<link rel='shortcut icon' href='img/favicon/teacup.png' type='image/x-icon'>
|
||||
<!-- <link rel="apple-touch-icon" sizes="194x194" href="/apple-touch-icon.png" type="image/png"> -->
|
||||
<% } %>
|
||||
|
||||
<!-- PHP generated properties -->
|
||||
<x-properties id="properties" style="display: none">
|
||||
<?php
|
||||
function spawn_property($name, $value, $element_id = null)
|
||||
{
|
||||
if(isset($value))
|
||||
echo "\t\t\t<x-property key=\"" . $name . "\" " . (isset($element_id) ? "id=\"" . $element_id . "\" " : "") . "value=\"" . urlencode($value) . "\"></x-property>\r\n";
|
||||
}
|
||||
|
||||
spawn_property('connect_default_host', $localhost ? "localhost" : "ts.TeaSpeak.de");
|
||||
spawn_property('localhost_debug', $localhost ? "true" : "false");
|
||||
|
||||
if(defined("TEA_SERVE") && TEA_SERVE) {
|
||||
$version = "0000000";
|
||||
} else {
|
||||
$version = file_get_contents("./version");
|
||||
if ($version === false)
|
||||
$version = "unknown";
|
||||
}
|
||||
spawn_property("version", $version, "app_version");
|
||||
?>
|
||||
<!--
|
||||
We don't need to put any properties down here.
|
||||
But this tag is here to not brick the settings class.
|
||||
But it will be removed quite soonly as soon this class has been fixed
|
||||
-->
|
||||
</x-properties>
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
|
@ -124,6 +104,8 @@
|
|||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<%- initial_css %>
|
||||
</head>
|
||||
<body>
|
||||
<!-- No javascript error -->
|
||||
|
@ -139,18 +121,8 @@
|
|||
</noscript>
|
||||
|
||||
<!-- loader setup -->
|
||||
<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" async defer></script>
|
||||
<script type="application/javascript" src="loader/loader_app.js" async defer></script>
|
||||
-->
|
||||
<script type="application/javascript" src="js/loader.js?_<?php echo time() ?>" async defer></script>
|
||||
</div>
|
||||
<div id="style"></div>
|
||||
<div id="scripts"></div>
|
||||
|
||||
<!-- Loading screen -->
|
||||
<div class="loader" id="loader-overlay">
|
||||
|
@ -172,13 +144,15 @@
|
|||
<!-- Critical load error -->
|
||||
<div class="fulloverlay" id="critical-load">
|
||||
<div class="container">
|
||||
<img src="img/loading_error_right.svg" style="height: 12em">
|
||||
<!-- We're loading the error image via JS so improve first page content loaded speed -->
|
||||
<div id="load-error-image" x-src="img/loading_error_right.svg"></div>
|
||||
|
||||
<h1 class="error" style="color: red; margin-bottom: 0"></h1>
|
||||
<h3 class="detail" style="margin-top: .5em"></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- debugging close -->
|
||||
<%# <!-- Old debgging stuff back for the days where we designed the client -->
|
||||
<?php if($localhost && false) { ?>
|
||||
<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"> -->
|
||||
|
@ -241,6 +215,7 @@
|
|||
};
|
||||
setTimeout(() => init($), 1000);
|
||||
</script>
|
||||
<?php } ?>
|
||||
%>
|
||||
<%- initial_script %>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,4 @@
|
|||
import {createModal} from "tc-shared/ui/elements/Modal";
|
||||
import * as loader from "tc-loader";
|
||||
import {LogCategory} from "tc-shared/log";
|
||||
import * as log from "tc-shared/log";
|
||||
|
||||
|
@ -10,29 +9,16 @@ function format_date(date: number) {
|
|||
}
|
||||
|
||||
export function spawnAbout() {
|
||||
const app_version = (() => {
|
||||
const version_node = document.getElementById("app_version");
|
||||
if(!version_node) return undefined;
|
||||
|
||||
const version = version_node.hasAttribute("value") ? version_node.getAttribute("value") : undefined;
|
||||
if(!version) return undefined;
|
||||
|
||||
if(version == "unknown" || version.replace(/0+/, "").length == 0)
|
||||
return undefined;
|
||||
|
||||
return version;
|
||||
})();
|
||||
|
||||
const connectModal = createModal({
|
||||
header: tr("About"),
|
||||
body: () => {
|
||||
let tag = $("#tmpl_about").renderTag({
|
||||
client: __build.target !== "web",
|
||||
|
||||
version_client: __build.target === "web" ? app_version || "in-dev" : "loading...",
|
||||
version_ui: app_version || "in-dev",
|
||||
version_client: __build.target === "web" ? __build.version || "in-dev" : "loading...",
|
||||
version_ui: __build.version || "in-dev",
|
||||
|
||||
version_timestamp: !!app_version ? format_date(Date.now()) : "--"
|
||||
version_timestamp: format_date(__build.timestamp)
|
||||
});
|
||||
return tag;
|
||||
},
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
"webpack/build-definitions.d.ts",
|
||||
"webpack/ManifestPlugin.ts",
|
||||
"webpack/EJSGenerator.ts",
|
||||
"webpack/WatLoader.ts",
|
||||
|
||||
"file.ts"
|
||||
|
|
|
@ -3,6 +3,7 @@ import * as fs from "fs";
|
|||
import trtransformer from "./tools/trgen/ts_transformer";
|
||||
import {exec} from "child_process";
|
||||
import * as util from "util";
|
||||
import EJSGenerator = require("./webpack/EJSGenerator");
|
||||
|
||||
const path = require('path');
|
||||
const webpack = require("webpack");
|
||||
|
@ -74,7 +75,24 @@ export const config = async (target: "web" | "client") => { return {
|
|||
minSize: 1024 * 8,
|
||||
maxSize: 1024 * 128
|
||||
}),
|
||||
new webpack.DefinePlugin(await generate_definitions(target))
|
||||
new webpack.DefinePlugin(await generate_definitions(target)),
|
||||
|
||||
new EJSGenerator({
|
||||
variables: {
|
||||
build_target: target
|
||||
},
|
||||
input: path.join(__dirname, "shared/html/index.html.ejs"),
|
||||
output: path.join(__dirname, "dist/index.html"),
|
||||
initialJSEntryChunk: "loader",
|
||||
minify: !isDevelopment,
|
||||
embedInitialJSEntryChunk: !isDevelopment,
|
||||
|
||||
embedInitialCSSFile: !isDevelopment,
|
||||
initialCSSFile: {
|
||||
localFile: path.join(__dirname, "loader/css/loader.css"),
|
||||
publicFile: "css/loader.css"
|
||||
}
|
||||
})
|
||||
].filter(e => !!e),
|
||||
module: {
|
||||
rules: [
|
||||
|
@ -142,13 +160,8 @@ export const config = async (target: "web" | "client") => { return {
|
|||
{"tc-loader": "window loader"}
|
||||
] as any[],
|
||||
output: {
|
||||
filename: (chunkData) => {
|
||||
if(chunkData.chunk.name === "loader")
|
||||
return "loader.js";
|
||||
|
||||
return '[name].js';
|
||||
},
|
||||
chunkFilename: "[name].js",
|
||||
filename: isDevelopment ? "[name].[contenthash].js" : "[contenthash].js",
|
||||
chunkFilename: isDevelopment ? "[name].[contenthash].js" : "[contenthash].js",
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
publicPath: "js/"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
import * as webpack from "webpack";
|
||||
import * as ejs from "ejs";
|
||||
import * as fs from "fs";
|
||||
import * as util from "util";
|
||||
import * as minifier from "html-minifier";
|
||||
import * as path from "path";
|
||||
import {Compilation} from "webpack";
|
||||
|
||||
interface Options {
|
||||
input: string,
|
||||
output: string,
|
||||
|
||||
minify?: boolean,
|
||||
|
||||
initialJSEntryChunk: string,
|
||||
embedInitialJSEntryChunk?: boolean,
|
||||
|
||||
initialCSSFile: {
|
||||
localFile: string,
|
||||
publicFile: string
|
||||
},
|
||||
embedInitialCSSFile?: boolean,
|
||||
|
||||
variables?: {[name: string]: any};
|
||||
}
|
||||
|
||||
class EJSGenerator {
|
||||
readonly options: Options;
|
||||
|
||||
constructor(options: Options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
private async generate_entry_js_tag(compilation: Compilation) {
|
||||
const entry_group = compilation.chunkGroups.find(e => e.options.name === this.options.initialJSEntryChunk);
|
||||
if(!entry_group) return; /* not the correct compilation */
|
||||
if(entry_group.chunks.length !== 1) throw "Unsupported entry chunk size. We only support one at the moment.";
|
||||
if(entry_group.chunks[0].files.length !== 1)
|
||||
throw "Entry chunk has too many files. We only support to inline one!";
|
||||
const file = entry_group.chunks[0].files[0];
|
||||
if(path.extname(file) !== ".js")
|
||||
throw "Entry chunk file has unknown extension";
|
||||
|
||||
if(!this.options.embedInitialJSEntryChunk) {
|
||||
return '<script type="application/javascript" src=' + compilation.compiler.options.output.publicPath + file + ' async defer></script>';
|
||||
} else {
|
||||
const script = await util.promisify(fs.readFile)(path.join(compilation.compiler.outputPath, file));
|
||||
return `<script type="application/javascript">${script}</script>`;
|
||||
}
|
||||
}
|
||||
|
||||
private async generate_entry_css_tag() {
|
||||
if(this.options.embedInitialCSSFile) {
|
||||
const style = await util.promisify(fs.readFile)(this.options.initialCSSFile.localFile);
|
||||
return `<style>${style}</style>`
|
||||
} else {
|
||||
//<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">
|
||||
return `<link rel="preload" as="style" onload="this.rel='stylesheet'" href="${this.options.initialCSSFile.publicFile}">`
|
||||
}
|
||||
}
|
||||
|
||||
apply(compiler: webpack.Compiler) {
|
||||
compiler.hooks.afterEmit.tapPromise(this.constructor.name, async compilation => {
|
||||
const input = await util.promisify(fs.readFile)(this.options.input);
|
||||
const variables = Object.assign({}, this.options.variables);
|
||||
|
||||
variables["initial_script"] = await this.generate_entry_js_tag(compilation);
|
||||
variables["initial_css"] = await this.generate_entry_css_tag();
|
||||
|
||||
let generated = await ejs.render(input.toString(), variables, {
|
||||
beautify: false /* uglify is a bit dump and does not understands ES6 */
|
||||
});
|
||||
|
||||
if(this.options.minify) {
|
||||
generated = minifier.minify(generated, {
|
||||
html5: true,
|
||||
|
||||
collapseWhitespace: true,
|
||||
removeComments: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeTagWhitespace: true,
|
||||
minifyCSS: true,
|
||||
minifyJS: true,
|
||||
minifyURLs: true
|
||||
});
|
||||
}
|
||||
|
||||
await util.promisify(fs.writeFile)(this.options.output, generated);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export = EJSGenerator;
|
|
@ -24,8 +24,9 @@ class ManifestGenerator {
|
|||
const modules = [];
|
||||
|
||||
for(const chunk of chunk_group.chunks) {
|
||||
if(!chunk.files.length) continue;
|
||||
if(chunk.files.length !== 1) {
|
||||
console.error("Expected only on file per chunk but got " + chunk.files.length);
|
||||
console.error("Expected only one file per chunk but got " + chunk.files.length);
|
||||
chunk.files.forEach(e => console.log(" - %s", e));
|
||||
throw "expected only one file per chunk";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue