Some more small rework and cleanup
parent
e2be859266
commit
85acd6dd56
|
@ -1,6 +1,6 @@
|
|||
import * as loader from "./loader/loader";
|
||||
import {Stage} from "./loader/loader";
|
||||
import {getUrlParameter} from "./loader/utils";
|
||||
import {getUrlParameter} from "./loader/Utils";
|
||||
|
||||
let overlay: HTMLDivElement;
|
||||
let setupContainer: HTMLDivElement;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
import "core-js/stable";
|
||||
import "./polifill";
|
||||
import "./css";
|
||||
|
||||
import {ApplicationLoader} from "./loader/loader";
|
||||
import {getUrlParameter} from "./loader/Utils";
|
||||
|
||||
/* let the loader register himself at the window first */
|
||||
const target = getUrlParameter("loader-target") || "app";
|
||||
console.info("Loading app with loader \"%s\"", target);
|
||||
|
||||
let appLoader: ApplicationLoader;
|
||||
if(target === "empty") {
|
||||
appLoader = new (require("./targets/empty").default);
|
||||
} else if(target === "manifest") {
|
||||
appLoader = new (require("./targets/maifest-target").default);
|
||||
} else {
|
||||
appLoader = new (require("./targets/app").default);
|
||||
}
|
||||
setTimeout(() => appLoader.execute(), 0);
|
||||
|
||||
export {};
|
||||
|
||||
if(__build.target === "client") {
|
||||
/* do this so we don't get a react dev tools warning within the client */
|
||||
if(!('__REACT_DEVTOOLS_GLOBAL_HOOK__' in window)) {
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {};
|
||||
}
|
||||
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject = function () {};
|
||||
}
|
||||
|
||||
/* Hello World message */
|
||||
{
|
||||
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 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);
|
||||
}
|
||||
}
|
|
@ -1,35 +1,14 @@
|
|||
import "core-js/stable";
|
||||
import "./polifill";
|
||||
import "./css";
|
||||
|
||||
import * as loader from "./loader/loader";
|
||||
import {ApplicationLoader} from "./loader/loader";
|
||||
import {getUrlParameter} from "./loader/utils";
|
||||
|
||||
if(window["loader"]) {
|
||||
throw "an loader instance has already been defined";
|
||||
}
|
||||
window["loader"] = loader;
|
||||
/* let the loader register himself at the window first */
|
||||
|
||||
const target = getUrlParameter("loader-target") || "app";
|
||||
console.info("Loading app with loader \"%s\"", target);
|
||||
export * from "./loader/loader";
|
||||
export * as loaderAnimation from "./animation";
|
||||
|
||||
let appLoader: ApplicationLoader;
|
||||
if(target === "empty") {
|
||||
appLoader = new (require("./targets/empty").default);
|
||||
} else if(target === "manifest") {
|
||||
appLoader = new (require("./targets/maifest-target").default);
|
||||
} else {
|
||||
appLoader = new (require("./targets/app").default);
|
||||
import "./bootstrap";
|
||||
|
||||
/* FIXME: This is glue! */
|
||||
if(window["loader"]) {
|
||||
throw "an loader instance has already been defined";
|
||||
}
|
||||
setTimeout(() => appLoader.execute(), 0);
|
||||
|
||||
export {};
|
||||
|
||||
if(__build.target === "client") {
|
||||
/* do this so we don't get a react dev tools warning within the client */
|
||||
if(!('__REACT_DEVTOOLS_GLOBAL_HOOK__' in window))
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {};
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject = function () {};
|
||||
}
|
||||
window["loader"] = module.exports;
|
|
@ -1,11 +1,12 @@
|
|||
import {config, critical_error, SourcePath} from "./loader";
|
||||
import {load_parallel, LoadCallback, LoadSyntaxError, ParallelOptions, script_name} from "./utils";
|
||||
import {executeParallelLoad, LoadCallback, LoadSyntaxError, ParallelOptions} from "./Utils";
|
||||
|
||||
let _script_promises: {[key: string]: Promise<void>} = {};
|
||||
|
||||
function load_script_url(url: string) : Promise<void> {
|
||||
if(typeof _script_promises[url] === "object")
|
||||
if(typeof _script_promises[url] === "object") {
|
||||
return _script_promises[url];
|
||||
}
|
||||
|
||||
return (_script_promises[url] = new Promise((resolve, reject) => {
|
||||
const script_tag: HTMLScriptElement = document.createElement("script");
|
||||
|
@ -67,40 +68,18 @@ export interface Options {
|
|||
cache_tag?: string;
|
||||
}
|
||||
|
||||
export async function load(path: SourcePath, options: Options) : Promise<void> {
|
||||
if(Array.isArray(path)) { //We have fallback scripts
|
||||
return load(path[0], options).catch(error => {
|
||||
if(error instanceof LoadSyntaxError)
|
||||
return Promise.reject(error);
|
||||
|
||||
if(path.length > 1)
|
||||
return load(path.slice(1), options);
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
} else {
|
||||
const source = typeof(path) === "string" ? {url: path, depends: []} : path;
|
||||
if(source.url.length == 0) return Promise.resolve();
|
||||
|
||||
/* await depends */
|
||||
for(const depend of source.depends) {
|
||||
if(!_script_promises[depend])
|
||||
throw "Missing dependency " + depend;
|
||||
await _script_promises[depend];
|
||||
}
|
||||
|
||||
await load_script_url(source.url + (options.cache_tag || ""));
|
||||
}
|
||||
export async function loadScript(path: SourcePath, options: Options) : Promise<void> {
|
||||
await load_script_url(path + (options.cache_tag || ""));
|
||||
}
|
||||
|
||||
type MultipleOptions = Options | ParallelOptions;
|
||||
export async function load_multiple(paths: SourcePath[], options: MultipleOptions, callback?: LoadCallback<SourcePath>) : Promise<void> {
|
||||
const result = await load_parallel<SourcePath>(paths, e => load(e, options), e => script_name(e, false), options, callback);
|
||||
export async function loadScripts(paths: SourcePath[], options: MultipleOptions, callback?: LoadCallback<SourcePath>) : Promise<void> {
|
||||
const result = await executeParallelLoad<SourcePath>(paths, e => loadScript(e, options), e => e, options, callback);
|
||||
if(result.failed.length > 0) {
|
||||
if(config.error) {
|
||||
console.error("Failed to load the following scripts:");
|
||||
for(const script of result.failed) {
|
||||
const sname = script_name(script.request, false);
|
||||
const sname = script.request;
|
||||
if(script.error instanceof LoadSyntaxError) {
|
||||
const source = script.error.source as Error;
|
||||
if(source.name === "TypeError") {
|
||||
|
@ -126,11 +105,11 @@ export async function load_multiple(paths: SourcePath[], options: MultipleOption
|
|||
} else if(typeof error === "string") {
|
||||
errorMessage = error;
|
||||
} else {
|
||||
console.error("Script %s loading error: %o", script_name(result.failed[0].request, false), error);
|
||||
console.error("Script %s loading error: %o", result.failed[0].request, error);
|
||||
errorMessage = "View the browser console for more information!";
|
||||
}
|
||||
critical_error("Failed to load script " + script_name(result.failed[0].request, true), errorMessage);
|
||||
critical_error("Failed to load script " + result.failed[0].request, errorMessage);
|
||||
}
|
||||
throw "failed to load script " + script_name(result.failed[0].request, false) + " (" + errorMessage + ")";
|
||||
throw "failed to load script " + result.failed[0].request + " (" + errorMessage + ")";
|
||||
}
|
||||
}
|
|
@ -1,18 +1,22 @@
|
|||
import {config, critical_error, SourcePath} from "./loader";
|
||||
import {load_parallel, LoadCallback, LoadSyntaxError, ParallelOptions, script_name} from "./utils";
|
||||
import {executeParallelLoad, LoadCallback, LoadSyntaxError, ParallelOptions} from "./Utils";
|
||||
|
||||
let _style_promises: {[key: string]: Promise<void>} = {};
|
||||
let loadedStyles: {[key: string]: Promise<void>} = {};
|
||||
|
||||
function load_style_url(url: string) : Promise<void> {
|
||||
if(typeof _style_promises[url] === "object")
|
||||
return _style_promises[url];
|
||||
if(typeof loadedStyles[url] === "object") {
|
||||
return loadedStyles[url];
|
||||
}
|
||||
|
||||
return (_style_promises[url] = new Promise((resolve, reject) => {
|
||||
return (loadedStyles[url] = new Promise((resolve, reject) => {
|
||||
const tag: HTMLLinkElement = document.createElement("link");
|
||||
|
||||
let error = false;
|
||||
const error_handler = (event: ErrorEvent) => {
|
||||
if(config.verbose) console.log("msg: %o, url: %o, line: %o, col: %o, error: %o", event.message, event.filename, event.lineno, event.colno, event.error);
|
||||
if(config.verbose) {
|
||||
console.log("msg: %o, url: %o, line: %o, col: %o, error: %o", event.message, event.filename, event.lineno, event.colno, event.error);
|
||||
}
|
||||
|
||||
if(event.filename == tag.href) { //FIXME!
|
||||
window.removeEventListener('error', error_handler as any);
|
||||
|
||||
|
@ -42,8 +46,9 @@ function load_style_url(url: string) : Promise<void> {
|
|||
tag.onerror = error => {
|
||||
cleanup();
|
||||
tag.remove();
|
||||
if(config.error)
|
||||
if(config.error) {
|
||||
console.error("File load error for file %s: %o", url, error);
|
||||
}
|
||||
reject("failed to load file " + url);
|
||||
};
|
||||
tag.onload = () => {
|
||||
|
@ -80,14 +85,14 @@ function load_style_url(url: string) : Promise<void> {
|
|||
|
||||
document.getElementById("style").appendChild(tag);
|
||||
tag.href = config.baseUrl + url;
|
||||
})).then(result => {
|
||||
})).then(() => {
|
||||
/* cleanup memory */
|
||||
_style_promises[url] = Promise.resolve(); /* this promise does not holds the whole script tag and other memory */
|
||||
return _style_promises[url];
|
||||
loadedStyles[url] = Promise.resolve(); /* this promise does not holds the whole script tag and other memory */
|
||||
return loadedStyles[url];
|
||||
}).catch(error => {
|
||||
/* cleanup memory */
|
||||
_style_promises[url] = Promise.reject(error); /* this promise does not holds the whole script tag and other memory */
|
||||
return _style_promises[url];
|
||||
loadedStyles[url] = Promise.reject(error); /* this promise does not holds the whole script tag and other memory */
|
||||
return loadedStyles[url];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -95,39 +100,18 @@ export interface Options {
|
|||
cache_tag?: string;
|
||||
}
|
||||
|
||||
export async function load(path: SourcePath, options: Options) : Promise<void> {
|
||||
if(Array.isArray(path)) { //We have fallback scripts
|
||||
return load(path[0], options).catch(error => {
|
||||
if(error instanceof LoadSyntaxError)
|
||||
return Promise.reject(error);
|
||||
|
||||
if(path.length > 1)
|
||||
return load(path.slice(1), options);
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
} else {
|
||||
const source = typeof(path) === "string" ? {url: path, depends: []} : path;
|
||||
if(source.url.length == 0) return Promise.resolve();
|
||||
|
||||
/* await depends */
|
||||
for(const depend of source.depends) {
|
||||
if(!_style_promises[depend])
|
||||
throw "Missing dependency " + depend;
|
||||
await _style_promises[depend];
|
||||
}
|
||||
await load_style_url(source.url + (options.cache_tag || ""));
|
||||
}
|
||||
export async function loadStyle(path: SourcePath, options: Options) : Promise<void> {
|
||||
await load_style_url(path + (options.cache_tag || ""));
|
||||
}
|
||||
|
||||
export type MultipleOptions = Options | ParallelOptions;
|
||||
export async function load_multiple(paths: SourcePath[], options: MultipleOptions, callback?: LoadCallback<SourcePath>) : Promise<void> {
|
||||
const result = await load_parallel<SourcePath>(paths, e => load(e, options), e => script_name(e, false), options, callback);
|
||||
export async function loadStyles(paths: SourcePath[], options: MultipleOptions, callback?: LoadCallback<SourcePath>) : Promise<void> {
|
||||
const result = await executeParallelLoad<SourcePath>(paths, e => loadStyle(e, options), e => e, options, callback);
|
||||
if(result.failed.length > 0) {
|
||||
if(config.error) {
|
||||
console.error("Failed to load the following style sheets:");
|
||||
for(const style of result.failed) {
|
||||
const sname = script_name(style.request, false);
|
||||
const sname = style.request;
|
||||
if(style.error instanceof LoadSyntaxError) {
|
||||
console.log(" - %s: %o", sname, style.error.source);
|
||||
} else {
|
||||
|
@ -136,7 +120,7 @@ export async function load_multiple(paths: SourcePath[], options: MultipleOption
|
|||
}
|
||||
}
|
||||
|
||||
critical_error("Failed to load style " + script_name(result.failed[0].request, true) + " <br>" + "View the browser console for more information!");
|
||||
throw "failed to load style " + script_name(result.failed[0].request, false);
|
||||
critical_error("Failed to load style <code>" + result.failed[0].request + "</code><br>" + "View the browser console for more information!");
|
||||
throw "failed to load style " + result.failed[0].request;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
import {SourcePath} from "./loader";
|
||||
import {Options} from "./script_loader";
|
||||
import {Options} from "./ScriptLoader";
|
||||
|
||||
export const getUrlParameter = key => {
|
||||
const match = location.search.match(new RegExp("(.*[?&]|^)" + key + "=([^&]+)($|&.*)"));
|
||||
if(!match)
|
||||
if(!match) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return match[2];
|
||||
};
|
||||
|
@ -16,24 +16,15 @@ export class LoadSyntaxError {
|
|||
}
|
||||
}
|
||||
|
||||
export function script_name(path: SourcePath, html: boolean) {
|
||||
if(Array.isArray(path)) {
|
||||
return path.filter(e => !!e).map(e => script_name(e, html)).join(" or ");
|
||||
} else if(typeof(path) === "string")
|
||||
return html ? "<code>" + path + "</code>" : path;
|
||||
else
|
||||
return html ? "<code>" + path.url + "</code>" : path.url;
|
||||
}
|
||||
|
||||
export interface ParallelOptions extends Options {
|
||||
max_parallel_requests?: number
|
||||
maxParallelRequests?: number
|
||||
}
|
||||
|
||||
export interface ParallelResult<T> {
|
||||
succeeded: T[];
|
||||
failed: {
|
||||
request: T,
|
||||
error: T
|
||||
error: any
|
||||
}[],
|
||||
|
||||
skipped: T[];
|
||||
|
@ -41,15 +32,22 @@ export interface ParallelResult<T> {
|
|||
|
||||
export type LoadCallback<T> = (entry: T, state: "loading" | "loaded") => void;
|
||||
|
||||
export async function load_parallel<T>(requests: T[], executor: (_: T) => Promise<void>, stringify: (_: T) => string, options: ParallelOptions, callback?: LoadCallback<T>) : Promise<ParallelResult<T>> {
|
||||
export async function executeParallelLoad<T>(
|
||||
requests: T[],
|
||||
executor: (_: T) => Promise<void>,
|
||||
stringify: (_: T) => string,
|
||||
options: ParallelOptions,
|
||||
callback?: LoadCallback<T>
|
||||
) : Promise<ParallelResult<T>> {
|
||||
const result: ParallelResult<T> = { failed: [], succeeded: [], skipped: [] };
|
||||
const pendingRequests = requests.slice(0).reverse(); /* we're only able to pop from the back */
|
||||
const currentRequests = {};
|
||||
|
||||
if(typeof callback === "undefined")
|
||||
if(typeof callback === "undefined") {
|
||||
callback = () => {};
|
||||
}
|
||||
|
||||
const maxParallelRequests = typeof options.max_parallel_requests === "number" && options.max_parallel_requests > 0 ? options.max_parallel_requests : Number.MAX_SAFE_INTEGER;
|
||||
const maxParallelRequests = typeof options.maxParallelRequests === "number" && options.maxParallelRequests > 0 ? options.maxParallelRequests : Number.MAX_SAFE_INTEGER;
|
||||
while (pendingRequests.length > 0) {
|
||||
while(Object.keys(currentRequests).length < maxParallelRequests) {
|
||||
const element = pendingRequests.pop();
|
||||
|
@ -60,8 +58,10 @@ export async function load_parallel<T>(requests: T[], executor: (_: T) => Promis
|
|||
delete currentRequests[name];
|
||||
callback(element, "loaded");
|
||||
});
|
||||
if(pendingRequests.length == 0)
|
||||
|
||||
if(pendingRequests.length == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -69,8 +69,9 @@ export async function load_parallel<T>(requests: T[], executor: (_: T) => Promis
|
|||
* This should also not throw because any errors will be caught before.
|
||||
*/
|
||||
await Promise.race(Object.keys(currentRequests).map(e => currentRequests[e]));
|
||||
if(result.failed.length > 0)
|
||||
if(result.failed.length > 0) {
|
||||
break; /* finish loading the other requests and than show the error */
|
||||
}
|
||||
}
|
||||
await Promise.all(Object.keys(currentRequests).map(e => currentRequests[e]));
|
||||
result.skipped.push(...pendingRequests);
|
|
@ -1,7 +1,5 @@
|
|||
import * as script_loader from "./script_loader";
|
||||
import * as style_loader from "./style_loader";
|
||||
import * as Animation from "../animation";
|
||||
import {getUrlParameter} from "./utils";
|
||||
import {getUrlParameter} from "./Utils";
|
||||
|
||||
export interface ApplicationLoader {
|
||||
execute();
|
||||
|
@ -76,30 +74,9 @@ export enum Stage {
|
|||
DONE
|
||||
}
|
||||
|
||||
let cache_tag: string | undefined;
|
||||
let currentStage: Stage = undefined;
|
||||
const tasks: {[key:number]: InternalTask[]} = {};
|
||||
|
||||
/* test if all files shall be load from cache or fetch again */
|
||||
function loader_cache_tag() {
|
||||
if(__build.mode === "debug") {
|
||||
cache_tag = "?_ts=" + Date.now();
|
||||
return;
|
||||
}
|
||||
|
||||
const cached_version = localStorage.getItem("cached_version");
|
||||
if(!cached_version || cached_version !== __build.version) {
|
||||
register_task(Stage.LOADED, {
|
||||
priority: 0,
|
||||
name: "cached version updater",
|
||||
function: async () => {
|
||||
localStorage.setItem("cached_version", __build.version);
|
||||
}
|
||||
});
|
||||
}
|
||||
cache_tag = "?_version=" + __build.version;
|
||||
}
|
||||
|
||||
export type ModuleMapping = {
|
||||
application: string,
|
||||
modules: {
|
||||
|
@ -174,22 +151,23 @@ export function setCurrentTaskName(taskId: number, name: string) {
|
|||
}
|
||||
|
||||
export async function execute(customLoadingAnimations: boolean) {
|
||||
if(!await Animation.initialize(customLoadingAnimations))
|
||||
if(!await Animation.initialize(customLoadingAnimations)) {
|
||||
return;
|
||||
}
|
||||
|
||||
loader_cache_tag();
|
||||
|
||||
const load_begin = Date.now();
|
||||
const timestampBegin = Date.now();
|
||||
|
||||
let begin: number = 0;
|
||||
let end: number = Date.now();
|
||||
while(currentStage <= Stage.LOADED || typeof(currentStage) === "undefined") {
|
||||
while(currentStage <= Stage.LOADED || typeof currentStage === "undefined") {
|
||||
|
||||
let pendingTasks: InternalTask[] = [];
|
||||
while((tasks[currentStage] || []).length > 0) {
|
||||
if(pendingTasks.length == 0 || pendingTasks[0].priority == tasks[currentStage][0].priority) {
|
||||
pendingTasks.push(tasks[currentStage].pop());
|
||||
} else break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const errors: {
|
||||
|
@ -282,7 +260,7 @@ export async function execute(customLoadingAnimations: boolean) {
|
|||
}
|
||||
|
||||
if(config.verbose)
|
||||
console.debug("[loader] finished loader. (Total time: %dms)", Date.now() - load_begin);
|
||||
console.debug("[loader] finished loader. (Total time: %dms)", Date.now() - timestampBegin);
|
||||
|
||||
Animation.finalize(config.abortAnimationOnFinish);
|
||||
}
|
||||
|
@ -351,79 +329,4 @@ export function critical_error_handler(handler?: ErrorHandler, override?: boolea
|
|||
}
|
||||
|
||||
/* loaders */
|
||||
export type DependSource = {
|
||||
url: string;
|
||||
depends: string[];
|
||||
}
|
||||
export type SourcePath = string | DependSource | string[];
|
||||
|
||||
export const scripts = script_loader;
|
||||
export const style = style_loader;
|
||||
|
||||
/* Hello World message */
|
||||
{
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
export type SourcePath = string;
|
|
@ -1,8 +1,9 @@
|
|||
import * as loader from "./loader/loader";
|
||||
import {config} from "./loader/loader";
|
||||
import {script_name} from "./loader/utils";
|
||||
import {loadStyles} from "./loader/StyleLoader";
|
||||
import {loadScripts} from "./loader/ScriptLoader";
|
||||
|
||||
export interface TeaManifest {
|
||||
export interface ApplicationManifest {
|
||||
version: number;
|
||||
|
||||
chunks: {
|
||||
|
@ -24,15 +25,17 @@ export interface TeaManifest {
|
|||
};
|
||||
}
|
||||
|
||||
let manifest: TeaManifest;
|
||||
export async function loadManifest() : Promise<TeaManifest> {
|
||||
let manifest: ApplicationManifest;
|
||||
export async function loadManifest() : Promise<ApplicationManifest> {
|
||||
if(manifest) {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(config.baseUrl + "/manifest.json?_date=" + Date.now());
|
||||
if(!response.ok) throw response.status + " " + response.statusText;
|
||||
if(!response.ok) {
|
||||
throw response.status + " " + response.statusText;
|
||||
}
|
||||
|
||||
manifest = await response.json();
|
||||
} catch(error) {
|
||||
|
@ -40,8 +43,10 @@ export async function loadManifest() : Promise<TeaManifest> {
|
|||
loader.critical_error("Failed to load manifest.json", error);
|
||||
throw "failed to load manifest.json";
|
||||
}
|
||||
if(manifest.version !== 2)
|
||||
|
||||
if(manifest.version !== 2) {
|
||||
throw "invalid manifest version";
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
@ -51,30 +56,31 @@ export async function loadManifestTarget(chunkName: string, taskId: number) {
|
|||
loader.critical_error("Missing entry chunk in manifest.json", "Chunk " + chunkName + " is missing.");
|
||||
throw "missing entry chunk";
|
||||
}
|
||||
|
||||
loader.module_mapping().push({
|
||||
application: chunkName,
|
||||
modules: manifest.chunks[chunkName].modules
|
||||
});
|
||||
|
||||
loader.style.load_multiple(manifest.chunks[chunkName].css_files.map(e => e.file), {
|
||||
await loadStyles(manifest.chunks[chunkName].css_files.map(e => e.file), {
|
||||
cache_tag: undefined,
|
||||
max_parallel_requests: 4
|
||||
maxParallelRequests: 4
|
||||
}, (entry, state) => {
|
||||
if(state !== "loading") {
|
||||
if (state !== "loading") {
|
||||
return;
|
||||
}
|
||||
|
||||
loader.setCurrentTaskName(taskId, script_name(entry, false));
|
||||
loader.setCurrentTaskName(taskId, entry);
|
||||
});
|
||||
|
||||
await loader.scripts.load_multiple(manifest.chunks[chunkName].files.map(e => e.file), {
|
||||
await loadScripts(manifest.chunks[chunkName].files.map(e => e.file), {
|
||||
cache_tag: undefined,
|
||||
max_parallel_requests: 4
|
||||
maxParallelRequests: 4
|
||||
}, (script, state) => {
|
||||
if(state !== "loading") {
|
||||
return;
|
||||
}
|
||||
|
||||
loader.setCurrentTaskName(taskId, script_name(script, false));
|
||||
loader.setCurrentTaskName(taskId, script);
|
||||
});
|
||||
}
|
|
@ -3,21 +3,13 @@ import * as loader from "../loader/loader";
|
|||
import {ApplicationLoader} from "../loader/loader";
|
||||
import {loadManifest, loadManifestTarget} from "../maifest";
|
||||
|
||||
/* all javascript loaders */
|
||||
const loader_javascript = {
|
||||
load_scripts: async taskId => {
|
||||
loader.setCurrentTaskName(taskId, "manifest");
|
||||
await loadManifest();
|
||||
await loadManifestTarget(__build.entry_chunk_name, taskId);
|
||||
}
|
||||
};
|
||||
|
||||
loader.register_task(loader.Stage.INITIALIZING, {
|
||||
name: "secure tester",
|
||||
function: async () => {
|
||||
/* we need https or localhost to use some things like the storage API */
|
||||
if(typeof isSecureContext === "undefined")
|
||||
if(typeof isSecureContext === "undefined") {
|
||||
(window as any)["isSecureContext"] = location.protocol !== 'https:' || location.hostname === 'localhost';
|
||||
}
|
||||
|
||||
if(!isSecureContext) {
|
||||
loader.critical_error("TeaWeb cant run on unsecured sides.", "App requires to be loaded via HTTPS!");
|
||||
|
@ -28,8 +20,12 @@ loader.register_task(loader.Stage.INITIALIZING, {
|
|||
});
|
||||
|
||||
loader.register_task(loader.Stage.JAVASCRIPT, {
|
||||
name: "scripts",
|
||||
function: loader_javascript.load_scripts,
|
||||
name: "manifest",
|
||||
function: async taskId => {
|
||||
loader.setCurrentTaskName(taskId, "manifest");
|
||||
await loadManifest();
|
||||
await loadManifestTarget(__build.entry_chunk_name, taskId);
|
||||
},
|
||||
priority: 10
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import "./shared";
|
|||
import * as loader from "../loader/loader";
|
||||
import {ApplicationLoader, Stage} from "../loader/loader";
|
||||
import {loadManifest, loadManifestTarget} from "../maifest";
|
||||
import {getUrlParameter} from "../loader/utils";
|
||||
import {getUrlParameter} from "../loader/Utils";
|
||||
|
||||
export default class implements ApplicationLoader {
|
||||
execute() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as loader from "../loader/loader";
|
||||
import {Stage} from "../loader/loader";
|
||||
import {BrowserInfo, detect as detectBrowser,} from "detect-browser";
|
||||
import {detect as detectBrowser} from "detect-browser";
|
||||
|
||||
loader.register_task(Stage.SETUP, {
|
||||
name: "app init",
|
||||
|
|
Loading…
Reference in New Issue