Restructuring project part two and added build scripts

canary
WolverinDEV 2018-10-04 22:49:20 +02:00
parent 8d1a6628fb
commit ba5baf8431
23 changed files with 380 additions and 91 deletions

8
.gitignore vendored
View File

@ -1,15 +1,17 @@
**.js*
**.js
**.js.map
*.css.map
asm/build/
generated/
node_modules/
auth/certs/
auth/js/auth.js.map
.idea/
#This is just for me local (a nice animation which i may implement later)
animates/
asm/**
!asm/identity/
!asm/src/
!asm/CMakeLists.txt
!asm/make_opus.sh
web/*-environment/

54
client/api.php Normal file
View File

@ -0,0 +1,54 @@
<?php
/**
* Created by PhpStorm.
* User: WolverinDEV
* Date: 04.10.18
* Time: 16:42
*/
if(!isset($_SERVER['REQUEST_METHOD'])) {
error_log("This is a web only script!");
exit(1);
}
include "../files.php";
function handle_develop_web_request() {
if($_GET["type"] === "files") {
header("Content-Type: text/plain");
header("info-version: 1");
header("mode: develop");
echo ("type\thash\tpath\tname\n");
foreach (find_files(0b10, "../") as $file) {
echo $file->type . "\t" . $file->hash . "\t" . $file->path . "\t" . $file->name . "\n";
}
echo "html\t".sha1("main")."\t.\tindex.html\n";
die;
} else if($_GET["type"] === "file") {
header("Content-Type: text/plain");
$available_files = find_files(0b10, "../");
foreach ($available_files as $entry) {
if(($entry->path == $_GET["path"]) && ($entry->name == $_GET["name"])) {
fdump($entry->local_path);
die();
}
}
if($_GET["name"] == "index.html") {
global $CLIENT;
$CLIENT = true;
include "../index.php";
die();
}
die(json_encode([
"success" => false,
"error" => "missing file!"
]));
} else die(json_encode([
"success" => false,
"error" => "invalid action!"
]));
}
handle_develop_web_request();

121
files.php
View File

@ -3,6 +3,7 @@
[
"type" => "html",
"search-pattern" => "/^([a-zA-Z]+)\.html$/",
"build-target" => "dev|rel",
"path" => "./",
"local-path" => "./"
@ -11,6 +12,7 @@
"type" => "js",
"search-pattern" => "/.*\.js$/",
"search-exclude" => "/(.*\/)?workers\/.*/",
"build-target" => "dev",
"path" => "js/",
"local-path" => "./shared/js/"
@ -18,6 +20,7 @@
[
"type" => "js",
"search-pattern" => "/WorkerCodec.js$/",
"build-target" => "dev|rel",
"path" => "js/workers/",
"local-path" => "./shared/js/workers/"
@ -25,6 +28,7 @@
[
"type" => "css",
"search-pattern" => "/.*\.css$/",
"build-target" => "dev|rel",
"path" => "css/",
"local-path" => "./shared/css/"
@ -32,6 +36,7 @@
[
"type" => "img",
"search-pattern" => "/.*\.(svg|png)/",
"build-target" => "dev|rel",
"path" => "img/",
"local-path" => "./shared/img/"
@ -39,15 +44,17 @@
[
"type" => "wasm",
"search-pattern" => "/.*\.(wasm)/",
"build-target" => "dev|rel",
"path" => "wasm/",
"local-path" => "./asm/generated/"
],
[
[ /* useless? */
"type" => "js",
"search-pattern" => "/.*\.(js)/",
"build-target" => "dev|rel",
"path" => "asm/generated/",
"path" => "wasm/",
"local-path" => "./asm/generated/"
],
@ -55,6 +62,7 @@
[
"type" => "js",
"search-pattern" => "/.*\.js$/",
"build-target" => "dev|rel",
"path" => "vendor/",
"local-path" => "./vendor/"
@ -62,6 +70,7 @@
[
"type" => "css",
"search-pattern" => "/.*\.css$/",
"build-target" => "dev|rel",
"path" => "vendor/",
"local-path" => "./vendor/"
@ -72,6 +81,7 @@
"client-only" => true,
"type" => "css",
"search-pattern" => "/.*\.css$/",
"build-target" => "dev|rel",
"path" => "css/",
"local-path" => "./client/css/"
@ -82,6 +92,7 @@
"web-only" => true,
"type" => "css",
"search-pattern" => "/.*\.css$/",
"build-target" => "dev|rel",
"path" => "css/",
"local-path" => "./web/css/"
@ -90,6 +101,7 @@
"web-only" => true,
"type" => "html",
"search-pattern" => "/.*\.(php|html)/",
"build-target" => "dev|rel",
"path" => "./",
"local-path" => "./web/html/"
@ -100,10 +112,29 @@
"search-pattern" => "/.*\.(php|html)/",
"search-exclude" => "/(files.php)/",
"search-depth" => 1,
"build-target" => "dev|rel",
"path" => "./",
"local-path" => "./"
],
[
"web-only" => true,
"type" => "js",
"search-pattern" => "/.*\.(js)/",
"build-target" => "rel",
"path" => "./",
"local-path" => "./generated/"
],
[
"web-only" => true,
"type" => "js",
"search-pattern" => "/load.js/",
"build-target" => "rel",
"path" => "./js/",
"local-path" => "./shared/js/"
],
];
function list_dir($base_dir, $match = null, $depth = -1, &$results = array(), $dir = "") {
@ -132,15 +163,16 @@
public $hash;
}
function find_files($flag = 0b11) { //TODO Use cache here!
function find_files($flag = 0b11, $local_path_prefix = "./", $type = "dev") { //TODO Use cache here!
global $APP_FILE_LIST;
$result = [];
foreach ($APP_FILE_LIST as $entry) {
if(isset($entry["web-only"]) && $entry["web-only"] && ($flag & 0b01) == 0) continue;
if(isset($entry["client-only"]) && $entry["client-only"] && ($flag & 0b10) == 0) continue;
if(isset($entry["build-target"]) && array_search($type, explode("|", $entry["build-target"])) === false) continue;
$entries = list_dir($entry["local-path"], $entry["search-pattern"], isset($entry["search-depth"]) ? $entry["search-depth"] : -1);
$entries = list_dir($local_path_prefix . $entry["local-path"], $entry["search-pattern"], isset($entry["search-depth"]) ? $entry["search-depth"] : -1);
foreach ($entries as $f_entry) {
if(isset($entry["search-exclude"]) && preg_match($entry["search-exclude"], $f_entry)) continue;
$file = new AppFile;
@ -154,7 +186,7 @@
$file->name = $f_entry;
}
$file->local_path = $entry["local-path"] . DIRECTORY_SEPARATOR . $f_entry;
$file->local_path = $local_path_prefix . $entry["local-path"] . DIRECTORY_SEPARATOR . $f_entry;
$file->type = $entry["type"];
$file->hash = sha1_file($file->local_path);
@ -180,47 +212,6 @@
fclose($file);
}
function handle_web_request() {
if($_GET["type"] === "files") {
header("Content-Type: text/plain");
header("info-version: 1");
echo ("type\thash\tpath\tname\n");
foreach (find_files(0b10) as $file) {
echo $file->type . "\t" . $file->hash . "\t" . $file->path . "\t" . $file->name . "\n";
}
echo "html\t".sha1("main")."\t.\tindex.html\n";
die;
} else if($_GET["type"] === "file") {
header("Content-Type: text/plain");
$available_files = find_files(0b10);
foreach ($available_files as $entry) {
if(($entry->path == $_GET["path"]) && ($entry->name == $_GET["name"])) {
fdump($entry->local_path);
die();
}
}
if($_GET["name"] == "index.html") {
$CLIENT = true;
include "./index.php";
die();
}
die(json_encode([
"success" => false,
"error" => "missing file!"
]));
} else die(json_encode([
"success" => false,
"error" => "invalid action!"
]));
}
if(isset($_SERVER['REQUEST_METHOD'])) {
handle_web_request();
die(); //Should never happen!
}
if(isset($_SERVER["argv"])) { //Executed by command line
if(strpos(PHP_OS, "Linux") == -1) {
error_log("Invalid operating system! Help tool only available under linux!");
@ -233,8 +224,8 @@
if($_SERVER["argv"][1] == "help") {
help:
echo "php " . $_SERVER["argv"][0] . " <type> <args...>" . PHP_EOL;
echo " generate <web/client>" . PHP_EOL;
echo " list <web/client>" . PHP_EOL;
echo " generate <web/client> <dev/package>" . PHP_EOL;
echo " list <web/client> <dev/package>" . PHP_EOL;
exit(1);
} else if($_SERVER["argv"][1] == "list") {
if(count($_SERVER["argv"]) < 3) {
@ -253,12 +244,30 @@
$flagset = 0b00;
$environment = "";
if($_SERVER["argv"][2] == "web") {
$flagset = 0b01;
$environment = "web/environment";
} else if($_SERVER["argv"][2] == "client") {
$flagset = 0b10;
$environment = "client/environment";
$type = "dev";
if($_SERVER["argv"][3] == "dev") {
if ($_SERVER["argv"][2] == "web") {
$flagset = 0b01;
$environment = "web/dev-environment";
} else if ($_SERVER["argv"][2] == "client") {
$flagset = 0b10;
$environment = "client/dev-environment";
} else {
error_log("Invalid type!");
goto help;
}
} else if($_SERVER["argv"][3] == "rel") {
$type = "rel";
if ($_SERVER["argv"][2] == "web") {
$flagset = 0b01;
$environment = "web/rel-environment";
} else if ($_SERVER["argv"][2] == "client") {
$flagset = 0b10;
$environment = "client/rel-environment";
} else {
error_log("Invalid type!");
goto help;
}
} else {
error_log("Invalid type!");
goto help;
@ -268,7 +277,7 @@
exec($command = "rm -r " . $environment, $output, $state);
exec($command = "mkdir " . $environment, $output, $state); if($state) goto handle_error;
$files = find_files(0b01);
$files = find_files(0b01, "./", $type);
if(!chdir($environment)) {
error_log("Failed to enter directory " . $environment . "!");
exit(1);
@ -294,6 +303,8 @@
exit(0);
handle_error:
error_log("Failed to execute command '" . $command . "'!");
error_log("Command returned code " . $state . ". Output: " . PHP_EOL);

32
package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name": "client",
"version": "1.0.0",
"description": "Welcome here! This repository is created with two reasons:\n 1. People can bring their own ideas and follow their implementation\n 2. People can see TeaSpeak Web client progress and avoid creating repetitive issues all the time.",
"main": "main.js",
"directories": {
},
"scripts": {
"build-web-app": "tsc -p tsconfig/tsconfig_web_app.json",
"build-web-app-release": "tsc -p tsconfig/tsconfig_web_app_packaged.json",
"build-web-preload": "tsc -p tsconfig/tsconfig_web_preload.json"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^9.4.6",
"@types/emscripten": "0.0.31",
"@types/jquery": "^3.3.0",
"@types/websocket": "0.0.38"
},
"dependencies": {
},
"repository": {
"type": "git",
"url": "git+https://github.com/TeaSpeak/TeaWeb/TeaWeb.git"
},
"bugs": {
"url": "https://github.com/TeaSpeak/TeaWeb/issues"
},
"homepage": "https://github.com/TeaSpeak/TeaWeb/TeaWeb#readme"
}

25
scripts/build_web.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
BASEDIR=$(dirname "$0")
cd "$BASEDIR/../"
npm run "build-web-app"
if [ $? -ne 0 ]; then
echo "Failed to compile app!"
exit 0
fi
npm run "build-web-preload"
if [ $? -ne 0 ]; then
echo "Failed to compile app-preloader!"
exit 0
fi
php files.php generate web dev
if [ $? -ne 0 ]; then
echo "Failed to setup environment!"
exit 0
fi
echo "Development environment successfully generated!"
echo "Note: Do not forget to recompile the typescript files when edited!"

31
scripts/build_web_release.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
BASEDIR=$(dirname "$0")
cd "$BASEDIR/../"
#Cleanup stuff
rm -r generated &> /dev/null
if [ -e generated ]; then
echo "Failed to remove generated directory!"
exit 1
fi
npm run "build-web-app-release"
if [ $? -ne 0 ]; then
echo "Failed to compile app!"
exit 0
fi
npm run "build-web-preload"
if [ $? -ne 0 ]; then
echo "Failed to compile app-preloader!"
exit 0
fi
php files.php generate web rel
if [ $? -ne 0 ]; then
echo "Failed to setup environment!"
exit 0
fi
echo "Release environment successfully generated!"

35
scripts/package_web_release.sh Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env bash
BASEDIR=$(dirname "$0")
cd "$BASEDIR/../"
if [ ! -d web/rel-environment ]; then
echo "Please generate first the release environment!"
exit 1
fi
git diff-index --quiet HEAD --
if [ $? -ne 0 ]; then
echo "You're using a private modified build!"
echo "Cant assign git hash!"
NAME="TeaWeb.zip"
else
NAME="TeaWeb-$(git rev-parse --short HEAD).zip"
fi
if [ -e ${NAME} ]; then
echo "Deleting old file"
rm -r ${NAME}
fi
cd web/rel-environment
zip -9 -r ${NAME} *
if [ $? -ne 0 ]; then
echo "Failed to package environment!"
fi
mv ${NAME} ../../
cd ../../
echo "Release package successfully packaged!"
echo "Target file: ${NAME}"

View File

@ -44,7 +44,7 @@ namespace TSIdentityHelper {
if(str == "") return "";
try {
if(!$.isFunction(window.Pointer_stringify) || !$.isFunction(Pointer_stringify)) {
displayCriticalError("Missing required wasm function!<br>Please reload the page!", false);
displayCriticalError("Missing required wasm function!<br>Please reload the page!");
}
let message: string = Pointer_stringify(str);
functionDestroyString(str);

View File

@ -37,18 +37,11 @@ namespace app {
Module['onAbort'] = message => {
Module['onAbort'] = undefined;
displayCriticalError("Could not load webassembly files!<br>Message: <code>" + message + "</code>", false);
displayCriticalError("Could not load webassembly files!<br>Message: <code>" + message + "</code>");
};
Module['locateFile'] = file => {
console.log("File path for " + file);
return "wasm/" + file;
switch (type) {
case Type.RELEASE:
return "js/assembly/" + file;
case Type.DEBUG:
return "asm/generated/" + file;
}
};
}
@ -108,8 +101,8 @@ function loadRelease() {
console.log("Load for release!");
awaitLoad(loadScripts([
//Load general API's
["js/assembly/TeaWeb-Identity.js"],
["js/client.min.js", "js/client.js", "generated/js/client.min.js", "generated/js/client.js"]
["wasm/TeaWeb-Identity.js"],
["js/client.min.js", "js/client.js"]
])).then(() => {
console.log("Loaded successfully all scripts!");
app.callbackApp();
@ -123,7 +116,7 @@ function loadDebug() {
console.log("Load for debug!");
awaitLoad(loadScripts([
["asm/generated/TeaWeb-Identity.js"],
["wasm/TeaWeb-Identity.js"],
//Load general API's
"js/log.js",
@ -168,7 +161,6 @@ function loadDebug() {
//Load codec
"js/codec/Codec.js",
"js/codec/BasicCodec.js",
"js/codec/CodecWrapper.js",
//Load general stuff
"js/settings.js",
@ -179,6 +171,8 @@ function loadDebug() {
"js/chat.js",
"js/Identity.js"
])).then(() => {
return loadScripts(["js/codec/CodecWrapper.js"]);
}).then(() => {
awaitLoad(loadScripts(["js/main.js"])).then(() => {
console.log("Loaded successfully all scripts!");
app.callbackApp();
@ -228,17 +222,16 @@ function loadTemplates() {
let root = document.getElementById("templates");
while(tags.length > 0){
let tag = tags.item(0);
if(tag.id == "tmpl_main")
document.getElementsByTagName("body").item(0).appendChild(tag);
if(tag.id == "tmpl_main") {
let main_node = document.createElement("div");
document.getElementsByTagName("body").item(0).appendChild(main_node);
main_node.outerHTML = tag.innerHTML;
tag.remove();
}
else
root.appendChild(tag);
}
/*
root = document.getElementById("script");
while(tags.length > 0)
root.appendChild(tags.item(0));
*/
}).catch(error => {
console.error("Could not load templates!");
console.log(error);
@ -248,6 +241,14 @@ function loadTemplates() {
//TODO release config!
function loadSide() {
if(window.require !== undefined) {
console.log("Loading node specific things");
const app = require('electron').remote.app;
module.paths.push(app.getAppPath());
window.$ = require("jquery");
require("native/loader_adapter.js");
}
if(typeof (WebAssembly) === "undefined" || typeof (WebAssembly.compile) === "undefined") {
console.log(navigator.browserSpecs);
if (navigator.browserSpecs.name == 'Safari') {
@ -262,11 +263,6 @@ function loadSide() {
displayCriticalError("You require WebAssembly for TeaSpeak-Web!");
return;
}
if(window.require !== undefined) {
const app = require('electron').remote.app;
module.paths.push(app.getAppPath());
window.$ = require("jquery");
}
//Load the general scripts and required scripts
awaitLoad(loadScripts([
["vendor/jquery/jquery.min.js", /*"https://code.jquery.com/jquery-latest.min.js"*/],

View File

@ -107,6 +107,6 @@ app.loadedListener.push(() => {
} catch (ex) {
if(ex instanceof ReferenceError)
ex = ex.message + ":<br>" + ex.stack;
displayCriticalError("Failed to invoke main function:<br>" + ex, false);
displayCriticalError("Failed to invoke main function:<br>" + ex);
}
});

View File

@ -194,6 +194,8 @@ interface Window {
readonly webkitOfflineAudioContext: typeof webkitOfflineAudioContext;
readonly RTCPeerConnection: typeof RTCPeerConnection;
readonly Pointer_stringify: any;
readonly jsrender: any;
require(id: string): any;
}

View File

@ -1,5 +1,5 @@
/// <reference path="../../client.ts" />
/// <reference path="../../../vendor/bbcode/xbbcode.ts" />
/// <reference path="../../../../vendor/bbcode/xbbcode.ts" />
abstract class InfoManagerBase {
private timers: NodeJS.Timer[] = [];

View File

@ -36,7 +36,7 @@ class AudioController {
(this._globalContextPromise = this._globalContext.resume()).then(() => {
this.fire_initialized();
}).catch(error => {
displayCriticalError("Failed to initialize global audio context! (" + error + ")", false);
displayCriticalError("Failed to initialize global audio context! (" + error + ")");
});
}
this._globalContext.resume(); //We already have our listener

View File

@ -29,7 +29,7 @@ Module['onAbort'] = message => {
try {
console.log("Node init!");
Module['locateFile'] = file => "../../wasm/" + file;
importScripts("../../asm/generated/TeaWeb-Worker-Codec-Opus.js");
importScripts("../../wasm/TeaWeb-Worker-Codec-Opus.js");
} catch (e) {
console.log(e);
Module['onAbort']("Cloud not load native script!");

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "none",
"target": "es6",
"sourceMap": true,
"outFile": "WorkerCodec.js"
},
"files": [
"codec/CodecWorker.ts",
"codec/OpusCodec.ts"
]
}

13
tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"module": "none",
"target": "es6",
"sourceMap": true
},
"exclude": [
"node_modules",
"js/workers",
"enviroment",
"tsconfig"
]
}

5
tsconfig/@types/exports/index.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
declare namespace app {
let loadedListener: (() => any)[]
}
declare function displayCriticalError(message: string);

32
tsconfig/@types/imports/index.d.ts vendored Normal file
View File

@ -0,0 +1,32 @@
declare class StaticSettings {
static instance : StaticSettings;
static?<T>(key: string, _default?: T) : T;
deleteStatic(key: string);
}
declare type BodyCreator = (() => JQuery | JQuery[] | string) | string | JQuery | JQuery[];
declare class ModalProperties {
header: BodyCreator;
body: BodyCreator;
footer: BodyCreator;
closeListener: (() => void) | (() => void)[];
registerCloseListener(listener: () => void): this;
width: number | string;
hight: number | string;
closeable: boolean;
triggerClose();
}
declare function createErrorModal(header: BodyCreator, message: BodyCreator, props: ModalProperties | any);
declare function displayCriticalError(message: string);
declare interface Window {
$: JQuery;
displayCriticalError: typeof displayCriticalError;
}

View File

@ -1,4 +0,0 @@
declare namespace app {
let loadedListener: (() => any)[]
}
declare function displayCriticalError(message: string, closeable: boolean);

View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"module": "none",
"target": "es6",
"sourceMap": true,
}
}

View File

@ -0,0 +1,18 @@
{
"extends": "./tsconfig_shared.json",
"compilerOptions": {
/* because were excluding load.ts we have to define its types */
"typeRoots" : ["../node_modules/@types/", "./@types/"],
"types" : ["exports", "jquery", "webassembly-js-api", "node", "emscripten"]
},
"exclude": [
"../node_modules",
"../shared/js/load.ts",
"../shared/js/codec/workers",
"../shared/js/workers"
],
"include": [
"../shared/js/**/*",
"../web/js/**/*"
]
}

View File

@ -0,0 +1,6 @@
{
"extends": "./tsconfig_web_app.json",
"compilerOptions": {
"outFile": "../generated/js/client.js",
}
}

View File

@ -0,0 +1,12 @@
{
"extends": "./tsconfig_shared.json",
"compilerOptions": {
/* because were excluding load.ts we have to define its types */
"typeRoots" : ["../node_modules/@types/", "./@types/"],
"types" : ["imports", "jquery", "webassembly-js-api", "node", "emscripten"]
},
"include": [
"../shared/js/load.ts",
"../shared/js/proto.ts"
]
}