Improved the initial page load
This commit is contained in:
parent
479168c26e
commit
702f0bae43
16 changed files with 343 additions and 158 deletions
|
@ -4,7 +4,9 @@
|
||||||
- Saving last away state and message
|
- Saving last away state and message
|
||||||
- Saving last query show state
|
- Saving last query show state
|
||||||
- Removing the hostbutton when we're disconnected from the server
|
- 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**
|
* **04.03.20**
|
||||||
- Implemented the new music bot playlist song list
|
- Implemented the new music bot playlist song list
|
||||||
- Implemented the missing server log message builders
|
- 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 */
|
{ /* javascript files as manifest.json */
|
||||||
"type": "js",
|
"type": "js",
|
||||||
"search-pattern": /.*$/,
|
"search-pattern": /.*\.(js|json)$/,
|
||||||
"build-target": "dev|rel",
|
"build-target": "dev|rel",
|
||||||
|
|
||||||
"path": "js/",
|
"path": "js/",
|
||||||
"local-path": "./dist/"
|
"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 */
|
{ /* shared developer single css files */
|
||||||
"type": "css",
|
"type": "css",
|
||||||
"search-pattern": /.*\.css$/,
|
"search-pattern": /.*\.css$/,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import * as loader from "./targets/app";
|
import * as loader from "./targets/app";
|
||||||
import * as loader_base from "./loader/loader";
|
import * as loader_base from "./loader/loader";
|
||||||
|
|
||||||
window["loader"] = loader_base;
|
window["loader"] = loader_base;
|
||||||
/* let the loader register himself at the window first */
|
/* let the loader register himself at the window first */
|
||||||
setTimeout(loader.run, 0);
|
setTimeout(loader.run, 0);
|
||||||
|
|
|
@ -309,85 +309,78 @@ export const templates = template_loader;
|
||||||
/* Hello World message */
|
/* Hello World message */
|
||||||
{
|
{
|
||||||
|
|
||||||
const hello_world = () => {
|
const clog = console.log;
|
||||||
const clog = console.log;
|
const print_security = () => {
|
||||||
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 css = [
|
const css = [
|
||||||
"display: block",
|
"display: block",
|
||||||
"text-align: center",
|
"text-align: center",
|
||||||
"font-size: 72px",
|
"font-size: 42px",
|
||||||
"font-weight: bold",
|
"font-weight: bold",
|
||||||
"-webkit-text-stroke: 2px black",
|
"-webkit-text-stroke: 2px black",
|
||||||
"color: #18BC9C"
|
"color: red"
|
||||||
].join(";");
|
].join(";");
|
||||||
clog("%cHey, hold on!", css);
|
clog("%c ", "font-size: 100px;");
|
||||||
|
clog("%cSecurity warning:", css);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const css = [
|
const css = [
|
||||||
"display: block",
|
"display: block",
|
||||||
"text-align: center",
|
"text-align: center",
|
||||||
"font-size: 26px",
|
"font-size: 18px",
|
||||||
"font-weight: bold"
|
"font-weight: bold"
|
||||||
].join(";");
|
].join(";");
|
||||||
|
|
||||||
const css_2 = [
|
clog("%cPasting anything in here could give attackers access to your data.", css);
|
||||||
"display: block",
|
clog("%cUnless you understand exactly what you are doing, close this window and stay safe.", css);
|
||||||
"text-align: center",
|
clog("%c ", "font-size: 100px;");
|
||||||
"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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try { /* lets try to print it as VM code :)*/
|
/* print the hello world */
|
||||||
let hello_world_code = hello_world.toString();
|
{
|
||||||
hello_world_code = hello_world_code.substr(hello_world_code.indexOf('() => {') + 8);
|
const css = [
|
||||||
hello_world_code = hello_world_code.substring(0, hello_world_code.lastIndexOf("}"));
|
"display: block",
|
||||||
|
"text-align: center",
|
||||||
//Look aheads are not possible with firefox
|
"font-size: 72px",
|
||||||
//hello_world_code = hello_world_code.replace(/(?<!const|let)(?<=^([^"'/]|"[^"]*"|'[^']*'|`[^`]*`|\/[^/]*\/)*) /gm, ""); /* replace all spaces */
|
"font-weight: bold",
|
||||||
hello_world_code = hello_world_code.replace(/[\n\r]/g, ""); /* replace as new lines */
|
"-webkit-text-stroke: 2px black",
|
||||||
|
"color: #18BC9C"
|
||||||
eval(hello_world_code);
|
].join(";");
|
||||||
} catch(e) {
|
clog("%cHey, hold on!", css);
|
||||||
console.error(e);
|
|
||||||
hello_world();
|
|
||||||
}
|
}
|
||||||
}
|
{
|
||||||
|
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);
|
111
package-lock.json
generated
111
package-lock.json
generated
|
@ -152,6 +152,15 @@
|
||||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
||||||
"dev": true
|
"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": {
|
"@types/dompurify": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.0.1.tgz",
|
||||||
|
@ -161,6 +170,12 @@
|
||||||
"@types/trusted-types": "*"
|
"@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": {
|
"@types/emscripten": {
|
||||||
"version": "1.39.2",
|
"version": "1.39.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.2.tgz",
|
||||||
|
@ -201,6 +216,17 @@
|
||||||
"@types/node": "*"
|
"@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": {
|
"@types/html-minifier-terser": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.0.0.tgz",
|
||||||
|
@ -274,6 +300,12 @@
|
||||||
"@types/react": "*"
|
"@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": {
|
"@types/sha256": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/sha256/-/sha256-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/sha256/-/sha256-0.2.0.tgz",
|
||||||
|
@ -2385,9 +2417,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ejs": {
|
"ejs": {
|
||||||
"version": "2.7.4",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.2.tgz",
|
||||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
|
"integrity": "sha512-IncmUpn1yN84hy2shb0POJ80FWrfGNY0cxO9f4v+/sG7qcBvAtVWUA1IdzY/8EYUmOVhoKJVdJjNd3AZcnxOjA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"elliptic": {
|
"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": {
|
"html-minifier-terser": {
|
||||||
"version": "5.0.5",
|
"version": "5.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.0.5.tgz",
|
"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==",
|
"integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
|
||||||
"dev": true
|
"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": {
|
"unc-path-regex": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
"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==",
|
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
|
||||||
"dev": true
|
"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": {
|
"uri-js": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||||
|
@ -10882,6 +10981,12 @@
|
||||||
"supports-color": "^5.3.0"
|
"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": {
|
"supports-color": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"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",
|
"main": "main.js",
|
||||||
"directories": {},
|
"directories": {},
|
||||||
"scripts": {
|
"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",
|
"compile-project-base": "tsc -p tsbaseconfig.json",
|
||||||
|
|
||||||
"dtsgen": "node tools/dtsgen/index.js",
|
"dtsgen": "node tools/dtsgen/index.js",
|
||||||
"trgen": "node tools/trgen/index.js",
|
"trgen": "node tools/trgen/index.js",
|
||||||
"sass": "sass",
|
"sass": "sass",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
|
|
||||||
"start": "npm run compile-project-base && node file.js ndevelop",
|
"start": "npm run compile-project-base && node file.js ndevelop",
|
||||||
|
|
||||||
"build-web": "webpack --config webpack-web.config.js",
|
"build-web": "webpack --config webpack-web.config.js",
|
||||||
"watch-web": "webpack --watch --config webpack-web.config.js",
|
"watch-web": "webpack --watch --config webpack-web.config.js",
|
||||||
"build-client": "webpack --config webpack-client.config.js",
|
"build-client": "webpack --config webpack-client.config.js",
|
||||||
"watch-client": "webpack --watch --config webpack-client.config.js",
|
"watch-client": "webpack --watch --config webpack-client.config.js",
|
||||||
|
|
||||||
"generate-i18n-gtranslate": "node shared/generate_i18n_gtranslate.js"
|
"generate-i18n-gtranslate": "node shared/generate_i18n_gtranslate.js"
|
||||||
},
|
},
|
||||||
"author": "TeaSpeak (WolverinDEV)",
|
"author": "TeaSpeak (WolverinDEV)",
|
||||||
|
@ -27,8 +23,10 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@google-cloud/translate": "^5.3.0",
|
"@google-cloud/translate": "^5.3.0",
|
||||||
"@types/dompurify": "^2.0.1",
|
"@types/dompurify": "^2.0.1",
|
||||||
|
"@types/ejs": "^3.0.2",
|
||||||
"@types/emscripten": "^1.38.0",
|
"@types/emscripten": "^1.38.0",
|
||||||
"@types/fs-extra": "^8.0.1",
|
"@types/fs-extra": "^8.0.1",
|
||||||
|
"@types/html-minifier": "^3.5.3",
|
||||||
"@types/jquery": "^3.3.34",
|
"@types/jquery": "^3.3.34",
|
||||||
"@types/lodash": "^4.14.149",
|
"@types/lodash": "^4.14.149",
|
||||||
"@types/moment": "^2.13.0",
|
"@types/moment": "^2.13.0",
|
||||||
|
@ -42,10 +40,12 @@
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"css-loader": "^3.4.2",
|
"css-loader": "^3.4.2",
|
||||||
"csso-cli": "^2.0.2",
|
"csso-cli": "^2.0.2",
|
||||||
|
"ejs": "^3.0.2",
|
||||||
"exports-loader": "^0.7.0",
|
"exports-loader": "^0.7.0",
|
||||||
"fs-extra": "latest",
|
"fs-extra": "latest",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"html-loader": "^1.0.0",
|
"html-loader": "^1.0.0",
|
||||||
|
"html-minifier": "^4.0.0",
|
||||||
"html-webpack-plugin": "^4.0.3",
|
"html-webpack-plugin": "^4.0.3",
|
||||||
"mime-types": "^2.1.24",
|
"mime-types": "^2.1.24",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@import "./mixin";
|
@import "mixin";
|
||||||
@import "./properties";
|
@import "properties";
|
||||||
|
|
||||||
//$color_client_normal: #bebebe;
|
//$color_client_normal: #bebebe;
|
||||||
$color_client_normal: #cccccc;
|
$color_client_normal: #cccccc;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "./mixin.scss";
|
@import "mixin";
|
||||||
|
|
||||||
.hostbanner {
|
.hostbanner {
|
||||||
.container-hostbanner {
|
.container-hostbanner {
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
<?php
|
<%
|
||||||
ini_set('display_errors', 1);
|
/* given build compile */
|
||||||
ini_set('display_startup_errors', 1);
|
var build_target;
|
||||||
error_reporting(E_ALL);
|
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>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -25,39 +22,22 @@
|
||||||
<!-- TODO Needs some fix -->
|
<!-- TODO Needs some fix -->
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
|
|
||||||
<?php
|
<% if(build_target === "client") { %>
|
||||||
if(!$WEB_CLIENT) {
|
<title>TeaClient</title>
|
||||||
echo "\t\t<title>TeaClient</title>" . PHP_EOL;
|
<meta name='og:title' content='TeaClient'>
|
||||||
echo "\t\t<meta name='og:title' content='TeaClient'>" . PHP_EOL;
|
<% } else { %>
|
||||||
} else {
|
<title>TeaSpeak-Web</title>
|
||||||
echo "\t\t<title>TeaSpeak-Web</title>" . PHP_EOL;
|
<meta name='og:title' content='TeaSpeak-Web'>
|
||||||
echo "\t\t<meta name='og:title' content='TeaSpeak-Web'>" . PHP_EOL;
|
<link rel='shortcut icon' href='img/favicon/teacup.png' type='image/x-icon'>
|
||||||
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"> -->
|
||||||
//<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">
|
<x-properties id="properties" style="display: none">
|
||||||
<?php
|
<!--
|
||||||
function spawn_property($name, $value, $element_id = null)
|
We don't need to put any properties down here.
|
||||||
{
|
But this tag is here to not brick the settings class.
|
||||||
if(isset($value))
|
But it will be removed quite soonly as soon this class has been fixed
|
||||||
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");
|
|
||||||
?>
|
|
||||||
</x-properties>
|
</x-properties>
|
||||||
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
@ -124,6 +104,8 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<%- initial_css %>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- No javascript error -->
|
<!-- No javascript error -->
|
||||||
|
@ -139,18 +121,8 @@
|
||||||
</noscript>
|
</noscript>
|
||||||
|
|
||||||
<!-- loader setup -->
|
<!-- loader setup -->
|
||||||
<div id="style">
|
<div id="style"></div>
|
||||||
<link rel="stylesheet" href="css/loader/loader.css">
|
<div id="scripts"></div>
|
||||||
</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>
|
|
||||||
|
|
||||||
<!-- Loading screen -->
|
<!-- Loading screen -->
|
||||||
<div class="loader" id="loader-overlay">
|
<div class="loader" id="loader-overlay">
|
||||||
|
@ -172,13 +144,15 @@
|
||||||
<!-- Critical load error -->
|
<!-- Critical load error -->
|
||||||
<div class="fulloverlay" id="critical-load">
|
<div class="fulloverlay" id="critical-load">
|
||||||
<div class="container">
|
<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>
|
<h1 class="error" style="color: red; margin-bottom: 0"></h1>
|
||||||
<h3 class="detail" style="margin-top: .5em"></h3>
|
<h3 class="detail" style="margin-top: .5em"></h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- debugging close -->
|
<%# <!-- Old debgging stuff back for the days where we designed the client -->
|
||||||
<?php if($localhost && false) { ?>
|
<?php if($localhost && false) { ?>
|
||||||
<div id="spoiler-style" style="z-index: 1000000; position: absolute; display: block; background: white; right: 5px; left: 5px; top: 34px;">
|
<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="https://www.chromatic-solutions.de/teaspeak/window/connect_opened.png"> -->
|
||||||
|
@ -241,6 +215,7 @@
|
||||||
};
|
};
|
||||||
setTimeout(() => init($), 1000);
|
setTimeout(() => init($), 1000);
|
||||||
</script>
|
</script>
|
||||||
<?php } ?>
|
%>
|
||||||
|
<%- initial_script %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,5 +1,4 @@
|
||||||
import {createModal} from "tc-shared/ui/elements/Modal";
|
import {createModal} from "tc-shared/ui/elements/Modal";
|
||||||
import * as loader from "tc-loader";
|
|
||||||
import {LogCategory} from "tc-shared/log";
|
import {LogCategory} from "tc-shared/log";
|
||||||
import * as log from "tc-shared/log";
|
import * as log from "tc-shared/log";
|
||||||
|
|
||||||
|
@ -10,29 +9,16 @@ function format_date(date: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function spawnAbout() {
|
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({
|
const connectModal = createModal({
|
||||||
header: tr("About"),
|
header: tr("About"),
|
||||||
body: () => {
|
body: () => {
|
||||||
let tag = $("#tmpl_about").renderTag({
|
let tag = $("#tmpl_about").renderTag({
|
||||||
client: __build.target !== "web",
|
client: __build.target !== "web",
|
||||||
|
|
||||||
version_client: __build.target === "web" ? app_version || "in-dev" : "loading...",
|
version_client: __build.target === "web" ? __build.version || "in-dev" : "loading...",
|
||||||
version_ui: app_version || "in-dev",
|
version_ui: __build.version || "in-dev",
|
||||||
|
|
||||||
version_timestamp: !!app_version ? format_date(Date.now()) : "--"
|
version_timestamp: format_date(__build.timestamp)
|
||||||
});
|
});
|
||||||
return tag;
|
return tag;
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
"webpack/build-definitions.d.ts",
|
"webpack/build-definitions.d.ts",
|
||||||
"webpack/ManifestPlugin.ts",
|
"webpack/ManifestPlugin.ts",
|
||||||
|
"webpack/EJSGenerator.ts",
|
||||||
"webpack/WatLoader.ts",
|
"webpack/WatLoader.ts",
|
||||||
|
|
||||||
"file.ts"
|
"file.ts"
|
||||||
|
|
|
@ -3,6 +3,7 @@ import * as fs from "fs";
|
||||||
import trtransformer from "./tools/trgen/ts_transformer";
|
import trtransformer from "./tools/trgen/ts_transformer";
|
||||||
import {exec} from "child_process";
|
import {exec} from "child_process";
|
||||||
import * as util from "util";
|
import * as util from "util";
|
||||||
|
import EJSGenerator = require("./webpack/EJSGenerator");
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
|
@ -74,7 +75,24 @@ export const config = async (target: "web" | "client") => { return {
|
||||||
minSize: 1024 * 8,
|
minSize: 1024 * 8,
|
||||||
maxSize: 1024 * 128
|
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),
|
].filter(e => !!e),
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
@ -142,13 +160,8 @@ export const config = async (target: "web" | "client") => { return {
|
||||||
{"tc-loader": "window loader"}
|
{"tc-loader": "window loader"}
|
||||||
] as any[],
|
] as any[],
|
||||||
output: {
|
output: {
|
||||||
filename: (chunkData) => {
|
filename: isDevelopment ? "[name].[contenthash].js" : "[contenthash].js",
|
||||||
if(chunkData.chunk.name === "loader")
|
chunkFilename: isDevelopment ? "[name].[contenthash].js" : "[contenthash].js",
|
||||||
return "loader.js";
|
|
||||||
|
|
||||||
return '[name].js';
|
|
||||||
},
|
|
||||||
chunkFilename: "[name].js",
|
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
publicPath: "js/"
|
publicPath: "js/"
|
||||||
},
|
},
|
||||||
|
|
94
webpack/EJSGenerator.ts
Normal file
94
webpack/EJSGenerator.ts
Normal file
|
@ -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 = [];
|
const modules = [];
|
||||||
|
|
||||||
for(const chunk of chunk_group.chunks) {
|
for(const chunk of chunk_group.chunks) {
|
||||||
|
if(!chunk.files.length) continue;
|
||||||
if(chunk.files.length !== 1) {
|
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));
|
chunk.files.forEach(e => console.log(" - %s", e));
|
||||||
throw "expected only one file per chunk";
|
throw "expected only one file per chunk";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue