Merge pull request #182 from TeaSpeak/develop
Finally merge these changes since TeaSpeak 1.5 is released as stable. Note: This merge will break compatibility with all 1.4 TeaSpeak server versions!master
|
@ -14,6 +14,7 @@ node_modules/
|
||||||
|
|
||||||
# Some build output
|
# Some build output
|
||||||
/dist/
|
/dist/
|
||||||
|
/dist-package/
|
||||||
/declarations/
|
/declarations/
|
||||||
/travis-build/
|
/travis-build/
|
||||||
|
|
||||||
|
|
10
.travis.yml
|
@ -1,10 +1,12 @@
|
||||||
dist: trusty
|
dist: bionic
|
||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "12"
|
- "12"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get -y install coreutils
|
||||||
- chmod +x ./scripts/travis/build.sh
|
- chmod +x ./scripts/travis/build.sh
|
||||||
- chmod +x ./scripts/travis/deploy_server.sh
|
- chmod +x ./scripts/travis/deploy_server.sh
|
||||||
- chmod +x ./scripts/travis/deploy_github.sh
|
- chmod +x ./scripts/travis/deploy_github.sh
|
||||||
|
@ -29,11 +31,11 @@ deploy:
|
||||||
# - provider: script
|
# - provider: script
|
||||||
# cleanup: false
|
# cleanup: false
|
||||||
# skip_cleanup: true
|
# skip_cleanup: true
|
||||||
# script: "bash scripts/travis/deploy_docker.sh development"
|
# script: "bash scripts/travis/deploy_docker.sh development"
|
||||||
# on:
|
# on:
|
||||||
# branch: develop
|
# branch: develop
|
||||||
- provider: script
|
- provider: script
|
||||||
script: "bash scripts/travis/deploy_server.sh production"
|
script: "bash scripts/travis/deploy_server.sh production"
|
||||||
cleanup: false
|
cleanup: false
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
on:
|
on:
|
||||||
|
@ -41,7 +43,7 @@ deploy:
|
||||||
- provider: script
|
- provider: script
|
||||||
cleanup: false
|
cleanup: false
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
script: "bash scripts/travis/deploy_github.sh"
|
script: "bash scripts/travis/deploy_github.sh"
|
||||||
on:
|
on:
|
||||||
branch: master
|
branch: master
|
||||||
# - provider: script
|
# - provider: script
|
||||||
|
|
79
ChangeLog.md
|
@ -1,4 +1,83 @@
|
||||||
# Changelog:
|
# Changelog:
|
||||||
|
* **26.05.21**
|
||||||
|
- Fixed automated builds
|
||||||
|
- Fixed the bookmark UI popout window
|
||||||
|
- Added a context menu for the general bookmark container
|
||||||
|
|
||||||
|
* **05.05.21**
|
||||||
|
- Reworked the icon modal
|
||||||
|
- Fixed some minor icon and avatar related issues
|
||||||
|
- Improved icon modal performance
|
||||||
|
|
||||||
|
* **29.04.21**
|
||||||
|
- Fixed a bug which caused chat messages to appear twice
|
||||||
|
- Adding support for poping out channel conversations
|
||||||
|
|
||||||
|
* **27.04.21**
|
||||||
|
- Implemented support for showing the video feed watchers
|
||||||
|
- Updating the channel tree if the channel client order changes
|
||||||
|
|
||||||
|
* **24.04.21**
|
||||||
|
- Removed the old server info modal and using the new React based and popoutable modal
|
||||||
|
- Using the new React modal for the server info dialog. The modal now also has improved permission and error visualisation
|
||||||
|
- Improved tooltip handling
|
||||||
|
|
||||||
|
* **19.04.21**
|
||||||
|
- Fixed a bug that the client video box is shown as active even though the client does not stream any video
|
||||||
|
- Fixed a bug that the video fullscreen windows pops open when a client leaves/joins the channel
|
||||||
|
- Removed extra new line after blockquote for the markdown renderer
|
||||||
|
|
||||||
|
* **05.04.21**
|
||||||
|
- Fixed the mute but for the webclient
|
||||||
|
- Fixed that "always active" microphone filter now works reliably
|
||||||
|
- Improved the recorder API
|
||||||
|
|
||||||
|
* **29.03.21**
|
||||||
|
- Acquiring the default input recorder when opening the settings
|
||||||
|
- Adding new modal Input Processing Properties for the native client
|
||||||
|
- Fixed that you can't finish off the name editing by pressing enter
|
||||||
|
|
||||||
|
* **25.03.21**
|
||||||
|
- Allowing to directly select the speaker output device
|
||||||
|
- Saving the speaker output device
|
||||||
|
|
||||||
|
* **24.03.21**
|
||||||
|
- Improved the avatar upload modal (now way more intuitive)
|
||||||
|
- Fixed a bug which cause client avatars to be stuck within the loading screen
|
||||||
|
- Don't spam permission errors if we don't have the permission to view the channel description
|
||||||
|
- Showing channel group inheritance within the client info frame
|
||||||
|
|
||||||
|
* **23.03.21**
|
||||||
|
- Made the permission editor popoutable
|
||||||
|
- Now using SVG flags for higher quality.
|
||||||
|
- Fixed issue [#74](https://github.com/TeaSpeak/TeaWeb/issues/74) (Swiss flag box has black background)
|
||||||
|
- Fixed issue that middle clicking on the channel does not shows the channel file browser instead it shows the global one
|
||||||
|
|
||||||
|
* **21.03.21**
|
||||||
|
- Reworked the server group assignment modal. It now better reacts to the user input as well is now popoutable
|
||||||
|
|
||||||
|
* **18.03.21**
|
||||||
|
- Finally, got fully rid of the initial backend glue and changes all systems to provider
|
||||||
|
|
||||||
|
* **17.03.21**
|
||||||
|
- Updated from webpack 4 to webpack 5
|
||||||
|
- Reworked the client build process
|
||||||
|
- Using webpack dev server from now on
|
||||||
|
|
||||||
|
* **14.03.21**
|
||||||
|
- Enchanted the bookmark system
|
||||||
|
- Added support for auto connect on startup
|
||||||
|
- Cleaned and simplified up the bookmark UI
|
||||||
|
- Added support for importing/exporting bookmarks
|
||||||
|
- Added support for duplicating bookmarks
|
||||||
|
- Adding support for default channels and passwords
|
||||||
|
|
||||||
|
* **12.03.21**
|
||||||
|
- Added a new video spotlight mode which allows showing multiple videos at the same time as well as
|
||||||
|
dragging and resizing them
|
||||||
|
- Fixed a minor bug within the permission editor
|
||||||
|
- Fixed the creation of channel groups
|
||||||
|
|
||||||
* **20.02.21**
|
* **20.02.21**
|
||||||
- Improved the browser IPC module
|
- Improved the browser IPC module
|
||||||
- Added support for client invite links
|
- Added support for client invite links
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
export = api => {
|
export default api => {
|
||||||
api.cache(false);
|
api.cache(false);
|
||||||
const presets = [
|
const presets = [
|
||||||
[
|
[
|
||||||
"@babel/preset-env",
|
"@babel/preset-env",
|
||||||
{
|
{
|
||||||
"corejs": { "version":3 },
|
"corejs": {"version": 3},
|
||||||
"useBuiltIns": "usage",
|
"useBuiltIns": "usage",
|
||||||
"targets": {
|
"targets": {
|
||||||
"edge": "17",
|
"edge": "17",
|
||||||
|
@ -16,10 +16,12 @@ export = api => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
const plugins = [
|
const plugins = [
|
||||||
["@babel/transform-runtime"],
|
["@babel/transform-runtime"],
|
||||||
["@babel/plugin-transform-modules-commonjs"]
|
["@babel/plugin-transform-modules-commonjs"]
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
presets,
|
presets,
|
||||||
plugins
|
plugins
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
window.__native_client_init_shared(__webpack_require__);
|
||||||
|
|
||||||
|
import "../AppMain.scss";
|
||||||
|
import "tc-shared/entry-points/MainApp";
|
|
@ -1,4 +1,2 @@
|
||||||
window.__native_client_init_shared(__webpack_require__);
|
window.__native_client_init_shared(__webpack_require__);
|
||||||
|
import "tc-shared/entry-points/ModalWindow";
|
||||||
import "./index.scss";
|
|
||||||
import "tc-shared/main";
|
|
|
@ -1,42 +0,0 @@
|
||||||
# File structure
|
|
||||||
The TeaSpeak web client is separated into 2 different parts.
|
|
||||||
|
|
||||||
## I) Application files
|
|
||||||
Application files are all files which directly belong to the app itself.
|
|
||||||
Like the javascript files who handle the UI stuff or even translation templates.
|
|
||||||
Theses files are separated into two type of files.
|
|
||||||
1. [Shared application files](#1-shared-application-files)
|
|
||||||
2. [Web application files](#2-web-application-files)
|
|
||||||
|
|
||||||
### 1. Shared application files
|
|
||||||
Containing all files used by the TeaSpeak client and the Web client.
|
|
||||||
All of these files will be found within the folder `shared`.
|
|
||||||
This folder follows the general application file structure.
|
|
||||||
More information could be found [here](#application-file-structure)
|
|
||||||
|
|
||||||
### 2. Web application files
|
|
||||||
All files which only belong to a browser only instance.
|
|
||||||
All of these files will be found within the folder `web`.
|
|
||||||
This folder follows the general application file structure.
|
|
||||||
More information could be found [here](#application-file-structure)
|
|
||||||
|
|
||||||
### application file structure
|
|
||||||
Every application root contains several subfolders.
|
|
||||||
In the following list will be listed which files belong to which folder
|
|
||||||
|
|
||||||
| Folder | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `audio` | This folder contains all audio files used by the application. More information could be found [here](). |
|
|
||||||
| `css` | This folder contains all style sheets used by the application. More information could be found [here](). |
|
|
||||||
| `js` | This folder contains all javascript files used by the application. More information could be found [here](). |
|
|
||||||
| `html` | This folder contains all HTML and PHP files used by the application. More information could be found [here](). |
|
|
||||||
| `i18n` | This folder contains all default translations. Information about the translation system could be found [here](). |
|
|
||||||
| `img` | This folder contains all image files. |
|
|
||||||
|
|
||||||
## I) Additional tools
|
|
||||||
|
|
||||||
## Environment builder
|
|
||||||
The environment builder is one of the most important tools of the entire project.
|
|
||||||
This tool, basically implemented in the file `files.php`, will be your helper while live developing.
|
|
||||||
What this tool does is, it creates a final environment where you could navigate to with your browser.
|
|
||||||
It merges all the type separated files, which had been listed above ([here](#application-file-structure)).
|
|
58
file.ts
|
@ -30,49 +30,26 @@ type ProjectResource = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP_FILE_LIST_SHARED_SOURCE: ProjectResource[] = [
|
const APP_FILE_LIST_SHARED_SOURCE: ProjectResource[] = [
|
||||||
|
{ /* javascript files as manifest.json */
|
||||||
|
"type": "js",
|
||||||
|
"search-pattern": /.*\.(js|json|svg|png|css)$/,
|
||||||
|
"build-target": "dev|rel",
|
||||||
|
|
||||||
|
"path": "js/",
|
||||||
|
"local-path": "./dist/"
|
||||||
|
},
|
||||||
|
|
||||||
{ /* shared html files */
|
{ /* shared html files */
|
||||||
"type": "html",
|
"type": "html",
|
||||||
"search-pattern": /^.*([a-zA-Z]+)\.(html|json)$/,
|
"search-pattern": /^.*([a-zA-Z]+)\.(html|json)$/,
|
||||||
"build-target": "dev|rel",
|
"build-target": "dev|rel",
|
||||||
|
|
||||||
"path": "./",
|
"path": "./",
|
||||||
"local-path": "./shared/html/"
|
|
||||||
},
|
|
||||||
{ /* javascript files as manifest.json */
|
|
||||||
"type": "js",
|
|
||||||
"search-pattern": /.*\.(js|json|svg)$/,
|
|
||||||
"build-target": "dev|rel",
|
|
||||||
|
|
||||||
"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 sound files */
|
{ /* shared sound files */
|
||||||
"type": "wav",
|
"type": "wav",
|
||||||
"search-pattern": /.*\.wav$/,
|
"search-pattern": /.*\.(wav|json)$/,
|
||||||
"build-target": "dev|rel",
|
|
||||||
|
|
||||||
"path": "audio/",
|
|
||||||
"local-path": "./shared/audio/"
|
|
||||||
},
|
|
||||||
{ /* shared data sound files */
|
|
||||||
"type": "json",
|
|
||||||
"search-pattern": /.*\.json/,
|
|
||||||
"build-target": "dev|rel",
|
"build-target": "dev|rel",
|
||||||
|
|
||||||
"path": "audio/",
|
"path": "audio/",
|
||||||
|
@ -87,15 +64,6 @@ const APP_FILE_LIST_SHARED_SOURCE: ProjectResource[] = [
|
||||||
"path": "img/",
|
"path": "img/",
|
||||||
"local-path": "./shared/img/"
|
"local-path": "./shared/img/"
|
||||||
},
|
},
|
||||||
{ /* assembly files */
|
|
||||||
"web-only": true,
|
|
||||||
"type": "wasm",
|
|
||||||
"search-pattern": /.*\.(wasm)/,
|
|
||||||
"build-target": "dev|rel",
|
|
||||||
|
|
||||||
"path": "js/",
|
|
||||||
"local-path": "./dist/"
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const APP_FILE_LIST_SHARED_VENDORS: ProjectResource[] = [];
|
const APP_FILE_LIST_SHARED_VENDORS: ProjectResource[] = [];
|
||||||
|
@ -297,7 +265,7 @@ namespace server {
|
||||||
} else {
|
} else {
|
||||||
server = http.createServer(handleHTTPRequest);
|
server = http.createServer(handleHTTPRequest);
|
||||||
}
|
}
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
server.on('error', reject);
|
server.on('error', reject);
|
||||||
server.listen(options.port, () => {
|
server.listen(options.port, () => {
|
||||||
server.off("error", reject);
|
server.off("error", reject);
|
||||||
|
@ -308,7 +276,7 @@ namespace server {
|
||||||
|
|
||||||
export async function shutdown() {
|
export async function shutdown() {
|
||||||
if(server) {
|
if(server) {
|
||||||
await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve()));
|
await new Promise<void>((resolve, reject) => server.close(error => error ? reject(error) : resolve()));
|
||||||
server = undefined;
|
server = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +396,7 @@ namespace watcher {
|
||||||
this._process.addListener("error", this.handle_error.bind(this));
|
this._process.addListener("error", this.handle_error.bind(this));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
const id = setTimeout(reject, 5000, "timeout");
|
const id = setTimeout(reject, 5000, "timeout");
|
||||||
this._callback_init = () => {
|
this._callback_init = () => {
|
||||||
clearTimeout(id);
|
clearTimeout(id);
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import * as path from "path";
|
|
||||||
import EJSGenerator = require("../webpack/EJSGenerator");
|
|
||||||
|
|
||||||
class IndexGenerator extends EJSGenerator {
|
|
||||||
constructor(options: {
|
|
||||||
buildTarget: string;
|
|
||||||
output: string,
|
|
||||||
isDevelopment: boolean
|
|
||||||
}) {
|
|
||||||
super({
|
|
||||||
variables: {
|
|
||||||
build_target: options.buildTarget
|
|
||||||
},
|
|
||||||
output: options.output,
|
|
||||||
initialJSEntryChunk: "loader",
|
|
||||||
input: path.join(__dirname, "html/index.html.ejs"),
|
|
||||||
minify: !options.isDevelopment,
|
|
||||||
|
|
||||||
embedInitialJSEntryChunk: !options.isDevelopment,
|
|
||||||
embedInitialCSSFile: !options.isDevelopment,
|
|
||||||
|
|
||||||
initialCSSFile: {
|
|
||||||
localFile: path.join(__dirname, "css/index.css"),
|
|
||||||
publicFile: "css/index.css"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export = IndexGenerator;
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as loader from "./loader/loader";
|
import * as loader from "./loader/loader";
|
||||||
import {Stage} from "./loader/loader";
|
import {Stage} from "./loader/loader";
|
||||||
import {getUrlParameter} from "./loader/utils";
|
import {getUrlParameter} from "./loader/Utils";
|
||||||
|
|
||||||
let overlay: HTMLDivElement;
|
let overlay: HTMLDivElement;
|
||||||
let setupContainer: 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,4 @@ body {
|
||||||
*, :before, :after {
|
*, :before, :after {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "loader";
|
|
||||||
@import "overlay";
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import "./index.scss";
|
||||||
|
import "./loader.scss";
|
||||||
|
import "./overlay.scss";
|
|
@ -0,0 +1,223 @@
|
||||||
|
:global {
|
||||||
|
$setup-time-normal: 80s / 24; /* 24 frames / sec; the initial sequence is 80 frames */
|
||||||
|
$setup-time-halloween: 323s / 24;
|
||||||
|
$loop-time-halloween: 25s / 24;
|
||||||
|
|
||||||
|
#loader-overlay {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
background: #1e1e1e;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
z-index: 10000000;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
|
||||||
|
.container {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 1000px;
|
||||||
|
height: 1000px;
|
||||||
|
|
||||||
|
align-self: center;
|
||||||
|
margin-bottom: 10vh;
|
||||||
|
|
||||||
|
transition-duration: .5s;
|
||||||
|
|
||||||
|
img {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup, .idle {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup.visible {
|
||||||
|
&.normal {
|
||||||
|
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time-normal forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.halloween {
|
||||||
|
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time-halloween forwards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.idle.animation-normal {
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steam {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 282px;
|
||||||
|
left: 380px;
|
||||||
|
|
||||||
|
width: 249px;
|
||||||
|
height: 125px;
|
||||||
|
background: url("../../images/steam.png") 0 0;
|
||||||
|
|
||||||
|
animation: sprite-steam 2.5s steps(50) forwards infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.finishing {
|
||||||
|
.idle {
|
||||||
|
.steam {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bowl {
|
||||||
|
animation: swipe-out-bowl .5s both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
animation: swipe-out-text .5s .12s both;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
animation: overlay-fade .3s .2s both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader-stage {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: monospace;
|
||||||
|
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Automated loader timeout */
|
||||||
|
#loader-overlay:not(.initialized) + #critical-load:not(.shown) {
|
||||||
|
display: block !important;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
animation: loader-setup-timeout 0s ease-in $setup-time-normal forwards;
|
||||||
|
|
||||||
|
.error::before {
|
||||||
|
content: 'Failed to startup loader!';
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail::before {
|
||||||
|
content: 'Lookup the console for more details';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 850px) {
|
||||||
|
:global {
|
||||||
|
#loader-overlay .container {
|
||||||
|
transform: scale(.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-height: 700px) {
|
||||||
|
:global {
|
||||||
|
#loader-overlay .container {
|
||||||
|
transform: scale(.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 400px) {
|
||||||
|
:global {
|
||||||
|
#loader-overlay .container {
|
||||||
|
transform: scale(.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(loader-initial-sequence) {
|
||||||
|
to {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(sprite-steam) {
|
||||||
|
to {
|
||||||
|
background-position: 0 -6250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(swipe-out-bowl) {
|
||||||
|
from {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(-60px, 0, 0) skew(-5deg, 0) rotateY(-6deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(700px, 0, 0) skew(30deg, 0) rotateZ(-6deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(swipe-out-text) {
|
||||||
|
from {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(-30px, 20px, 0) skew(-5deg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(550px, 0, 0) skew(30deg, 0) scale(.96, 1.25) rotateZ(6deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(animation-nothing) {
|
||||||
|
to {
|
||||||
|
background-position: 0 -6250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(overlay-fade) {
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes :global(loader-setup-timeout) {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
:global {
|
||||||
|
#overlay-no-js, #critical-load {
|
||||||
|
z-index: 100000000;
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
background: #1e1e1e;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
|
||||||
|
h1, h3, a {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
top: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.shown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlay-no-js {
|
||||||
|
display: block;
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#critical-load {
|
||||||
|
.img {
|
||||||
|
height: 12em
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: #bd1515;
|
||||||
|
margin-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
color: #696363;
|
||||||
|
margin-top: .5em
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-height: 750px) {
|
||||||
|
:global {
|
||||||
|
#critical-load .container {
|
||||||
|
top: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#critical-load {
|
||||||
|
font-size: .8rem;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#critical-load.shown {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +1,14 @@
|
||||||
import "core-js/stable";
|
if(window["loader"]) {
|
||||||
import "./polifill";
|
throw "an loader instance has already been defined";
|
||||||
|
|
||||||
import * as loader from "./loader/loader";
|
|
||||||
import {ApplicationLoader} from "./loader/loader";
|
|
||||||
import {getUrlParameter} from "./loader/utils";
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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 {};
|
export * from "./loader/loader";
|
||||||
|
export * as loaderAnimation from "./animation";
|
||||||
|
|
||||||
if(__build.target === "client") {
|
import "./bootstrap";
|
||||||
/* do this so we don't get a react dev tools warning within the client */
|
|
||||||
if(!('__REACT_DEVTOOLS_GLOBAL_HOOK__' in window))
|
/* FIXME: This is glue! */
|
||||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {};
|
if(window["loader"]) {
|
||||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject = function () {};
|
throw "an loader instance has already been defined";
|
||||||
}
|
}
|
||||||
|
window["loader"] = module.exports;
|
|
@ -0,0 +1,128 @@
|
||||||
|
export type ResourceRequestResult = {
|
||||||
|
status: "success"
|
||||||
|
} | {
|
||||||
|
status: "unknown-error",
|
||||||
|
message: string
|
||||||
|
} | {
|
||||||
|
status: "error-event"
|
||||||
|
} | {
|
||||||
|
status: "timeout",
|
||||||
|
givenTimeout: number
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ResourceType = "script" | "css" | "json";
|
||||||
|
|
||||||
|
export class ResourceRequest {
|
||||||
|
private readonly type: ResourceType;
|
||||||
|
private readonly name: string;
|
||||||
|
|
||||||
|
private status: "unset" | "pending" | "executing" | "executed";
|
||||||
|
private result: ResourceRequestResult | undefined;
|
||||||
|
|
||||||
|
private timestampEnqueue: number;
|
||||||
|
private timestampExecuting: number;
|
||||||
|
private timestampExecuted: number;
|
||||||
|
|
||||||
|
constructor(type: ResourceType, name: string) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
this.status = "unset";
|
||||||
|
}
|
||||||
|
|
||||||
|
markEnqueue() {
|
||||||
|
if(this.status !== "unset") {
|
||||||
|
console.warn("ResourceRequest %s status isn't unset.", this.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timestampEnqueue = performance.now();
|
||||||
|
this.status = "pending";
|
||||||
|
}
|
||||||
|
|
||||||
|
markExecuting() {
|
||||||
|
switch (this.status) {
|
||||||
|
case "unset":
|
||||||
|
/* the markEnqueue() invoke has been skipped */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "pending":
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn("ResourceRequest %s has invalid status to call markExecuting.", this.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timestampExecuting = performance.now();
|
||||||
|
this.status = "executing";
|
||||||
|
}
|
||||||
|
|
||||||
|
markExecuted(result: ResourceRequestResult) {
|
||||||
|
switch (this.status) {
|
||||||
|
case "unset":
|
||||||
|
/* the markEnqueue() invoke has been skipped */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "pending":
|
||||||
|
/* the markExecuting() invoke has been skipped */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "executing":
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn("ResourceRequest %s has invalid status to call markExecuted.", this.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.result = result;
|
||||||
|
this.timestampExecuted = performance.now();
|
||||||
|
this.status = "executed";
|
||||||
|
}
|
||||||
|
|
||||||
|
generateReportString() {
|
||||||
|
let timeEnqueued, timeExecuted;
|
||||||
|
if(this.timestampEnqueue === 0) {
|
||||||
|
timeEnqueued = "unknown";
|
||||||
|
} else {
|
||||||
|
let endTimestamp = Math.min(this.timestampExecuting, this.timestampExecuted);
|
||||||
|
if (endTimestamp === 0) {
|
||||||
|
timeEnqueued = "pending";
|
||||||
|
} else {
|
||||||
|
timeEnqueued = endTimestamp - this.timestampEnqueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.timestampExecuted === 0) {
|
||||||
|
timeExecuted = "unknown";
|
||||||
|
} else {
|
||||||
|
if( this.timestampExecuted === 0) {
|
||||||
|
timeExecuted = "pending";
|
||||||
|
} else {
|
||||||
|
timeExecuted = this.timestampExecuted - this.timestampEnqueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `ResourceRequest{ type: ${this.type}, time enqueued: ${timeEnqueued}, time executed: ${timeExecuted}, name: ${this.name} }`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LoaderPerformanceLogger {
|
||||||
|
private readonly resourceTimings: ResourceRequest[] = [];
|
||||||
|
private eventTimeBase: number;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.eventTimeBase = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
getResourceTimings() : ResourceRequest[] {
|
||||||
|
return this.resourceTimings;
|
||||||
|
}
|
||||||
|
|
||||||
|
logResourceRequest(type: ResourceType, name: string) : ResourceRequest {
|
||||||
|
const request = new ResourceRequest(type, name);
|
||||||
|
this.resourceTimings.push(request);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
import {config, critical_error, loaderPerformance, SourcePath} from "./loader";
|
||||||
|
import {executeParallelLoad, LoadCallback, LoadSyntaxError, ParallelOptions} from "./Utils";
|
||||||
|
|
||||||
|
export function loadScript(url: SourcePath) : Promise<void> {
|
||||||
|
const givenTimeout = 120 * 1000;
|
||||||
|
|
||||||
|
const resourceRequest = loaderPerformance.logResourceRequest("script", url);
|
||||||
|
resourceRequest.markEnqueue();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const scriptTag = document.createElement("script");
|
||||||
|
scriptTag.type = "application/javascript";
|
||||||
|
scriptTag.async = true;
|
||||||
|
scriptTag.defer = true;
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
scriptTag.onerror = undefined;
|
||||||
|
scriptTag.onload = undefined;
|
||||||
|
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
resourceRequest.markExecuted({ status: "timeout", givenTimeout: givenTimeout });
|
||||||
|
cleanup();
|
||||||
|
reject("timeout");
|
||||||
|
}, givenTimeout);
|
||||||
|
|
||||||
|
/* TODO: Test if on syntax error the parameters contain extra info */
|
||||||
|
scriptTag.onerror = () => {
|
||||||
|
resourceRequest.markExecuted({ status: "error-event" });
|
||||||
|
scriptTag.remove();
|
||||||
|
cleanup();
|
||||||
|
reject();
|
||||||
|
};
|
||||||
|
|
||||||
|
scriptTag.onload = () => {
|
||||||
|
resourceRequest.markExecuted({ status: "success" });
|
||||||
|
cleanup();
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
scriptTag.onloadstart = () => {
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptTag.src = config.baseUrl + url;
|
||||||
|
document.body.appendChild(scriptTag);
|
||||||
|
resourceRequest.markExecuting();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultipleOptions = ParallelOptions;
|
||||||
|
export async function loadScripts(paths: SourcePath[], options: MultipleOptions, callback?: LoadCallback<SourcePath>) : Promise<void> {
|
||||||
|
const result = await executeParallelLoad<SourcePath>(paths, e => loadScript(e), 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.request;
|
||||||
|
if(script.error instanceof LoadSyntaxError) {
|
||||||
|
const source = script.error.source as Error;
|
||||||
|
if(source.name === "TypeError") {
|
||||||
|
let prefix = "";
|
||||||
|
while(prefix.length < sname.length + 7) prefix += " ";
|
||||||
|
console.log(" - %s: %s:\n%s", sname, source.message, source.stack.split("\n").map(e => prefix + e.trim()).slice(1).join("\n"));
|
||||||
|
} else if(typeof source === "string") {
|
||||||
|
console.log(" - %s: %s", sname, source);
|
||||||
|
} else {
|
||||||
|
console.log(" - %s: %o", sname, source);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(" - %s: %o", sname, script.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let errorMessage;
|
||||||
|
{
|
||||||
|
const error = result.failed[0].error;
|
||||||
|
if(error instanceof LoadSyntaxError) {
|
||||||
|
errorMessage = error.source.message;
|
||||||
|
} else if(typeof error === "string") {
|
||||||
|
errorMessage = error;
|
||||||
|
} else {
|
||||||
|
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 " + result.failed[0].request, errorMessage);
|
||||||
|
}
|
||||||
|
throw "failed to load script " + result.failed[0].request + " (" + errorMessage + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
import {config, critical_error, loaderPerformance, SourcePath} from "./loader";
|
||||||
|
import {executeParallelLoad, LoadCallback, LoadSyntaxError, ParallelOptions} from "./Utils";
|
||||||
|
|
||||||
|
export function loadStyle(path: SourcePath) : Promise<void> {
|
||||||
|
const givenTimeout = 120 * 1000;
|
||||||
|
|
||||||
|
const resourceRequest = loaderPerformance.logResourceRequest("script", path);
|
||||||
|
resourceRequest.markEnqueue();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const linkTag = document.createElement("link");
|
||||||
|
|
||||||
|
linkTag.type = "text/css";
|
||||||
|
linkTag.rel = "stylesheet";
|
||||||
|
linkTag.href = config.baseUrl + path;
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
linkTag.onerror = undefined;
|
||||||
|
linkTag.onload = undefined;
|
||||||
|
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
};
|
||||||
|
|
||||||
|
const errorCleanup = () => {
|
||||||
|
linkTag.remove();
|
||||||
|
cleanup();
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
resourceRequest.markExecuted({ status: "timeout", givenTimeout: givenTimeout });
|
||||||
|
cleanup();
|
||||||
|
reject("timeout");
|
||||||
|
}, givenTimeout);
|
||||||
|
|
||||||
|
/* TODO: Test if on syntax error the parameters contain extra info */
|
||||||
|
linkTag.onerror = () => {
|
||||||
|
resourceRequest.markExecuted({ status: "error-event" });
|
||||||
|
errorCleanup();
|
||||||
|
reject();
|
||||||
|
};
|
||||||
|
|
||||||
|
linkTag.onload = () => {
|
||||||
|
resourceRequest.markExecuted({ status: "success" });
|
||||||
|
cleanup();
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(linkTag);
|
||||||
|
resourceRequest.markExecuting();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MultipleOptions = ParallelOptions;
|
||||||
|
export async function loadStyles(paths: SourcePath[], options: MultipleOptions, callback?: LoadCallback<SourcePath>) : Promise<void> {
|
||||||
|
const result = await executeParallelLoad<SourcePath>(paths, e => loadStyle(e), 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 = style.request;
|
||||||
|
if(style.error instanceof LoadSyntaxError) {
|
||||||
|
console.log(" - %s: %o", sname, style.error.source);
|
||||||
|
} else {
|
||||||
|
console.log(" - %s: %o", sname, style.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,8 @@
|
||||||
import {SourcePath} from "./loader";
|
|
||||||
import {Options} from "./script_loader";
|
|
||||||
|
|
||||||
export const getUrlParameter = key => {
|
export const getUrlParameter = key => {
|
||||||
const match = location.search.match(new RegExp("(.*[?&]|^)" + key + "=([^&]+)($|&.*)"));
|
const match = location.search.match(new RegExp("(.*[?&]|^)" + key + "=([^&]+)($|&.*)"));
|
||||||
if(!match)
|
if(!match) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return match[2];
|
return match[2];
|
||||||
};
|
};
|
||||||
|
@ -16,24 +14,15 @@ export class LoadSyntaxError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function script_name(path: SourcePath, html: boolean) {
|
export interface ParallelOptions {
|
||||||
if(Array.isArray(path)) {
|
maxParallelRequests?: number
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ParallelResult<T> {
|
export interface ParallelResult<T> {
|
||||||
succeeded: T[];
|
succeeded: T[];
|
||||||
failed: {
|
failed: {
|
||||||
request: T,
|
request: T,
|
||||||
error: T
|
error: any
|
||||||
}[],
|
}[],
|
||||||
|
|
||||||
skipped: T[];
|
skipped: T[];
|
||||||
|
@ -41,15 +30,22 @@ export interface ParallelResult<T> {
|
||||||
|
|
||||||
export type LoadCallback<T> = (entry: T, state: "loading" | "loaded") => void;
|
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 result: ParallelResult<T> = { failed: [], succeeded: [], skipped: [] };
|
||||||
const pendingRequests = requests.slice(0).reverse(); /* we're only able to pop from the back */
|
const pendingRequests = requests.slice(0).reverse(); /* we're only able to pop from the back */
|
||||||
const currentRequests = {};
|
const currentRequests = {};
|
||||||
|
|
||||||
if(typeof callback === "undefined")
|
if(typeof callback === "undefined") {
|
||||||
callback = () => {};
|
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 (pendingRequests.length > 0) {
|
||||||
while(Object.keys(currentRequests).length < maxParallelRequests) {
|
while(Object.keys(currentRequests).length < maxParallelRequests) {
|
||||||
const element = pendingRequests.pop();
|
const element = pendingRequests.pop();
|
||||||
|
@ -60,8 +56,10 @@ export async function load_parallel<T>(requests: T[], executor: (_: T) => Promis
|
||||||
delete currentRequests[name];
|
delete currentRequests[name];
|
||||||
callback(element, "loaded");
|
callback(element, "loaded");
|
||||||
});
|
});
|
||||||
if(pendingRequests.length == 0)
|
|
||||||
|
if(pendingRequests.length == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -69,8 +67,9 @@ export async function load_parallel<T>(requests: T[], executor: (_: T) => Promis
|
||||||
* This should also not throw because any errors will be caught before.
|
* This should also not throw because any errors will be caught before.
|
||||||
*/
|
*/
|
||||||
await Promise.race(Object.keys(currentRequests).map(e => currentRequests[e]));
|
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 */
|
break; /* finish loading the other requests and than show the error */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await Promise.all(Object.keys(currentRequests).map(e => currentRequests[e]));
|
await Promise.all(Object.keys(currentRequests).map(e => currentRequests[e]));
|
||||||
result.skipped.push(...pendingRequests);
|
result.skipped.push(...pendingRequests);
|
|
@ -1,7 +1,6 @@
|
||||||
import * as script_loader from "./script_loader";
|
|
||||||
import * as template_loader from "./template_loader";
|
|
||||||
import * as Animation from "../animation";
|
import * as Animation from "../animation";
|
||||||
import {getUrlParameter} from "./utils";
|
import {getUrlParameter} from "./Utils";
|
||||||
|
import {LoaderPerformanceLogger} from "./Performance";
|
||||||
|
|
||||||
export interface ApplicationLoader {
|
export interface ApplicationLoader {
|
||||||
execute();
|
execute();
|
||||||
|
@ -76,30 +75,9 @@ export enum Stage {
|
||||||
DONE
|
DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
let cache_tag: string | undefined;
|
|
||||||
let currentStage: Stage = undefined;
|
let currentStage: Stage = undefined;
|
||||||
const tasks: {[key:number]: InternalTask[]} = {};
|
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 = {
|
export type ModuleMapping = {
|
||||||
application: string,
|
application: string,
|
||||||
modules: {
|
modules: {
|
||||||
|
@ -111,8 +89,6 @@ export type ModuleMapping = {
|
||||||
const module_mapping_: ModuleMapping[] = [];
|
const module_mapping_: ModuleMapping[] = [];
|
||||||
export function module_mapping() : ModuleMapping[] { return module_mapping_; }
|
export function module_mapping() : ModuleMapping[] { return module_mapping_; }
|
||||||
|
|
||||||
export function get_cache_version() { return cache_tag; }
|
|
||||||
|
|
||||||
export function finished() {
|
export function finished() {
|
||||||
return currentStage == Stage.DONE;
|
return currentStage == Stage.DONE;
|
||||||
}
|
}
|
||||||
|
@ -176,22 +152,28 @@ export function setCurrentTaskName(taskId: number, name: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function execute(customLoadingAnimations: boolean) {
|
export async function execute(customLoadingAnimations: boolean) {
|
||||||
if(!await Animation.initialize(customLoadingAnimations))
|
if(!await Animation.initialize(customLoadingAnimations)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
loader_cache_tag();
|
/* Cleanup <noscript> elements */
|
||||||
|
for(const element of document.getElementsByTagName("noscript")) {
|
||||||
|
element.remove();
|
||||||
|
}
|
||||||
|
|
||||||
const load_begin = Date.now();
|
const timestampBegin = Date.now();
|
||||||
|
|
||||||
let begin: number = 0;
|
let begin: number = 0;
|
||||||
let end: number = Date.now();
|
let end: number = Date.now();
|
||||||
while(currentStage <= Stage.LOADED || typeof(currentStage) === "undefined") {
|
while(currentStage <= Stage.LOADED || typeof currentStage === "undefined") {
|
||||||
|
|
||||||
let pendingTasks: InternalTask[] = [];
|
let pendingTasks: InternalTask[] = [];
|
||||||
while((tasks[currentStage] || []).length > 0) {
|
while((tasks[currentStage] || []).length > 0) {
|
||||||
if(pendingTasks.length == 0 || pendingTasks[0].priority == tasks[currentStage][0].priority) {
|
if(pendingTasks.length == 0 || pendingTasks[0].priority == tasks[currentStage][0].priority) {
|
||||||
pendingTasks.push(tasks[currentStage].pop());
|
pendingTasks.push(tasks[currentStage].pop());
|
||||||
} else break;
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errors: {
|
const errors: {
|
||||||
|
@ -284,7 +266,7 @@ export async function execute(customLoadingAnimations: boolean) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.verbose)
|
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);
|
Animation.finalize(config.abortAnimationOnFinish);
|
||||||
}
|
}
|
||||||
|
@ -353,79 +335,6 @@ export function critical_error_handler(handler?: ErrorHandler, override?: boolea
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loaders */
|
/* loaders */
|
||||||
export type DependSource = {
|
export type SourcePath = string;
|
||||||
url: string;
|
|
||||||
depends: string[];
|
|
||||||
}
|
|
||||||
export type SourcePath = string | DependSource | string[];
|
|
||||||
|
|
||||||
export const scripts = script_loader;
|
export let loaderPerformance = new LoaderPerformanceLogger();
|
||||||
export const templates = template_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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,136 +0,0 @@
|
||||||
import {config, critical_error, SourcePath} from "./loader";
|
|
||||||
import {load_parallel, LoadCallback, LoadSyntaxError, ParallelOptions, script_name} from "./utils";
|
|
||||||
|
|
||||||
let _script_promises: {[key: string]: Promise<void>} = {};
|
|
||||||
|
|
||||||
function load_script_url(url: string) : Promise<void> {
|
|
||||||
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");
|
|
||||||
|
|
||||||
let error = false;
|
|
||||||
const error_handler = (event: ErrorEvent) => {
|
|
||||||
if(event.filename == script_tag.src && event.message.indexOf("Illegal constructor") == -1) { //Our tag throw an uncaught 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);
|
|
||||||
window.removeEventListener('error', error_handler as any);
|
|
||||||
|
|
||||||
reject(new LoadSyntaxError(event.error));
|
|
||||||
event.preventDefault();
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
window.addEventListener('error', error_handler as any);
|
|
||||||
|
|
||||||
const cleanup = () => {
|
|
||||||
script_tag.onerror = undefined;
|
|
||||||
script_tag.onload = undefined;
|
|
||||||
|
|
||||||
clearTimeout(timeout_handle);
|
|
||||||
window.removeEventListener('error', error_handler as any);
|
|
||||||
};
|
|
||||||
const timeout_handle = setTimeout(() => {
|
|
||||||
cleanup();
|
|
||||||
reject("timeout");
|
|
||||||
}, 120 * 1000);
|
|
||||||
script_tag.type = "application/javascript";
|
|
||||||
script_tag.async = true;
|
|
||||||
script_tag.defer = true;
|
|
||||||
script_tag.onerror = error => {
|
|
||||||
cleanup();
|
|
||||||
script_tag.remove();
|
|
||||||
reject(error);
|
|
||||||
};
|
|
||||||
script_tag.onload = () => {
|
|
||||||
cleanup();
|
|
||||||
|
|
||||||
if(config.verbose) console.debug("Script %o loaded", url);
|
|
||||||
setTimeout(resolve, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("scripts").appendChild(script_tag);
|
|
||||||
|
|
||||||
script_tag.src = config.baseUrl + url;
|
|
||||||
})).then(() => {
|
|
||||||
/* cleanup memory */
|
|
||||||
_script_promises[url] = Promise.resolve(); /* this promise does not holds the whole script tag and other memory */
|
|
||||||
return _script_promises[url];
|
|
||||||
}).catch(error => {
|
|
||||||
/* cleanup memory */
|
|
||||||
_script_promises[url] = Promise.reject(error); /* this promise does not holds the whole script tag and other memory */
|
|
||||||
return _script_promises[url];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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 || ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
if(script.error instanceof LoadSyntaxError) {
|
|
||||||
const source = script.error.source as Error;
|
|
||||||
if(source.name === "TypeError") {
|
|
||||||
let prefix = "";
|
|
||||||
while(prefix.length < sname.length + 7) prefix += " ";
|
|
||||||
console.log(" - %s: %s:\n%s", sname, source.message, source.stack.split("\n").map(e => prefix + e.trim()).slice(1).join("\n"));
|
|
||||||
} else if(typeof source === "string") {
|
|
||||||
console.log(" - %s: %s", sname, source);
|
|
||||||
} else {
|
|
||||||
console.log(" - %s: %o", sname, source);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(" - %s: %o", sname, script.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let errorMessage;
|
|
||||||
{
|
|
||||||
const error = result.failed[0].error;
|
|
||||||
if(error instanceof LoadSyntaxError) {
|
|
||||||
errorMessage = error.source.message;
|
|
||||||
} else if(typeof error === "string") {
|
|
||||||
errorMessage = error;
|
|
||||||
} else {
|
|
||||||
console.error("Script %s loading error: %o", script_name(result.failed[0].request, false), error);
|
|
||||||
errorMessage = "View the browser console for more information!";
|
|
||||||
}
|
|
||||||
critical_error("Failed to load script " + script_name(result.failed[0].request, true), errorMessage);
|
|
||||||
}
|
|
||||||
throw "failed to load script " + script_name(result.failed[0].request, false) + " (" + errorMessage + ")";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
import {config, critical_error, SourcePath} from "./loader";
|
|
||||||
import {load_parallel, LoadCallback, LoadSyntaxError, ParallelOptions, script_name} from "./utils";
|
|
||||||
|
|
||||||
let _template_promises: {[key: string]: Promise<void>} = {};
|
|
||||||
|
|
||||||
function load_template_url(url: string) : Promise<void> {
|
|
||||||
if(typeof _template_promises[url] === "object")
|
|
||||||
return _template_promises[url];
|
|
||||||
|
|
||||||
return (_template_promises[url] = (async () => {
|
|
||||||
const response = await (await fetch(config.baseUrl + url)).text();
|
|
||||||
|
|
||||||
let node = document.createElement("html");
|
|
||||||
node.innerHTML = response;
|
|
||||||
let tags: HTMLCollection;
|
|
||||||
if(node.getElementsByTagName("body").length > 0)
|
|
||||||
tags = node.getElementsByTagName("body")[0].children;
|
|
||||||
else
|
|
||||||
tags = node.children;
|
|
||||||
|
|
||||||
let root = document.getElementById("templates");
|
|
||||||
if(!root) {
|
|
||||||
critical_error("Failed to find template tag!");
|
|
||||||
throw "Failed to find template tag";
|
|
||||||
}
|
|
||||||
while(tags.length > 0){
|
|
||||||
let tag = tags.item(0);
|
|
||||||
root.appendChild(tag);
|
|
||||||
|
|
||||||
}
|
|
||||||
})()).then(result => {
|
|
||||||
/* cleanup memory */
|
|
||||||
_template_promises[url] = Promise.resolve(); /* this promise does not holds the whole script tag and other memory */
|
|
||||||
return _template_promises[url];
|
|
||||||
}).catch(error => {
|
|
||||||
/* cleanup memory */
|
|
||||||
_template_promises[url] = Promise.reject(error); /* this promise does not holds the whole script tag and other memory */
|
|
||||||
return _template_promises[url];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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(!_template_promises[depend])
|
|
||||||
throw "Missing dependency " + depend;
|
|
||||||
await _template_promises[depend];
|
|
||||||
}
|
|
||||||
await load_template_url(source.url + (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);
|
|
||||||
if(result.failed.length > 0) {
|
|
||||||
if(config.error) {
|
|
||||||
console.error("Failed to load the following template files:");
|
|
||||||
for(const style of result.failed) {
|
|
||||||
const sname = script_name(style.request, false);
|
|
||||||
if(style.error instanceof LoadSyntaxError) {
|
|
||||||
console.log(" - %s: %o", sname, style.error.source);
|
|
||||||
} else {
|
|
||||||
console.log(" - %s: %o", sname, style.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
critical_error("Failed to load template file " + script_name(result.failed[0].request, true) + " <br>" + "View the browser console for more information!");
|
|
||||||
throw "failed to load template file " + script_name(result.failed[0].request, false);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,9 @@
|
||||||
import * as loader from "./loader/loader";
|
import * as loader from "./loader/loader";
|
||||||
import {config} from "./loader/loader";
|
import {config, loaderPerformance} 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;
|
version: number;
|
||||||
|
|
||||||
chunks: {
|
chunks: {
|
||||||
|
@ -11,6 +12,10 @@ export interface TeaManifest {
|
||||||
hash: string,
|
hash: string,
|
||||||
file: string
|
file: string
|
||||||
}[],
|
}[],
|
||||||
|
css_files: {
|
||||||
|
hash: string,
|
||||||
|
file: string
|
||||||
|
}[],
|
||||||
modules: {
|
modules: {
|
||||||
id: string,
|
id: string,
|
||||||
context: string,
|
context: string,
|
||||||
|
@ -20,24 +25,33 @@ export interface TeaManifest {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let manifest: TeaManifest;
|
let manifest: ApplicationManifest;
|
||||||
export async function loadManifest() : Promise<TeaManifest> {
|
export async function loadManifest() : Promise<ApplicationManifest> {
|
||||||
if(manifest) {
|
if(manifest) {
|
||||||
return manifest;
|
return manifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const requestResource = loaderPerformance.logResourceRequest("json", "manifest.json");
|
||||||
try {
|
try {
|
||||||
const response = await fetch(config.baseUrl + "js/manifest.json?_date=" + Date.now());
|
requestResource.markExecuting();
|
||||||
if(!response.ok) throw response.status + " " + response.statusText;
|
const response = await fetch(config.baseUrl + "/manifest.json?_date=" + Date.now());
|
||||||
|
if(!response.ok) {
|
||||||
|
requestResource.markExecuted({ status: "unknown-error", message: response.status + " " + response.statusText });
|
||||||
|
throw response.status + " " + response.statusText;
|
||||||
|
}
|
||||||
|
|
||||||
manifest = await response.json();
|
manifest = await response.json();
|
||||||
|
requestResource.markExecuted({ status: "success" });
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
|
requestResource.markExecuted({ status: "error-event" });
|
||||||
console.error("Failed to load javascript manifest: %o", error);
|
console.error("Failed to load javascript manifest: %o", error);
|
||||||
loader.critical_error("Failed to load manifest.json", error);
|
loader.critical_error("Failed to load manifest.json", error);
|
||||||
throw "failed to load manifest.json";
|
throw "failed to load manifest.json";
|
||||||
}
|
}
|
||||||
if(manifest.version !== 2)
|
|
||||||
|
if(manifest.version !== 2) {
|
||||||
throw "invalid manifest version";
|
throw "invalid manifest version";
|
||||||
|
}
|
||||||
|
|
||||||
return manifest;
|
return manifest;
|
||||||
}
|
}
|
||||||
|
@ -47,18 +61,30 @@ export async function loadManifestTarget(chunkName: string, taskId: number) {
|
||||||
loader.critical_error("Missing entry chunk in manifest.json", "Chunk " + chunkName + " is missing.");
|
loader.critical_error("Missing entry chunk in manifest.json", "Chunk " + chunkName + " is missing.");
|
||||||
throw "missing entry chunk";
|
throw "missing entry chunk";
|
||||||
}
|
}
|
||||||
|
|
||||||
loader.module_mapping().push({
|
loader.module_mapping().push({
|
||||||
application: chunkName,
|
application: chunkName,
|
||||||
modules: manifest.chunks[chunkName].modules
|
modules: manifest.chunks[chunkName].modules
|
||||||
});
|
});
|
||||||
|
|
||||||
await loader.scripts.load_multiple(manifest.chunks[chunkName].files.map(e => "js/" + e.file), {
|
const kMaxRequests = 4;
|
||||||
cache_tag: undefined,
|
await loadStyles(manifest.chunks[chunkName].css_files.map(e => e.file), {
|
||||||
max_parallel_requests: 4
|
maxParallelRequests: kMaxRequests
|
||||||
}, (script, state) => {
|
}, (entry, state) => {
|
||||||
if(state !== "loading")
|
if (state !== "loading") {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
loader.setCurrentTaskName(taskId, script_name(script, false));
|
loader.setCurrentTaskName(taskId, entry);
|
||||||
|
});
|
||||||
|
|
||||||
|
await loadScripts(manifest.chunks[chunkName].files.map(e => e.file), {
|
||||||
|
maxParallelRequests: kMaxRequests
|
||||||
|
}, (script, state) => {
|
||||||
|
if(state !== "loading") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.setCurrentTaskName(taskId, script);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/* IE11 and safari */
|
/* IE11 and safari */
|
||||||
if(Element.prototype.remove === undefined)
|
if(Element.prototype.remove === undefined) {
|
||||||
Object.defineProperty(Element.prototype, "remove", {
|
Object.defineProperty(Element.prototype, "remove", {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
configurable: false,
|
configurable: false,
|
||||||
|
@ -8,6 +8,7 @@ if(Element.prototype.remove === undefined)
|
||||||
this.parentElement.removeChild(this);
|
this.parentElement.removeChild(this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* IE11 */
|
/* IE11 */
|
||||||
function ReplaceWithPolyfill() {
|
function ReplaceWithPolyfill() {
|
||||||
|
@ -28,14 +29,17 @@ function ReplaceWithPolyfill() {
|
||||||
parent.insertBefore(currentNode, this.nextSibling);
|
parent.insertBefore(currentNode, this.nextSibling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Element.prototype.replaceWith)
|
if (!Element.prototype.replaceWith) {
|
||||||
Element.prototype.replaceWith = ReplaceWithPolyfill;
|
Element.prototype.replaceWith = ReplaceWithPolyfill;
|
||||||
|
}
|
||||||
|
|
||||||
if (!CharacterData.prototype.replaceWith)
|
if (!CharacterData.prototype.replaceWith) {
|
||||||
CharacterData.prototype.replaceWith = ReplaceWithPolyfill;
|
CharacterData.prototype.replaceWith = ReplaceWithPolyfill;
|
||||||
|
}
|
||||||
|
|
||||||
if (!DocumentType.prototype.replaceWith)
|
if (!DocumentType.prototype.replaceWith) {
|
||||||
DocumentType.prototype.replaceWith = ReplaceWithPolyfill;
|
DocumentType.prototype.replaceWith = ReplaceWithPolyfill;
|
||||||
|
}
|
||||||
|
|
||||||
// Source: https://github.com/jserz/js_piece/blob/master/DOM/ParentNode/append()/append().md
|
// Source: https://github.com/jserz/js_piece/blob/master/DOM/ParentNode/append()/append().md
|
||||||
(function (arr) {
|
(function (arr) {
|
||||||
|
|
|
@ -1,62 +1,15 @@
|
||||||
import "./shared";
|
import "./shared";
|
||||||
import * as loader from "../loader/loader";
|
import * as loader from "../loader/loader";
|
||||||
import {ApplicationLoader, SourcePath} from "../loader/loader";
|
import {ApplicationLoader} from "../loader/loader";
|
||||||
import {script_name} from "../loader/utils";
|
|
||||||
import {loadManifest, loadManifestTarget} from "../maifest";
|
import {loadManifest, loadManifestTarget} from "../maifest";
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
native_client: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCacheTag() {
|
|
||||||
return "?_ts=" + (__build.mode === "debug" ? Date.now() : __build.timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoaderTaskCallback = taskId => (script: SourcePath, state) => {
|
|
||||||
if(state !== "loading")
|
|
||||||
return;
|
|
||||||
|
|
||||||
loader.setCurrentTaskName(taskId, script_name(script, false));
|
|
||||||
};
|
|
||||||
|
|
||||||
/* all javascript loaders */
|
|
||||||
const loader_javascript = {
|
|
||||||
load_scripts: async taskId => {
|
|
||||||
loader.setCurrentTaskName(taskId, "manifest");
|
|
||||||
await loadManifest();
|
|
||||||
await loadManifestTarget(__build.entry_chunk_name, taskId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const loader_webassembly = {
|
|
||||||
test_webassembly: async () => {
|
|
||||||
/* We dont required WebAssembly anymore for fundamental functions, only for auto decoding
|
|
||||||
if(typeof (WebAssembly) === "undefined" || typeof (WebAssembly.compile) === "undefined") {
|
|
||||||
console.log(navigator.browserSpecs);
|
|
||||||
if (navigator.browserSpecs.name == 'Safari') {
|
|
||||||
if (parseInt(navigator.browserSpecs.version) < 11) {
|
|
||||||
displayCriticalError("You require Safari 11 or higher to use the web client!<br>Safari " + navigator.browserSpecs.version + " does not support WebAssambly!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Do something for all other browsers.
|
|
||||||
}
|
|
||||||
displayCriticalError("You require WebAssembly for TeaSpeak-Web!");
|
|
||||||
throw "Missing web assembly";
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.INITIALIZING, {
|
loader.register_task(loader.Stage.INITIALIZING, {
|
||||||
name: "secure tester",
|
name: "secure tester",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
/* we need https or localhost to use some things like the storage API */
|
/* we need https or localhost to use some things like the storage API */
|
||||||
if(typeof isSecureContext === "undefined")
|
if(typeof isSecureContext === "undefined") {
|
||||||
(<any>window)["isSecureContext"] = location.protocol !== 'https:' || location.hostname === 'localhost';
|
(window as any)["isSecureContext"] = location.protocol !== 'https:' || location.hostname === 'localhost';
|
||||||
|
}
|
||||||
|
|
||||||
if(!isSecureContext) {
|
if(!isSecureContext) {
|
||||||
loader.critical_error("TeaWeb cant run on unsecured sides.", "App requires to be loaded via HTTPS!");
|
loader.critical_error("TeaWeb cant run on unsecured sides.", "App requires to be loaded via HTTPS!");
|
||||||
|
@ -66,29 +19,12 @@ loader.register_task(loader.Stage.INITIALIZING, {
|
||||||
priority: 20
|
priority: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
loader.register_task(loader.Stage.INITIALIZING, {
|
|
||||||
name: "webassembly tester",
|
|
||||||
function: loader_webassembly.test_webassembly,
|
|
||||||
priority: 20
|
|
||||||
});
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT, {
|
loader.register_task(loader.Stage.JAVASCRIPT, {
|
||||||
name: "scripts",
|
name: "manifest",
|
||||||
function: loader_javascript.load_scripts,
|
|
||||||
priority: 10
|
|
||||||
});
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.TEMPLATES, {
|
|
||||||
name: "templates",
|
|
||||||
function: async taskId => {
|
function: async taskId => {
|
||||||
await loader.templates.load_multiple([
|
loader.setCurrentTaskName(taskId, "manifest");
|
||||||
"templates.html",
|
await loadManifest();
|
||||||
"templates/modal/musicmanage.html",
|
await loadManifestTarget(__build.entry_chunk_name, taskId);
|
||||||
"templates/modal/newcomer.html",
|
|
||||||
], {
|
|
||||||
cache_tag: getCacheTag(),
|
|
||||||
max_parallel_requests: -1
|
|
||||||
}, LoaderTaskCallback(taskId));
|
|
||||||
},
|
},
|
||||||
priority: 10
|
priority: 10
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,9 +11,9 @@ export default class implements ApplicationLoader {
|
||||||
console.log("Doing nothing");
|
console.log("Doing nothing");
|
||||||
|
|
||||||
for(let index of [1, 2, 3]) {
|
for(let index of [1, 2, 3]) {
|
||||||
await new Promise(resolve => {
|
await new Promise<void>(resolve => {
|
||||||
const callback = () => {
|
const callback = () => {
|
||||||
document.removeEventListener("click", resolve);
|
document.removeEventListener("click", callback);
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import "./shared";
|
||||||
import * as loader from "../loader/loader";
|
import * as loader from "../loader/loader";
|
||||||
import {ApplicationLoader, Stage} from "../loader/loader";
|
import {ApplicationLoader, Stage} from "../loader/loader";
|
||||||
import {loadManifest, loadManifestTarget} from "../maifest";
|
import {loadManifest, loadManifestTarget} from "../maifest";
|
||||||
import {getUrlParameter} from "../loader/utils";
|
import {getUrlParameter} from "../loader/Utils";
|
||||||
|
|
||||||
export default class implements ApplicationLoader {
|
export default class implements ApplicationLoader {
|
||||||
execute() {
|
execute() {
|
||||||
|
@ -10,7 +10,7 @@ export default class implements ApplicationLoader {
|
||||||
function: async taskId => {
|
function: async taskId => {
|
||||||
await loadManifest();
|
await loadManifest();
|
||||||
|
|
||||||
const entryChunk = getUrlParameter("chunk");
|
const entryChunk = getUrlParameter("loader-chunk");
|
||||||
if(!entryChunk) {
|
if(!entryChunk) {
|
||||||
loader.critical_error("Missing entry chunk parameter");
|
loader.critical_error("Missing entry chunk parameter");
|
||||||
throw "Missing entry chunk parameter";
|
throw "Missing entry chunk parameter";
|
||||||
|
@ -45,19 +45,6 @@ export default class implements ApplicationLoader {
|
||||||
priority: 10
|
priority: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
loader.register_task(loader.Stage.TEMPLATES, {
|
|
||||||
name: "templates",
|
|
||||||
function: async () => {
|
|
||||||
await loader.templates.load_multiple([
|
|
||||||
"templates.html"
|
|
||||||
], {
|
|
||||||
cache_tag: "?22",
|
|
||||||
max_parallel_requests: -1
|
|
||||||
});
|
|
||||||
},
|
|
||||||
priority: 10
|
|
||||||
});
|
|
||||||
|
|
||||||
loader.execute_managed(false);
|
loader.execute_managed(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import * as loader from "../loader/loader";
|
import * as loader from "../loader/loader";
|
||||||
import {Stage} 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, {
|
loader.register_task(Stage.SETUP, {
|
||||||
name: "app init",
|
name: "app init",
|
||||||
|
@ -13,14 +13,11 @@ loader.register_task(Stage.SETUP, {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.__native_client_init_hook();
|
window.__native_client_init_hook();
|
||||||
window.native_client = true;
|
|
||||||
} else {
|
} else {
|
||||||
if(__build.target !== "web") {
|
if(__build.target !== "web") {
|
||||||
loader.critical_error("App seems not to be compiled for the web.", "This app has been compiled for " + __build.target);
|
loader.critical_error("App seems not to be compiled for the web.", "This app has been compiled for " + __build.target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.native_client = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
priority: 1000
|
priority: 1000
|
||||||
|
@ -50,7 +47,6 @@ loader.register_task(Stage.SETUP, {
|
||||||
case "ie":
|
case "ie":
|
||||||
loader.critical_error("Browser not supported", "We're sorry, but your browser isn't supported.");
|
loader.critical_error("Browser not supported", "We're sorry, but your browser isn't supported.");
|
||||||
throw "unsupported browser";
|
throw "unsupported browser";
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
priority: 50
|
priority: 50
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
**/*.css
|
|
||||||
**/*.css.map
|
|
|
@ -1,216 +0,0 @@
|
||||||
$setup-time-normal: 80s / 24; /* 24 frames / sec; the initial sequence is 80 frames */
|
|
||||||
$setup-time-halloween: 323s / 24;
|
|
||||||
$loop-time-halloween: 25s / 24;
|
|
||||||
|
|
||||||
#loader-overlay {
|
|
||||||
position: absolute;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
background: #1e1e1e;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
z-index: 10000000;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
-webkit-app-region: drag;
|
|
||||||
|
|
||||||
.container {
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
width: 1000px;
|
|
||||||
height: 1000px;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
margin-bottom: 10vh;
|
|
||||||
|
|
||||||
transition-duration: .5s;
|
|
||||||
|
|
||||||
img {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.setup, .idle {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.setup.visible {
|
|
||||||
&.normal {
|
|
||||||
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time-normal forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.halloween {
|
|
||||||
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time-halloween forwards;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.idle.animation-normal {
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.steam {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
top: 282px;
|
|
||||||
left: 380px;
|
|
||||||
|
|
||||||
width: 249px;
|
|
||||||
height: 125px;
|
|
||||||
background: url("img/loader/steam.png") 0 0, url("../img/loader/steam.png") 0 0;
|
|
||||||
|
|
||||||
animation: sprite-steam 2.5s steps(50) forwards infinite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.finishing {
|
|
||||||
.idle {
|
|
||||||
.steam {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bowl {
|
|
||||||
animation: swipe-out-bowl .5s both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
animation: swipe-out-text .5s .12s both;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
animation: overlay-fade .3s .2s both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader-stage {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
left: 5px;
|
|
||||||
bottom: 5px;
|
|
||||||
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: monospace;
|
|
||||||
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 850px) {
|
|
||||||
#loader-overlay .container {
|
|
||||||
transform: scale(.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-height: 700px) {
|
|
||||||
#loader-overlay .container {
|
|
||||||
transform: scale(.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 400px) {
|
|
||||||
#loader-overlay .container {
|
|
||||||
transform: scale(.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes loader-initial-sequence {
|
|
||||||
to {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes sprite-steam {
|
|
||||||
to {
|
|
||||||
background-position: 0 -6250px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes swipe-out-bowl {
|
|
||||||
from {
|
|
||||||
transform: translate3d(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translate3d(-60px, 0, 0) skew(-5deg, 0) rotateY(-6deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translate3d(700px, 0, 0) skew(30deg, 0) rotateZ(-6deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes swipe-out-text {
|
|
||||||
from {
|
|
||||||
transform: translate3d(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translate3d(-30px, 20px, 0) skew(-5deg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translate3d(550px, 0, 0) skew(30deg, 0) scale(.96, 1.25) rotateZ(6deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes animation-nothing {
|
|
||||||
to {
|
|
||||||
background-position: 0 -6250px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes overlay-fade {
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Automated loader timeout */
|
|
||||||
#loader-overlay:not(.initialized) + #critical-load:not(.shown) {
|
|
||||||
display: block !important;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
animation: loader-setup-timeout 0s ease-in $setup-time-normal forwards;
|
|
||||||
|
|
||||||
.error::before {
|
|
||||||
content: 'Failed to startup loader!';
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail::before {
|
|
||||||
content: 'Lookup the console for more details';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@keyframes loader-setup-timeout {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
#overlay-no-js, #critical-load {
|
|
||||||
z-index: 100000000;
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
background: #1e1e1e;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
-webkit-app-region: drag;
|
|
||||||
|
|
||||||
h1, h3, a {
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
top: 20%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.shown {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#critical-load {
|
|
||||||
img {
|
|
||||||
height: 12em
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
color: #bd1515;
|
|
||||||
margin-bottom: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail {
|
|
||||||
color: #696363;
|
|
||||||
margin-top: .5em
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media (max-height: 750px) {
|
|
||||||
#critical-load .container {
|
|
||||||
top: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#critical-load {
|
|
||||||
font-size: .8rem;
|
|
||||||
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#critical-load.shown {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,7 +24,7 @@ export let config: Config;
|
||||||
export type Task = {
|
export type Task = {
|
||||||
name: string,
|
name: string,
|
||||||
priority: number, /* tasks with the same priority will be executed in sync */
|
priority: number, /* tasks with the same priority will be executed in sync */
|
||||||
function: () => Promise<void>
|
function: (taskId: number) => Promise<void>
|
||||||
};
|
};
|
||||||
export enum Stage {
|
export enum Stage {
|
||||||
/*
|
/*
|
||||||
|
@ -86,4 +86,5 @@ export type SourcePath = string | DependSource | string[];
|
||||||
export type ErrorHandler = (message: string, detail: string) => void;
|
export type ErrorHandler = (message: string, detail: string) => void;
|
||||||
export function critical_error(message: string, detail?: string);
|
export function critical_error(message: string, detail?: string);
|
||||||
export function critical_error_handler(handler?: ErrorHandler, override?: boolean);
|
export function critical_error_handler(handler?: ErrorHandler, override?: boolean);
|
||||||
export function hide_overlay();
|
export function hide_overlay();
|
||||||
|
export function setCurrentTaskName(taskId: number, name: string);
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 3.0 MiB After Width: | Height: | Size: 3.0 MiB |
Before Width: | Height: | Size: 472 KiB After Width: | Height: | Size: 472 KiB |
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 4.4 MiB After Width: | Height: | Size: 4.4 MiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,66 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path d="M6.5,41v15c0,1.009,1.22,2,2.463,2h40.074c1.243,0,2.463-0.991,2.463-2V41H6.5z M27.021,51.566
|
||||||
|
c0,0.474-0.087,0.873-0.26,1.196c-0.174,0.323-0.406,0.583-0.697,0.779c-0.292,0.196-0.627,0.333-1.005,0.41
|
||||||
|
s-0.769,0.116-1.169,0.116c-0.201,0-0.436-0.021-0.704-0.062s-0.547-0.104-0.834-0.191s-0.563-0.185-0.827-0.294
|
||||||
|
c-0.265-0.109-0.488-0.232-0.67-0.369l0.697-1.107c0.091,0.063,0.221,0.13,0.39,0.198s0.353,0.132,0.554,0.191
|
||||||
|
c0.2,0.06,0.41,0.111,0.629,0.157s0.424,0.068,0.615,0.068c0.482,0,0.868-0.094,1.155-0.28s0.439-0.504,0.458-0.95v-7.711h1.668
|
||||||
|
V51.566z M34.958,52.298c-0.15,0.342-0.362,0.643-0.636,0.902s-0.611,0.467-1.012,0.622c-0.401,0.155-0.857,0.232-1.367,0.232
|
||||||
|
c-0.219,0-0.444-0.012-0.677-0.034s-0.468-0.062-0.704-0.116c-0.237-0.055-0.463-0.13-0.677-0.226s-0.399-0.212-0.554-0.349
|
||||||
|
l0.287-1.176c0.127,0.073,0.289,0.144,0.485,0.212s0.398,0.132,0.608,0.191c0.209,0.06,0.419,0.107,0.629,0.144
|
||||||
|
c0.209,0.036,0.405,0.055,0.588,0.055c0.556,0,0.982-0.13,1.278-0.39s0.444-0.645,0.444-1.155c0-0.31-0.105-0.574-0.314-0.793
|
||||||
|
c-0.21-0.219-0.472-0.417-0.786-0.595s-0.654-0.355-1.019-0.533c-0.365-0.178-0.707-0.388-1.025-0.629
|
||||||
|
c-0.319-0.241-0.584-0.526-0.793-0.854c-0.21-0.328-0.314-0.738-0.314-1.23c0-0.446,0.082-0.843,0.246-1.189
|
||||||
|
s0.385-0.641,0.663-0.882s0.602-0.426,0.971-0.554s0.759-0.191,1.169-0.191c0.419,0,0.843,0.039,1.271,0.116
|
||||||
|
c0.428,0.077,0.774,0.203,1.039,0.376c-0.055,0.118-0.119,0.248-0.191,0.39c-0.073,0.142-0.142,0.273-0.205,0.396
|
||||||
|
c-0.064,0.123-0.119,0.226-0.164,0.308c-0.046,0.082-0.073,0.128-0.082,0.137c-0.055-0.027-0.116-0.063-0.185-0.109
|
||||||
|
s-0.167-0.091-0.294-0.137c-0.128-0.046-0.297-0.077-0.506-0.096c-0.21-0.019-0.479-0.014-0.807,0.014
|
||||||
|
c-0.183,0.019-0.355,0.07-0.52,0.157s-0.311,0.193-0.438,0.321c-0.128,0.128-0.229,0.271-0.301,0.431
|
||||||
|
c-0.073,0.159-0.109,0.313-0.109,0.458c0,0.364,0.104,0.658,0.314,0.882c0.209,0.224,0.469,0.419,0.779,0.588
|
||||||
|
c0.31,0.169,0.646,0.333,1.012,0.492c0.364,0.159,0.704,0.354,1.019,0.581s0.576,0.513,0.786,0.854
|
||||||
|
c0.209,0.342,0.314,0.781,0.314,1.319C35.184,51.603,35.108,51.956,34.958,52.298z"/>
|
||||||
|
<path d="M51.5,39V13.978c0-0.766-0.092-1.333-0.55-1.792L39.313,0.55C38.964,0.201,38.48,0,37.985,0H8.963
|
||||||
|
C7.777,0,6.5,0.916,6.5,2.926V39H51.5z M29.5,32c0,0.552-0.447,1-1,1s-1-0.448-1-1v-3c0-0.552,0.447-1,1-1s1,0.448,1,1V32z
|
||||||
|
M37.5,3.391c0-0.458,0.553-0.687,0.877-0.363l10.095,10.095C48.796,13.447,48.567,14,48.109,14H37.5V3.391z M36.5,23v-4
|
||||||
|
c0-0.551-0.448-1-1-1c-0.553,0-1-0.448-1-1s0.447-1,1-1c1.654,0,3,1.346,3,3v4c0,1.103,0.897,2,2,2c0.553,0,1,0.448,1,1
|
||||||
|
s-0.447,1-1,1c-1.103,0-2,0.897-2,2v4c0,1.654-1.346,3-3,3c-0.553,0-1-0.448-1-1s0.447-1,1-1c0.552,0,1-0.449,1-1v-4
|
||||||
|
c0-1.2,0.542-2.266,1.382-3C37.042,25.266,36.5,24.2,36.5,23z M28.5,21c0.828,0,1.5,0.672,1.5,1.5S29.328,24,28.5,24
|
||||||
|
S27,23.328,27,22.5S27.672,21,28.5,21z M16.5,25c1.103,0,2-0.897,2-2v-4c0-1.654,1.346-3,3-3c0.553,0,1,0.448,1,1s-0.447,1-1,1
|
||||||
|
c-0.552,0-1,0.449-1,1v4c0,1.2-0.542,2.266-1.382,3c0.84,0.734,1.382,1.8,1.382,3v4c0,0.551,0.448,1,1,1c0.553,0,1,0.448,1,1
|
||||||
|
s-0.447,1-1,1c-1.654,0-3-1.346-3-3v-4c0-1.103-0.897-2-2-2c-0.553,0-1-0.448-1-1S15.947,25,16.5,25z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
@ -1,10 +1,3 @@
|
||||||
<%
|
|
||||||
/* given on compile time */
|
|
||||||
var build_target;
|
|
||||||
var initial_script;
|
|
||||||
var initial_css;
|
|
||||||
%>
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -16,20 +9,20 @@ var initial_css;
|
||||||
|
|
||||||
<meta name="og:description" content="The TeaSpeak Web client is a in the browser running client for the VoIP communication software TeaSpeak." />
|
<meta name="og:description" content="The TeaSpeak Web client is a in the browser running client for the VoIP communication software TeaSpeak." />
|
||||||
<meta name="og:url" content="https://web.teaspeak.de/">
|
<meta name="og:url" content="https://web.teaspeak.de/">
|
||||||
<%# TODO: Put in an appropirate image <meta name="og:image" content="https://www.whatsapp.com/img/whatsapp-promo.png"> %>
|
<% /* TODO: Put in an appropriate image <meta name="og:image" content="https://www.whatsapp.com/img/whatsapp-promo.png"> */ %>
|
||||||
|
|
||||||
<%# Using an absolute path here since the manifest.json works only with such. %>
|
<% /* Using an absolute path here since the manifest.json works only with such. */ %>
|
||||||
<link rel="manifest" href="/manifest.json">
|
<% /* <link rel="manifest" href="/manifest.json"> */ %>
|
||||||
|
|
||||||
<% if(build_target === "client") { %>
|
<% if(buildTarget === "client") { %>
|
||||||
<title>TeaClient</title>
|
<title>TeaClient</title>
|
||||||
<meta name='og:title' content='TeaClient'>
|
<meta name='og:title' content='TeaClient'>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<title>TeaSpeak-Web</title>
|
<title>TeaSpeak-Web</title>
|
||||||
<meta name='og:title' content='TeaSpeak-Web'>
|
<meta name='og:title' content='TeaSpeak-Web'>
|
||||||
<link rel='shortcut icon' href='img/favicon/teacup.png' type='image/x-icon' id="favicon">
|
<link rel='shortcut icon' href='<%= require("./images/favicon_teacup.png") %>' type='image/x-icon' id="favicon">
|
||||||
<%# <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"> */ %>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
@ -47,19 +40,21 @@ var initial_css;
|
||||||
gtag('config', 'UA-113151733-4');
|
gtag('config', 'UA-113151733-4');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<link rel="preload" as="image" href="img/loader/initial-sequence.gif">
|
<link rel="preload" as="image" href="<%= require("./images/initial-sequence.gif") %>">
|
||||||
<link rel="preload" as="image" href="img/loader/bowl.png">
|
<link rel="preload" as="image" href="<%= require("./images/bowl.png") %>">
|
||||||
<%# We don't preload the bowl since it's only a div background %>
|
<% /* We don't preload the bowl since it's only a div background */ %>
|
||||||
<link rel="preload" as="image" href="img/loader/text.png">
|
<link rel="preload" as="image" href="<%= require("./images/text.png") %>">
|
||||||
|
|
||||||
<%- initial_css %>
|
<%= htmlWebpackPlugin.tags.headTags %>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- No javascript error -->
|
<!-- No javascript error -->
|
||||||
<noscript>
|
<noscript>
|
||||||
<div id="overlay-no-js">
|
<div id="overlay-no-js">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img draggable="false" src="img/script.svg" height="128px" alt="no script" >
|
<div class="img">
|
||||||
|
<%= require("!!svg-inline-loader!./images/script.svg") %>
|
||||||
|
</div>
|
||||||
<h1>Please enable JavaScript</h1>
|
<h1>Please enable JavaScript</h1>
|
||||||
<h3>TeaSpeak web could not run without it!</h3>
|
<h3>TeaSpeak web could not run without it!</h3>
|
||||||
<h3>Its like you, without coffee</h3>
|
<h3>Its like you, without coffee</h3>
|
||||||
|
@ -67,24 +62,20 @@ var initial_css;
|
||||||
</div>
|
</div>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
|
||||||
<!-- loader setup -->
|
|
||||||
<div id="style"></div>
|
|
||||||
<div id="scripts"></div>
|
|
||||||
|
|
||||||
<!-- Loading screen -->
|
<!-- Loading screen -->
|
||||||
<div class="loader" id="loader-overlay">
|
<div class="loader" id="loader-overlay">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="setup">
|
<div class="setup">
|
||||||
<lazy-img src="img/loader/initial-sequence.gif" alt="initial loading sequence" x-animation-depend="normal"></lazy-img>
|
<lazy-img src="<%= require("./images/initial-sequence.gif") %>" alt="initial loading sequence" x-animation-depend="normal"></lazy-img>
|
||||||
<lazy-img src="img/loader/halloween-initial-sequence.gif" alt="initial loading sequence" x-animation-depend="halloween"></lazy-img>
|
<lazy-img src="<%= require("./images/halloween-initial-sequence.gif") %>" alt="initial loading sequence" x-animation-depend="halloween"></lazy-img>
|
||||||
</div>
|
</div>
|
||||||
<div class="idle animation-normal">
|
<div class="idle animation-normal">
|
||||||
<lazy-img class="bowl" src="img/loader/bowl.png" alt="bowl" x-animation-depend="normal"></lazy-img>
|
<lazy-img class="bowl" src="<%= require("./images/bowl.png") %>" alt="bowl" x-animation-depend="normal"></lazy-img>
|
||||||
<lazy-img class="text" src="img/loader/text.png" alt="TeaSpeak" x-animation-depend="normal"></lazy-img>
|
<lazy-img class="text" src="<%= require("./images/text.png") %>" alt="TeaSpeak" x-animation-depend="normal"></lazy-img>
|
||||||
<div class="steam"></div>
|
<div class="steam"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="idle animation-halloween">
|
<div class="idle animation-halloween">
|
||||||
<lazy-img src="img/loader/halloween-loop.gif" alt="halloween loop" x-animation-depend="halloween"></lazy-img>
|
<lazy-img src="<%= require("./images/halloween-loop.gif") %>" alt="halloween loop" x-animation-depend="halloween"></lazy-img>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -94,13 +85,15 @@ var initial_css;
|
||||||
<!-- 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 draggable="false" src="img/loading_error_right.svg" alt="load error" />
|
<div class="img">
|
||||||
|
<%= require("!!svg-inline-loader!./images/loading_error_right.svg") %>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h1 class="error"></h1>
|
<h1 class="error"></h1>
|
||||||
<h3 class="detail"></h3>
|
<h3 class="detail"></h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%- initial_script %>
|
<%= htmlWebpackPlugin.tags.bodyTags %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
50
package.json
|
@ -4,14 +4,14 @@
|
||||||
"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.",
|
"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.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile-project-base": "tsc -p tsbaseconfig.json",
|
"compile-project-base": "tsc -p tsbaseconfig.json",
|
||||||
|
"compile-tr-gen": "tsc -p tools/trgen/tsconfig.json",
|
||||||
"trgen": "node tools/trgen/index.js",
|
"trgen": "node tools/trgen/index.js",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"compile-scss": "sass loader/css/index.scss:loader/css/index.css",
|
"compile-scss": "sass loader/css/index.scss:loader/css/index.css",
|
||||||
"start": "npm run compile-project-base && node file.js ndevelop",
|
"start": "npm run compile-project-base && webpack serve --config webpack-web.config.js",
|
||||||
|
"start-client": "npm run compile-project-base && webpack serve --config webpack-client.config.js",
|
||||||
"build-web": "webpack --config webpack-web.config.js",
|
"build-web": "webpack --config webpack-web.config.js",
|
||||||
"build-client": "webpack --config webpack-client.config.js",
|
"build-client": "webpack --config webpack-client.config.js",
|
||||||
"webpack-web": "webpack --config webpack-web.config.js",
|
|
||||||
"webpack-client": "webpack --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)",
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
"@babel/plugin-transform-runtime": "^7.10.4",
|
"@babel/plugin-transform-runtime": "^7.10.4",
|
||||||
"@babel/preset-env": "^7.10.4",
|
"@babel/preset-env": "^7.10.4",
|
||||||
"@google-cloud/translate": "^5.3.0",
|
"@google-cloud/translate": "^5.3.0",
|
||||||
|
"@svgr/webpack": "^5.5.0",
|
||||||
"@types/dompurify": "^2.0.1",
|
"@types/dompurify": "^2.0.1",
|
||||||
"@types/ejs": "^3.0.2",
|
"@types/ejs": "^3.0.2",
|
||||||
"@types/emoji-mart": "^3.0.2",
|
"@types/emoji-mart": "^3.0.2",
|
||||||
|
@ -29,12 +30,12 @@
|
||||||
"@types/html-minifier": "^3.5.3",
|
"@types/html-minifier": "^3.5.3",
|
||||||
"@types/jquery": "^3.3.34",
|
"@types/jquery": "^3.3.34",
|
||||||
"@types/jsrender": "^1.0.5",
|
"@types/jsrender": "^1.0.5",
|
||||||
"@types/loader-utils": "^1.1.3",
|
|
||||||
"@types/lodash": "^4.14.149",
|
"@types/lodash": "^4.14.149",
|
||||||
"@types/moment": "^2.13.0",
|
"@types/moment": "^2.13.0",
|
||||||
"@types/node": "^12.7.2",
|
"@types/node": "^12.7.2",
|
||||||
"@types/react-color": "^3.0.4",
|
"@types/react-color": "^3.0.4",
|
||||||
"@types/react-dom": "^16.9.5",
|
"@types/react-dom": "^16.9.5",
|
||||||
|
"@types/react-grid-layout": "^1.1.1",
|
||||||
"@types/remarkable": "^1.7.4",
|
"@types/remarkable": "^1.7.4",
|
||||||
"@types/sdp-transform": "^2.4.4",
|
"@types/sdp-transform": "^2.4.4",
|
||||||
"@types/sha256": "^0.2.0",
|
"@types/sha256": "^0.2.0",
|
||||||
|
@ -42,14 +43,14 @@
|
||||||
"@types/websocket": "0.0.40",
|
"@types/websocket": "0.0.40",
|
||||||
"@types/xml-parser": "^1.2.29",
|
"@types/xml-parser": "^1.2.29",
|
||||||
"@wasm-tool/wasm-pack-plugin": "^1.3.1",
|
"@wasm-tool/wasm-pack-plugin": "^1.3.1",
|
||||||
|
"autoprefixer": "^10.2.5",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"chunk-manifest-webpack-plugin": "^1.1.2",
|
|
||||||
"circular-dependency-plugin": "^5.2.0",
|
"circular-dependency-plugin": "^5.2.0",
|
||||||
"clean-css": "^4.2.1",
|
"clean-css": "^4.2.1",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
|
"copy-webpack-plugin": "^8.0.0",
|
||||||
"css-loader": "^3.6.0",
|
"css-loader": "^3.6.0",
|
||||||
"csso-cli": "^3.0.0",
|
"css-minimizer-webpack-plugin": "^1.3.0",
|
||||||
"ejs": "^3.0.2",
|
|
||||||
"exports-loader": "^0.7.0",
|
"exports-loader": "^0.7.0",
|
||||||
"fast-xml-parser": "^3.17.4",
|
"fast-xml-parser": "^3.17.4",
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.0.0",
|
||||||
|
@ -57,11 +58,15 @@
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"html-loader": "^1.0.0",
|
"html-loader": "^1.0.0",
|
||||||
"html-minifier": "^4.0.0",
|
"html-minifier": "^4.0.0",
|
||||||
"html-webpack-plugin": "^4.0.3",
|
"html-webpack-inline-source-plugin": "0.0.10",
|
||||||
|
"html-webpack-plugin": "^5.3.1",
|
||||||
|
"inline-chunks-html-webpack-plugin": "^1.3.1",
|
||||||
"mime-types": "^2.1.24",
|
"mime-types": "^2.1.24",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^1.3.9",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^4.14.1",
|
||||||
|
"postcss": "^8.2.8",
|
||||||
|
"postcss-loader": "^5.2.0",
|
||||||
"potpack": "^1.0.1",
|
"potpack": "^1.0.1",
|
||||||
"raw-loader": "^4.0.0",
|
"raw-loader": "^4.0.0",
|
||||||
"sass": "1.22.10",
|
"sass": "1.22.10",
|
||||||
|
@ -73,14 +78,15 @@
|
||||||
"terser-webpack-plugin": "4.2.3",
|
"terser-webpack-plugin": "4.2.3",
|
||||||
"ts-loader": "^6.2.2",
|
"ts-loader": "^6.2.2",
|
||||||
"tsd": "^0.13.1",
|
"tsd": "^0.13.1",
|
||||||
"typescript": "^3.7.0",
|
"typescript": "^4.2",
|
||||||
|
"url-loader": "^4.1.1",
|
||||||
"wabt": "^1.0.13",
|
"wabt": "^1.0.13",
|
||||||
"webpack": "^4.42.1",
|
"webpack": "^5.26.1",
|
||||||
"webpack-bundle-analyzer": "^3.6.1",
|
"webpack-bundle-analyzer": "^3.6.1",
|
||||||
"webpack-cli": "^3.3.11",
|
"webpack-cli": "^4.5.0",
|
||||||
"webpack-svg-sprite-generator": "^1.0.17",
|
"webpack-dev-server": "^3.11.2",
|
||||||
"worker-plugin": "^4.0.3",
|
"webpack-svg-sprite-generator": "^5.0.4",
|
||||||
"xml-parser": "^1.2.1"
|
"zip-webpack-plugin": "^4.0.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -91,8 +97,11 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://www.teaspeak.de",
|
"homepage": "https://www.teaspeak.de",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react-transition-group": "^4.4.0",
|
"@types/crypto-js": "^4.0.1",
|
||||||
"broadcastchannel-polyfill": "^1.0.1",
|
"broadcastchannel-polyfill": "^1.0.1",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"crypto-browserify": "^3.12.0",
|
||||||
|
"crypto-js": "^4.0.0",
|
||||||
"detect-browser": "^5.2.0",
|
"detect-browser": "^5.2.0",
|
||||||
"dompurify": "^2.0.8",
|
"dompurify": "^2.0.8",
|
||||||
"emoji-mart": "git+https://github.com/WolverinDEV/emoji-mart.git",
|
"emoji-mart": "git+https://github.com/WolverinDEV/emoji-mart.git",
|
||||||
|
@ -104,16 +113,17 @@
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
"react-grid-layout": "^1.2.2",
|
||||||
"react-player": "^2.5.0",
|
"react-player": "^2.5.0",
|
||||||
"react-transition-group": "^4.4.1",
|
|
||||||
"remarkable": "^2.0.1",
|
"remarkable": "^2.0.1",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "git+https://github.com/albancreton/resize-observer-polyfill.git#patch-1",
|
||||||
"sdp-transform": "^2.14.0",
|
"sdp-transform": "^2.14.0",
|
||||||
"simple-jsonp-promise": "^1.1.0",
|
"simple-jsonp-promise": "^1.1.0",
|
||||||
"simplebar-react": "^2.2.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"twemoji": "^13.0.0",
|
"twemoji": "^13.0.0",
|
||||||
"url-knife": "^3.1.3",
|
"url-knife": "^3.1.3",
|
||||||
"webcrypto-liner": "^1.2.3",
|
"webcrypto-liner": "^1.2.4",
|
||||||
|
"webpack-manifest-plugin": "^3.1.0",
|
||||||
"webrtc-adapter": "^7.5.1"
|
"webrtc-adapter": "^7.5.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
export = {
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
require("autoprefixer"),
|
||||||
|
"postcss-preset-env",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
|
@ -1,10 +1,8 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "$(dirname "$0")/resolve_commands.sh"
|
|
||||||
cd "$(dirname "$0")/../" || { echo "Failed to enter the base directory"; exit 1; }
|
cd "$(dirname "$0")/../" || { echo "Failed to enter the base directory"; exit 1; }
|
||||||
|
|
||||||
|
|
||||||
if [[ $# -lt 2 ]]; then
|
if [[ $# -lt 2 ]]; then
|
||||||
echo "Invalid argument count!"
|
echo "Invalid argument count!"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -41,7 +39,7 @@ if [[ $_exit_code -ne 0 ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Generating required build tooks"
|
echo "Generating required build hooks"
|
||||||
chmod +x ./tools/build_trgen.sh
|
chmod +x ./tools/build_trgen.sh
|
||||||
./tools/build_trgen.sh; _exit_code=$?
|
./tools/build_trgen.sh; _exit_code=$?
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
if [[ $_exit_code -ne 0 ]]; then
|
||||||
|
@ -49,32 +47,18 @@ if [[ $_exit_code -ne 0 ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Generating style files"
|
|
||||||
npm run compile-scss; _exit_code=$?
|
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
|
||||||
echo "Failed to generate style files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$build_type" == "release" ]]; then # Compile everything for release mode
|
if [[ "$build_type" == "release" ]]; then # Compile everything for release mode
|
||||||
NODE_ENV=production npm run build-$build_target; _exit_code=$?
|
NODE_ENV=production npm run build-$build_target -- --env package=1; _exit_code=$?
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
if [[ $_exit_code -ne 0 ]]; then
|
||||||
echo "Failed to build the $build_target applcation"
|
echo "Failed to build the $build_target application"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "$build_type" == "development" ]]; then
|
elif [[ "$build_type" == "development" ]]; then
|
||||||
NODE_ENV=development npm run build-$build_target; _exit_code=$?
|
NODE_ENV=development npm run build-$build_target -- --env package=1; _exit_code=$?
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
if [[ $_exit_code -ne 0 ]]; then
|
||||||
echo "Failed to build the $build_target applcation"
|
echo "Failed to build the $build_target application"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Generating environment"
|
echo "$build_target build successfully!"
|
||||||
node file.js generate $build_target ${build_type}; _exit_code=$?
|
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
|
||||||
echo "Failed to generate environment"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$build_target builded successfully!"
|
|
|
@ -1,8 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
BASEDIR=$(dirname "$0")
|
BASEDIR=$(dirname "$0")
|
||||||
# shellcheck disable=SC1090
|
|
||||||
source "${BASEDIR}/resolve_commands.sh"
|
|
||||||
cd "$BASEDIR/../" || { echo "Failed to enter parent directory!"; exit 1; }
|
cd "$BASEDIR/../" || { echo "Failed to enter parent directory!"; exit 1; }
|
||||||
|
|
||||||
#Shared
|
#Shared
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
BASEDIR=$(dirname "$0")
|
BASEDIR=$(dirname "$0")
|
||||||
cd "$BASEDIR/../"
|
cd "$BASEDIR/../" || exit
|
||||||
|
|
||||||
# This script cleanups all generated files
|
# This script cleanups all generated files
|
||||||
function remove_if_exists() {
|
function remove_if_exists() {
|
||||||
|
@ -35,7 +35,7 @@ function cleanup_files() {
|
||||||
for file in "${files[@]}"
|
for file in "${files[@]}"
|
||||||
do :
|
do :
|
||||||
echo " - $file"
|
echo " - $file"
|
||||||
rm ${file}
|
rm "${file}"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ if [[ "$1" == "full" ]]; then
|
||||||
echo "Full cleanup. Deleting generated javascript and css files"
|
echo "Full cleanup. Deleting generated javascript and css files"
|
||||||
cleanup_files "shared/js" "*.js" "JavaScript"
|
cleanup_files "shared/js" "*.js" "JavaScript"
|
||||||
cleanup_files "shared/js" "*.js.map" "JavaScript-Mapping"
|
cleanup_files "shared/js" "*.js.map" "JavaScript-Mapping"
|
||||||
|
cleanup_files "shared/js" "*.css" "JavaScript - CSS"
|
||||||
|
cleanup_files "shared/js" "*.css.map" "JavaScript - CSS - Mapping"
|
||||||
cleanup_files "shared/css/static/" "*.css" "CSS" # We only use SCSS, not CSS
|
cleanup_files "shared/css/static/" "*.css" "CSS" # We only use SCSS, not CSS
|
||||||
cleanup_files "shared/css/static/" "*.css.map" "CSS-Mapping"
|
cleanup_files "shared/css/static/" "*.css.map" "CSS-Mapping"
|
||||||
|
|
||||||
|
|
|
@ -2,107 +2,72 @@
|
||||||
|
|
||||||
# Example usage: ./scripts/deploy_ui_files.sh http://dev.clientapi.teaspeak.de/api.php test 1.1.0
|
# Example usage: ./scripts/deploy_ui_files.sh http://dev.clientapi.teaspeak.de/api.php test 1.1.0
|
||||||
|
|
||||||
TMP_FILE_NAME="TeaSpeakUI.tar.gz"
|
cd "$(dirname "$0")" || { echo "failed to enter base directory"; exit 1; }
|
||||||
TMP_DIR_NAME="tmp"
|
source "./helper.sh"
|
||||||
|
|
||||||
cd "$(dirname "$0")/../" || { echo "failed to enter base directory"; exit 1; }
|
|
||||||
|
|
||||||
if [[ "$#" -ne 3 ]]; then
|
if [[ "$#" -ne 3 ]]; then
|
||||||
echo "Illegal number of parameters (url | channel | required version)"
|
echo "Illegal number of parameters (url | channel | required version)"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -d client-api/environment/ui-files/ ]]; then
|
|
||||||
echo "Missing UI Files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
if [[ "${teaclient_deploy_secret}" == "" ]]; then
|
if [[ "${teaclient_deploy_secret}" == "" ]]; then
|
||||||
echo "Missing deploy secret!"
|
echo "Missing deploy secret!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -e "${TMP_FILE_NAME}" ]]; then
|
package_file=$(find_release_package "client" "release")
|
||||||
echo "Temp file already exists!"
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Deleting it!"
|
echo "$package_file"
|
||||||
|
|
||||||
if ! rm ${TMP_FILE_NAME}; then
|
|
||||||
echo "Failed to delete file"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
GIT_HASH=$(git rev-parse --verify --short HEAD)
|
|
||||||
APPLICATION_VERSION=$(< package.json python -c "import sys, json; print(json.load(sys.stdin)['version'])")
|
|
||||||
echo "Git hash ${GIT_HASH} on version ${APPLICATION_VERSION} on channel $2"
|
|
||||||
|
|
||||||
#Packaging the app
|
|
||||||
cd client-api/environment/ui-files/ || {
|
|
||||||
echo "Missing UI files directory"
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
|
||||||
if [[ -e ${TMP_DIR_NAME} ]]; then
|
|
||||||
if ! rm -r ${TMP_DIR_NAME}; then
|
|
||||||
echo "Failed to remove temporary directory!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
cp -rL raw ${TMP_DIR_NAME}
|
|
||||||
|
|
||||||
while IFS= read -r -d '' file
|
# We require a .tar.gz file and not a zip file.
|
||||||
do
|
# So we're extracting the contents and tar.gz ing them
|
||||||
echo "Evaluating php file $file"
|
temp_dir=$(mktemp -d)
|
||||||
__cur_dir=$(pwd)
|
unzip "$package_file" -d "$temp_dir/raw/"
|
||||||
cd "$(dirname "${file}")" || { echo "Failed to enter php file directory"; exit 1; }
|
if [[ $? -ne 0 ]]; then
|
||||||
php_result=$(php "$(basename "${file}")" 2> /dev/null)
|
rm -r "$temp_dir" &>/dev/null
|
||||||
CODE=$?
|
echo "Failed to unpack package."
|
||||||
if [[ ${CODE} -ne 0 ]]; then
|
|
||||||
echo "Failed to evaluate php file $file!"
|
|
||||||
echo "Return code $CODE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "${__cur_dir}" || { echo "failed to enter original dir"; exit 1; }
|
|
||||||
echo "${php_result}" > "${file::-4}.html"
|
|
||||||
done < <(find "${TMP_DIR_NAME}" -name '*.php' -print0)
|
|
||||||
|
|
||||||
cd ${TMP_DIR_NAME} || { echo "failed to enter the temp dir"; exit 1; }
|
|
||||||
tar chvzf ${TMP_FILE_NAME} ./*; _exit_code=$?
|
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
|
||||||
echo "Failed to pack file ($_exit_code)"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
mv ${TMP_FILE_NAME} ../../../../
|
|
||||||
cd ../
|
|
||||||
rm -r ${TMP_DIR_NAME}
|
|
||||||
cd ../../../
|
|
||||||
|
|
||||||
RESP=$(curl \
|
echo "Generating .tar.gz file from $package_file"
|
||||||
|
package_file="$temp_dir/$(basename -s ".zip" "$package_file").tar.gz"
|
||||||
|
tar --use-compress-program="gzip -9" -C "$temp_dir/raw/" -c . -cf "$package_file";
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
rm -r "$temp_dir"
|
||||||
|
echo "Failed to package package."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git_hash=$(git_version "short-tag")
|
||||||
|
application_version=$(project_version)
|
||||||
|
echo "Deploying $package_file."
|
||||||
|
echo "Hash: ${git_hash}, Version: ${application_version}, Target channel: $2."
|
||||||
|
|
||||||
|
upload_result=$(curl \
|
||||||
-k \
|
-k \
|
||||||
-X POST \
|
-X POST \
|
||||||
-F "required_client=$3" \
|
-F "required_client=$3" \
|
||||||
-F "type=deploy-ui-build" \
|
-F "type=deploy-ui-build" \
|
||||||
-F "channel=$2" \
|
-F "channel=$2" \
|
||||||
-F "version=$APPLICATION_VERSION" \
|
-F "version=$application_version" \
|
||||||
-F "git_ref=$GIT_HASH" \
|
-F "git_ref=$git_hash" \
|
||||||
-F "secret=${teaclient_deploy_secret}" \
|
-F "secret=${teaclient_deploy_secret}" \
|
||||||
-F "file=@$(pwd)/TeaSpeakUI.tar.gz" \
|
-F "file=@$package_file" \
|
||||||
"$1"
|
"$1"
|
||||||
)
|
)
|
||||||
echo "$RESP"
|
|
||||||
SUCCESS=$(echo "${RESP}" | python -c "import sys, json; print(json.load(sys.stdin)['success'])")
|
|
||||||
|
|
||||||
if [[ ! "${SUCCESS}" == "True" ]]; then
|
rm -r "$temp_dir"
|
||||||
ERROR=$(echo "${RESP}" | python -c "import sys, json; print(json.load(sys.stdin)['error'])" 2>/dev/null); _exit_code=$?
|
echo "Server upload result: $upload_result"
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
success=$(echo "${upload_result}" | python -c "import sys, json; print(json.load(sys.stdin)['success'])")
|
||||||
ERROR=$(echo "${RESP}" | python -c "import sys, json; print(json.load(sys.stdin)['msg'])" 2>/dev/null)
|
|
||||||
fi
|
|
||||||
echo "Failed to deploy build!"
|
|
||||||
echo "${ERROR}"
|
|
||||||
|
|
||||||
rm ${TMP_FILE_NAME}
|
if [[ ! "${success}" == "True" ]]; then
|
||||||
|
error_message=$(echo "${upload_result}" | python -c "import sys, json; print(json.load(sys.stdin)['msg'])" 2>/dev/null);
|
||||||
|
echo "Failed to deploy build: ${error_message}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
else
|
||||||
|
echo "Build successfully deployed!"
|
||||||
echo "Build deployed!"
|
exit 0
|
||||||
|
fi
|
|
@ -1,26 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
response=$(git diff-index HEAD -- . ':!asm/libraries/' ':!package-lock.json' ':!vendor/')
|
|
||||||
if [[ "$response" != "" ]]; then
|
|
||||||
if [[ "$1" == "sort-tag" ]]; then
|
|
||||||
echo "0000000"
|
|
||||||
fi
|
|
||||||
if [[ "$1" == "name" ]]; then
|
|
||||||
echo "custom build"
|
|
||||||
fi
|
|
||||||
if [[ "$1" == "file-name" ]]; then
|
|
||||||
echo "custom"
|
|
||||||
fi
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
if [[ "$1" == "sort-tag" ]]; then
|
|
||||||
git rev-parse --short HEAD
|
|
||||||
fi
|
|
||||||
if [[ "$1" == "name" ]]; then
|
|
||||||
git rev-parse --short HEAD
|
|
||||||
fi
|
|
||||||
if [[ "$1" == "file-name" ]]; then
|
|
||||||
git rev-parse --short HEAD
|
|
||||||
fi
|
|
||||||
exit 0
|
|
||||||
fi
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
build_package_directory="dist-package"
|
||||||
|
|
||||||
|
# Get the projects absolute directory
|
||||||
|
project_directory() {
|
||||||
|
realpath "$(dirname "$(pwd)/${BASH_SOURCE[0]}")/.."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the project version specified within the package.json file
|
||||||
|
project_version() {
|
||||||
|
< "$(project_directory)/package.json" python -c "import sys, json; print(json.load(sys.stdin)['version'])"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the absolute path to the target release package
|
||||||
|
# Parameters:
|
||||||
|
# 1. The build target
|
||||||
|
# Values: "client" | "web"
|
||||||
|
# 2. The release mode the package has been created
|
||||||
|
# Values: "release" | "development"
|
||||||
|
find_release_package() {
|
||||||
|
local git_version_
|
||||||
|
local package_name_
|
||||||
|
local directory_
|
||||||
|
|
||||||
|
directory_="$(project_directory)/$build_package_directory"
|
||||||
|
if [[ ! -d "$directory_" ]]; then
|
||||||
|
echo "Missing package directory $directory_. May you haven't yet build a package."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git_version_="$(git_version "short-tag")"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo "We're in a development state and have a dirty work tree. Can't find release packages."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
package_name_="$(release_package_name "$1" "$2")"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo "Failed to generate target package name: $package_name_"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$directory_/$package_name_" ]]; then
|
||||||
|
echo "Missing target package at $directory_/$package_name_ (git version: $git_version_, target: $1, release mode: $2)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$directory_/$package_name_"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate the target build package name
|
||||||
|
# Parameters:
|
||||||
|
# 1. The build target
|
||||||
|
# Values: "client" | "web"
|
||||||
|
# 2. The release mode the package has been created
|
||||||
|
# Values: "release" | "development"
|
||||||
|
release_package_name() {
|
||||||
|
local prefix_
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
"client")
|
||||||
|
prefix_="TeaClient"
|
||||||
|
;;
|
||||||
|
"web")
|
||||||
|
prefix_="TeaWeb"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "invalid package mode"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$2" in
|
||||||
|
"release" | "development")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "invalid package mode"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# This must line up with the package name generated within the webpack config!
|
||||||
|
echo "${prefix_}-$2-$(git_version "short-tag").zip"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the current working tree git version.
|
||||||
|
# If the working tree is dirty (modified) the function returns 1.
|
||||||
|
# Possible modes (first parameter):
|
||||||
|
# short-tag: Returns a 6 digit git rev
|
||||||
|
# long-tag: The full git revision hash
|
||||||
|
#
|
||||||
|
# Influential environment variables:
|
||||||
|
# ignore_dirty_worktree: If set to 1 it ignores if the worktree is dirty
|
||||||
|
git_version() {
|
||||||
|
response=$(git diff-index HEAD -- "$(project_directory)" ':!package-lock.json' ':!vendor/')
|
||||||
|
# FIXME: Remove the `1 -eq 1` but for some reason travis fails (I guess the check above is incorrect)
|
||||||
|
if [[ -z "$response" || "${ignore_dirty_worktree:=0}" -eq 1 || 1 -eq 1 ]]; then
|
||||||
|
case "$1" in
|
||||||
|
"short-tag" | "name" | "file-name")
|
||||||
|
git rev-parse --short=8 HEAD
|
||||||
|
;;
|
||||||
|
"long-tag")
|
||||||
|
git rev-parse HEAD
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "unknown type"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
# We're in development
|
||||||
|
case "$1" in
|
||||||
|
"short-tag" | "name" | "file-name" | "long-tag")
|
||||||
|
echo "00000000"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "unknown type"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
|
@ -34,52 +34,5 @@ install_node() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install_rust() {
|
|
||||||
rustup_version=$(rustup --version 2>/dev/null)
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "> Missing rustup, installing..."
|
|
||||||
curl https://build.travis-ci.org/files/rustup-init.sh -sSf | sh -s -- -y --default-toolchain nightly
|
|
||||||
# shellcheck disable=SC2181
|
|
||||||
[[ $? -ne 0 ]] && {
|
|
||||||
echo "> Failed to install rustup"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
PATH="$PATH:$HOME/.cargo/bin"
|
|
||||||
rustup_version=$(rustup --version 2>/dev/null)
|
|
||||||
echo "> Installed $rustup_version"
|
|
||||||
else
|
|
||||||
echo "> Found $rustup_version"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "> Installing/updating the wasm32-unknown-unknown host"
|
|
||||||
rustup target add wasm32-unknown-unknown
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "> Failed to install/updating the wasm target"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
install_wasmpack() {
|
|
||||||
wasmpack_version=$(wasm-pack --version 2>/dev/null)
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "> Missing wasm-pack, installing..."
|
|
||||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
|
||||||
|
|
||||||
# shellcheck disable=SC2181
|
|
||||||
[[ $? -ne 0 ]] && {
|
|
||||||
echo "> Failed to install wasm-pack"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
wasmpack_version=$(wasm-pack --version 2>/dev/null)
|
|
||||||
echo "> Installed $wasmpack_version"
|
|
||||||
else
|
|
||||||
echo "> Found $wasmpack_version"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
install_sys_deps
|
install_sys_deps
|
||||||
install_node
|
install_node
|
||||||
install_rust
|
|
||||||
install_wasmpack
|
|
|
@ -1,28 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
function execute_tsc() {
|
|
||||||
# shellcheck disable=SC2068
|
|
||||||
execute_npm_command tsc $@
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_npm_command() {
|
|
||||||
command_name=$1
|
|
||||||
command_variable="command_$command_name"
|
|
||||||
#echo "Variable names $command_variable"
|
|
||||||
|
|
||||||
if [[ "${!command_variable}" == "" ]]; then
|
|
||||||
node_bin=$(npm bin)
|
|
||||||
#echo "Node root ${node_bin}"
|
|
||||||
|
|
||||||
if [[ ! -e "${node_bin}/${command_name}" ]]; then
|
|
||||||
echo "Could not find \"$command_name\" command"
|
|
||||||
echo "May type npm install"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
eval "${command_variable}=\"${node_bin}/${command_name}\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Arguments: ${@:2}"
|
|
||||||
${!command_variable} ${@:2}
|
|
||||||
}
|
|
|
@ -60,11 +60,11 @@ function parse_arguments() {
|
||||||
function execute() {
|
function execute() {
|
||||||
time_begin=$(date +%s%N)
|
time_begin=$(date +%s%N)
|
||||||
|
|
||||||
echo "> Executing step: $1" >> ${LOG_FILE}
|
echo "> Executing step: $1" >> "${LOG_FILE}"
|
||||||
echo -e "\e[32m> Executing step: $1\e[0m"
|
echo -e "\e[32m> Executing step: $1\e[0m"
|
||||||
#Execute the command
|
#Execute the command
|
||||||
for command in "${@:3}"; do
|
for command in "${@:3}"; do
|
||||||
echo "$> $command" >> ${LOG_FILE}
|
echo "$> $command" >> "${LOG_FILE}"
|
||||||
if [[ ${build_verbose} -gt 0 ]]; then
|
if [[ ${build_verbose} -gt 0 ]]; then
|
||||||
echo "$> $command"
|
echo "$> $command"
|
||||||
fi
|
fi
|
||||||
|
@ -72,18 +72,18 @@ function execute() {
|
||||||
error=""
|
error=""
|
||||||
if [[ ${build_verbose} -gt 0 ]]; then
|
if [[ ${build_verbose} -gt 0 ]]; then
|
||||||
if [[ -f ${LOG_FILE}.tmp ]]; then
|
if [[ -f ${LOG_FILE}.tmp ]]; then
|
||||||
rm ${LOG_FILE}.tmp
|
rm "${LOG_FILE}.tmp"
|
||||||
fi
|
fi
|
||||||
${command} |& tee ${LOG_FILE}.tmp | grep -E '^[^(/\S*/libstdc++.so\S*: no version information available)].*'
|
${command} |& tee "${LOG_FILE}.tmp" | grep -E '^[^(/\S*/libstdc++.so\S*: no version information available)].*'
|
||||||
|
|
||||||
error_code=${PIPESTATUS[0]}
|
error_code=${PIPESTATUS[0]}
|
||||||
error=$(cat ${LOG_FILE}.tmp)
|
error=$(cat "${LOG_FILE}.tmp")
|
||||||
cat ${LOG_FILE}.tmp >> ${LOG_FILE}
|
cat "${LOG_FILE}.tmp" >> "${LOG_FILE}"
|
||||||
rm ${LOG_FILE}.tmp
|
rm "${LOG_FILE}.tmp"
|
||||||
else
|
else
|
||||||
error=$(${command} 2>&1)
|
error=$(${command} 2>&1)
|
||||||
error_code=$?
|
error_code=$?
|
||||||
echo "$error" >> ${LOG_FILE}
|
echo "$error" >> "${LOG_FILE}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,51 +154,20 @@ source ./scripts/install_dependencies.sh
|
||||||
|
|
||||||
echo "---------- Web client ----------"
|
echo "---------- Web client ----------"
|
||||||
|
|
||||||
function move_target_file() {
|
|
||||||
file_name=$(ls -1t | grep -E "^TeaWeb-.*\.zip$" | head -n 1)
|
|
||||||
if [[ -z "$file_name" ]]; then
|
|
||||||
handle_failure -1 "Failed to find target file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "${PACKAGES_DIRECTORY}" || { echo "failed to create target path"; exit 1; }
|
|
||||||
target_file="${PACKAGES_DIRECTORY}/$file_name"
|
|
||||||
if [[ -f "$target_file" ]]; then
|
|
||||||
echo "Removing old packed file located at $target_file"
|
|
||||||
rm "${target_file}" && handle_failure -1 "Failed to remove target file"
|
|
||||||
fi
|
|
||||||
mv "${file_name}" "${target_file}"
|
|
||||||
echo "Moved target file to $target_file"
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_build_release() {
|
function execute_build_release() {
|
||||||
execute \
|
execute \
|
||||||
"Building release package" \
|
"Building release package" \
|
||||||
"Failed to build release" \
|
"Failed to build release" \
|
||||||
"./scripts/build.sh web release"
|
"./scripts/build.sh web release"
|
||||||
|
|
||||||
execute \
|
|
||||||
"Packaging release" \
|
|
||||||
"Failed to package release" \
|
|
||||||
"./scripts/web_package.sh release"
|
|
||||||
|
|
||||||
move_target_file
|
|
||||||
}
|
}
|
||||||
function execute_build_debug() {
|
function execute_build_debug() {
|
||||||
execute \
|
execute \
|
||||||
"Building debug package" \
|
"Building debug package" \
|
||||||
"Failed to build debug" \
|
"Failed to build debug" \
|
||||||
"./scripts/build.sh web dev"
|
"./scripts/build.sh web dev"
|
||||||
|
|
||||||
execute \
|
|
||||||
"Packaging release" \
|
|
||||||
"Failed to package debug" \
|
|
||||||
"./scripts/web_package.sh dev"
|
|
||||||
|
|
||||||
move_target_file
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chmod +x ./scripts/build.sh
|
chmod +x ./scripts/build.sh
|
||||||
chmod +x ./scripts/web_package.sh
|
|
||||||
if [[ ${build_release} ]]; then
|
if [[ ${build_release} ]]; then
|
||||||
execute_build_release
|
execute_build_release
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -2,13 +2,9 @@
|
||||||
|
|
||||||
cd "$(dirname "$0")/../../" || { echo "Failed to enter base dir"; exit 1; }
|
cd "$(dirname "$0")/../../" || { echo "Failed to enter base dir"; exit 1; }
|
||||||
source ./scripts/travis/properties.sh
|
source ./scripts/travis/properties.sh
|
||||||
|
source ./scripts/helper.sh
|
||||||
|
|
||||||
git_rev=$(git rev-parse --short HEAD)
|
git_rev=$(git_version "short-tag")
|
||||||
[[ ! "$git_rev" =~ [a-z0-9]{6} ]] && {
|
|
||||||
echo "Failed to parse git rev. Received: '$git_rev'."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "$1" == "release" ]]; then
|
if [[ "$1" == "release" ]]; then
|
||||||
echo "Releasing $git_rev as release"
|
echo "Releasing $git_rev as release"
|
||||||
rolling_tag="latest"
|
rolling_tag="latest"
|
||||||
|
@ -20,6 +16,7 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# FIXME: This dosn't work anymore
|
||||||
zip_file=$(find "$PACKAGES_DIRECTORY" -maxdepth 1 -name "TeaWeb-release*.zip" -print)
|
zip_file=$(find "$PACKAGES_DIRECTORY" -maxdepth 1 -name "TeaWeb-release*.zip" -print)
|
||||||
[[ $(echo "$zip_file" | wc -l) -ne 1 ]] && {
|
[[ $(echo "$zip_file" | wc -l) -ne 1 ]] && {
|
||||||
echo "Invalid .zip file count (Expected 1 but got $(echo "$zip_file" | wc -l)): ${zip_file[*]}"
|
echo "Invalid .zip file count (Expected 1 but got $(echo "$zip_file" | wc -l)): ${zip_file[*]}"
|
||||||
|
|
|
@ -1,98 +1,92 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
cd "$(dirname "$0")/../../" || { echo "Failed to enter base dir"; exit 1; }
|
cd "$(dirname "$0")/../../" || {
|
||||||
|
echo "Failed to enter base dir"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
source ./scripts/travis/properties.sh
|
source ./scripts/travis/properties.sh
|
||||||
|
source ./scripts/helper.sh
|
||||||
|
|
||||||
if [[ -z "${GIT_AUTHTOKEN}" ]]; then
|
if [[ -z "${GIT_AUTHTOKEN}" ]]; then
|
||||||
echo "GIT_AUTHTOKEN isn't set. Don't deploying build!"
|
echo "GIT_AUTHTOKEN isn't set. Don't deploying build!"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
GIT_COMMIT_SHORT=$(git rev-parse --short HEAD)
|
git_release_executable="/tmp/git-release"
|
||||||
GIT_COMMIT_LONG=$(git rev-parse HEAD)
|
install_git_release() {
|
||||||
echo "Deploying $GIT_COMMIT_SHORT ($GIT_COMMIT_LONG) to github."
|
if [[ -x "${git_release_executable}" ]]; then
|
||||||
|
# File already available. No need to install it.
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
GIT_RELEASE_EXECUTABLE="/tmp/git-release"
|
if [[ ! -f ${git_release_executable} ]]; then
|
||||||
if [[ ! -x ${GIT_RELEASE_EXECUTABLE} ]]; then
|
echo "Downloading github-release-linux (1.2.4)"
|
||||||
if [[ ! -f ${GIT_RELEASE_EXECUTABLE} ]]; then
|
|
||||||
echo "Downloading github-release-linux (1.2.4)"
|
|
||||||
|
|
||||||
if [[ -f /tmp/git-release.gz ]]; then
|
if [[ -f /tmp/git-release.gz ]]; then
|
||||||
rm /tmp/git-release.gz
|
rm /tmp/git-release.gz
|
||||||
fi
|
|
||||||
wget https://github.com/tfausak/github-release/releases/download/1.2.4/github-release-linux.gz -O /tmp/git-release.gz -q;
|
|
||||||
[[ $? -eq 0 ]] || {
|
|
||||||
echo "Failed to download github-release-linux"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
gunzip /tmp/git-release.gz; _exit_code=$?;
|
|
||||||
[[ $_exit_code -eq 0 ]] || {
|
|
||||||
echo "Failed to unzip github-release-linux"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
chmod +x /tmp/git-release;
|
|
||||||
|
|
||||||
echo "Download of github-release-linux (1.2.4) finished"
|
|
||||||
else
|
|
||||||
chmod +x ${GIT_RELEASE_EXECUTABLE}
|
|
||||||
fi
|
fi
|
||||||
|
wget https://github.com/tfausak/github-release/releases/download/1.2.4/github-release-linux.gz -O /tmp/git-release.gz -q
|
||||||
|
[[ $? -eq 0 ]] || {
|
||||||
|
echo "Failed to download github-release-linux"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
if [[ ! -x ${GIT_RELEASE_EXECUTABLE} ]]; then
|
gunzip /tmp/git-release.gz
|
||||||
echo "git-release isn't executable"
|
_exit_code=$?
|
||||||
exit 1
|
[[ $_exit_code -eq 0 ]] || {
|
||||||
fi
|
echo "Failed to unzip github-release-linux"
|
||||||
fi
|
exit 1
|
||||||
|
}
|
||||||
|
chmod +x /tmp/git-release
|
||||||
|
|
||||||
cd "$(dirname "$0")/../../" || { echo "Failed to enter base dir"; exit 1; }
|
echo "Download of github-release-linux (1.2.4) finished"
|
||||||
echo "Generating release"
|
else
|
||||||
${GIT_RELEASE_EXECUTABLE} release \
|
chmod +x ${git_release_executable}
|
||||||
--repo "TeaWeb" \
|
fi
|
||||||
--owner "TeaSpeak" \
|
|
||||||
--token "${GIT_AUTHTOKEN}" \
|
if [[ ! -x ${git_release_executable} ]]; then
|
||||||
--title "Travis autobuild ${GIT_COMMIT_SHORT}" \
|
echo "git-release isn't executable"
|
||||||
--tag "${GIT_COMMIT_SHORT}" \
|
|
||||||
--description "This is a autobuild release from travis"
|
|
||||||
[[ $? -eq 0 ]] || {
|
|
||||||
echo "Failed to generate git release"
|
|
||||||
exit 1
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
install_git_release
|
||||||
|
|
||||||
|
git_versions_tag=$(git_version "short-tag")
|
||||||
|
echo "Deploying $git_versions_tag ($(git_version "long-tag")) to GitHub."
|
||||||
|
|
||||||
|
echo "Generating release tag"
|
||||||
|
${git_release_executable} release \
|
||||||
|
--repo "TeaWeb" \
|
||||||
|
--owner "TeaSpeak" \
|
||||||
|
--token "${GIT_AUTHTOKEN}" \
|
||||||
|
--title "Travis auto build $git_versions_tag" \
|
||||||
|
--tag "$git_versions_tag" \
|
||||||
|
--description "This is a auto build release from travis"
|
||||||
|
|
||||||
|
[[ $? -eq 0 ]] || {
|
||||||
|
echo "Failed to generate git release"
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Uploading release files"
|
upload_package() {
|
||||||
folders=("${LOG_FILE}" "${PACKAGES_DIRECTORY}")
|
local package_file
|
||||||
uploaded_files=()
|
package_file=$(find_release_package "web" "$1")
|
||||||
failed_files=()
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo "Uploading $1 package ($package_file)"
|
||||||
|
${git_release_executable} upload \
|
||||||
|
--repo "TeaWeb" \
|
||||||
|
--owner "TeaSpeak" \
|
||||||
|
--token "${GIT_AUTHTOKEN}" \
|
||||||
|
--tag "$git_versions_tag" \
|
||||||
|
--file "$package_file" \
|
||||||
|
--name "$(basename "$package_file")"
|
||||||
|
|
||||||
for folder in "${folders[@]}"; do
|
echo "Successfully uploaded $1 package"
|
||||||
echo "Scanning folder $folder"
|
else
|
||||||
if [[ ! -d ${folder} ]]; then
|
echo "Skipping $1 package upload: $package_file"
|
||||||
continue;
|
fi
|
||||||
fi
|
}
|
||||||
|
|
||||||
for file in ${folder}*; do
|
upload_package "development"
|
||||||
if [[ -d ${file} ]]; then
|
upload_package "release"
|
||||||
echo " Skipping directory `basename $file` ($file)"
|
exit 0
|
||||||
continue
|
|
||||||
fi
|
|
||||||
echo " Found entry `basename $file` ($file). Uploading file.";
|
|
||||||
|
|
||||||
${GIT_RELEASE_EXECUTABLE} upload \
|
|
||||||
--repo "TeaWeb" \
|
|
||||||
--owner "TeaSpeak" \
|
|
||||||
--token "${GIT_AUTHTOKEN}" \
|
|
||||||
--tag "${GIT_COMMIT_SHORT}" \
|
|
||||||
--file "$file" \
|
|
||||||
--name "`basename $file`"
|
|
||||||
|
|
||||||
[[ $? -eq 0 ]] && {
|
|
||||||
echo " Uploaded.";
|
|
||||||
uploaded_files+="$file"
|
|
||||||
} || {
|
|
||||||
echo "Failed to generate git release"
|
|
||||||
failed_files+="$file"
|
|
||||||
}
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Successfully uploaded ${#uploaded_files[@]} files. ${#failed_files[@]} uploads failed."
|
|
||||||
exit 0
|
|
||||||
|
|
|
@ -5,8 +5,12 @@ if [[ -z "$1" ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$(dirname "$0")/../../" || { echo "Failed to enter base dir"; exit 1; }
|
cd "$(dirname "$0")/../../" || {
|
||||||
|
echo "Failed to enter base dir"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
source ./scripts/travis/properties.sh
|
source ./scripts/travis/properties.sh
|
||||||
|
source ./scripts/helper.sh
|
||||||
|
|
||||||
if [[ -z "${SSH_KEY}" ]]; then
|
if [[ -z "${SSH_KEY}" ]]; then
|
||||||
echo "Missing environment variable SSH_KEY. Please set it before using this script!"
|
echo "Missing environment variable SSH_KEY. Please set it before using this script!"
|
||||||
|
@ -20,31 +24,28 @@ chmod 600 /tmp/sftp_key
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
file=$(find "$PACKAGES_DIRECTORY" -maxdepth 1 -name "TeaWeb-release*.zip" -print)
|
|
||||||
[[ $(echo "$file" | wc -l) -ne 1 ]] && {
|
package_file=$(find_release_package "web" "release")
|
||||||
echo "Invalid release file count (Expected 1 but got $(echo "$file" | wc -l)): ${file[*]}"
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo "$package_file"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
fi
|
||||||
[[ ! -e "$file" ]] && {
|
|
||||||
echo "File ($file) does not exists"
|
upload_name=$(basename "$package_file")
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
#TeaSpeak-Travis-Web
|
|
||||||
# ssh -oStrictHostKeyChecking=no $h TeaSpeak-Travis-Web@dev.web.teaspeak.de
|
|
||||||
ssh -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev rm "tmp-upload/*.zip" # Cleanup the old files
|
ssh -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev rm "tmp-upload/*.zip" # Cleanup the old files
|
||||||
_exit_code=$?
|
_exit_code=$?
|
||||||
[[ $_exit_code -ne 0 ]] && {
|
[[ $_exit_code -ne 0 ]] && {
|
||||||
echo "Failed to delete the old .zip files ($_exit_code)"
|
echo "Failed to delete the old .zip files ($_exit_code)"
|
||||||
}
|
}
|
||||||
|
|
||||||
filename="TeaWeb-Release-$(git rev-parse --short HEAD).zip"
|
|
||||||
sftp -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev << EOF
|
sftp -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev << EOF
|
||||||
put $file tmp-upload/$filename
|
put $package_file tmp-upload/$upload_name
|
||||||
EOF
|
EOF
|
||||||
_exit_code=$?
|
_exit_code=$?
|
||||||
[[ $_exit_code -ne 0 ]] && {
|
[[ $_exit_code -ne 0 ]] && {
|
||||||
echo "Failed to upload the .zip file ($_exit_code)"
|
echo "Failed to upload the .zip file ($_exit_code)"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
ssh -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev "./unpack.sh $1 tmp-upload/$filename"
|
|
||||||
|
ssh -oStrictHostKeyChecking=no -oIdentitiesOnly=yes -i /tmp/sftp_key TeaSpeak-Travis-Web@web.teaspeak.dev "./unpack.sh $1 tmp-upload/$upload_name"
|
||||||
exit $?
|
exit $?
|
|
@ -1,53 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
cd "$(dirname "$0")/../" || { echo "Failed to enter base directory"; exit 1; }
|
|
||||||
|
|
||||||
if [[ "$1" == "development" ]] || [[ "$1" == "dev" ]] || [[ "$1" == "dev" ]]; then
|
|
||||||
source_path="web/environment/development"
|
|
||||||
type="development"
|
|
||||||
elif [[ "$1" == "release" ]] || [[ "$1" == "rel" ]]; then
|
|
||||||
source_path="web/environment/release"
|
|
||||||
type="release"
|
|
||||||
else
|
|
||||||
if [[ $# -lt 1 ]]; then
|
|
||||||
echo "Invalid argument count!"
|
|
||||||
else
|
|
||||||
echo "Invalid option $1"
|
|
||||||
fi
|
|
||||||
echo 'Available options are: "development" or "dev", "release" or "rel"'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "$source_path" ]]; then
|
|
||||||
echo "Could not find environment! ($source_path)"
|
|
||||||
echo "Please generate it first!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
response=$(git diff-index HEAD -- . ':!asm/libraries/' ':!package-lock.json' ':!vendor/')
|
|
||||||
if [[ "$response" != "" ]]; then
|
|
||||||
echo "You're using a private modified build! Cant assign git hash!"
|
|
||||||
NAME="TeaWeb-${type}.zip"
|
|
||||||
else
|
|
||||||
NAME="TeaWeb-${type}-$(git rev-parse --short HEAD).zip"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -e ${NAME} ]]; then
|
|
||||||
echo "Found old file. Deleting it."
|
|
||||||
rm -r "${NAME}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
current_path=$(pwd)
|
|
||||||
cd "$source_path" || { echo "Failed to enter source path"; exit 1; }
|
|
||||||
|
|
||||||
zip -9 -r "${NAME}" ./*; _exit_code=$?
|
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
|
||||||
echo "Failed to package environment!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$current_path" || { echo "Failed to reenter source path"; exit 1; }
|
|
||||||
|
|
||||||
mv "${source_path}/${NAME}" .
|
|
||||||
echo "Release package successfully packaged!"
|
|
||||||
echo "Target file: ${NAME} ($(pwd))"
|
|
|
@ -5,7 +5,6 @@ The following tools or applications are required to develop the web client:
|
||||||
- [1.2 NodeJS](#12-nodejs)
|
- [1.2 NodeJS](#12-nodejs)
|
||||||
- [1.2.2 NPM](#122-npm)
|
- [1.2.2 NPM](#122-npm)
|
||||||
- [1.3 Git bash](#13-git-bash)
|
- [1.3 Git bash](#13-git-bash)
|
||||||
- [1.4 Rust (Options)](#14-rust-optional-will-be-installed-automatically)
|
|
||||||
|
|
||||||
### 1.1 IDE
|
### 1.1 IDE
|
||||||
It does not matter which IDE you use,
|
It does not matter which IDE you use,
|
||||||
|
@ -27,10 +26,6 @@ IMPORTANT: NPM must be available within the PATH environment variable!
|
||||||
For using the `.sh` build scripts you require Git Bash.
|
For using the `.sh` build scripts you require Git Bash.
|
||||||
A minimum of 4.2 is recommend, but in general every modern version should work.
|
A minimum of 4.2 is recommend, but in general every modern version should work.
|
||||||
|
|
||||||
### 1.4 Rust (Optional, will be installed automatically)
|
|
||||||
For building the web client audio library, you may want to install rust in advance.
|
|
||||||
Since it will be installed when executing the install libraries script, I'm not going into more detail here.
|
|
||||||
|
|
||||||
## 2.0 Project initialization
|
## 2.0 Project initialization
|
||||||
|
|
||||||
### 2.1 Cloning the WebClient
|
### 2.1 Cloning the WebClient
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* Country icons from https://www.flaticon.com/packs/rectangular-country-simple-flags?word=country&k=1616497480370 */
|
||||||
|
/* Worldwide: https://www.flaticon.com/free-icon/worldwide_814513?term=earth%20flag&page=1&position=1&page=1&position=1&related_id=814513&origin=search */
|
||||||
|
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs-extra";
|
||||||
|
import {getKnownCountries} from "./js/i18n/CountryFlag";
|
||||||
|
|
||||||
|
const kIconsPath = path.join(__dirname, "img", "country-flags");
|
||||||
|
|
||||||
|
async function fixupAdobeTags() {
|
||||||
|
const icons = await fs.readdir(kIconsPath);
|
||||||
|
for(const icon of icons) {
|
||||||
|
const iconPath = path.join(kIconsPath, icon);
|
||||||
|
|
||||||
|
console.error("Icon: %s", icon);
|
||||||
|
let content = (await fs.readFile(iconPath)).toString();
|
||||||
|
content = content.replace(/<g>\n<\/g>\n/g, "");
|
||||||
|
content = content.replace("\n<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->", "");
|
||||||
|
content = content.replace("id=\"Capa_1\" ", "");
|
||||||
|
content = content.replace("encoding=\"iso-8859-1\"", "encoding=\"utf-8\"");
|
||||||
|
await fs.writeFile(iconPath, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fixupIconNames() {
|
||||||
|
const icons = await fs.readdir(kIconsPath);
|
||||||
|
for(const icon of icons) {
|
||||||
|
if(!icon.match(/^[0-9]{3}-/)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newName = icon.substring(4).replace(/-/g, "_");
|
||||||
|
await fs.rename(path.join(kIconsPath, icon), path.join(kIconsPath, newName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateMapping() {
|
||||||
|
const icons = await fs.readdir(kIconsPath);
|
||||||
|
const knownCountries = getKnownCountries();
|
||||||
|
|
||||||
|
let countFound = 0, countUnknown = 0;
|
||||||
|
for(const country of knownCountries) {
|
||||||
|
let name = country.name;
|
||||||
|
const splitIndex = name.indexOf(",");
|
||||||
|
if(splitIndex !== -1) {
|
||||||
|
name = name.substring(splitIndex + 2) + " " + name.substring(0, splitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
let iconName = name.replace(/ /g, "_").toLocaleLowerCase() + ".svg";
|
||||||
|
|
||||||
|
console.log("array.push({");
|
||||||
|
console.log("name: \"%s\",", country.name);
|
||||||
|
console.log("alpha_2: \"%s\",", country.alpha_2);
|
||||||
|
console.log("alpha_3: \"%s\",", country.alpha_3);
|
||||||
|
console.log("un_code: %d,", country.un_code);
|
||||||
|
if(icons.indexOf(iconName) === -1) {
|
||||||
|
iconName = undefined;
|
||||||
|
console.log("icon: \"%s\", // FIXME: Resolve icons or remove", "worldwide");
|
||||||
|
countUnknown++;
|
||||||
|
} else {
|
||||||
|
console.log("icon: \"%s\",", iconName.replace(".svg", "").replace(/_/g, "-"));
|
||||||
|
countFound++;
|
||||||
|
}
|
||||||
|
console.log("});");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
array.push({
|
||||||
|
name: "Netherlands",
|
||||||
|
alpha_2: "NL",
|
||||||
|
alpha_3: "NLD",
|
||||||
|
un_code: 528
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
console.log("Icons resolved %d. Unresolved %d.", countFound, countUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
//await fixupAdobeTags();
|
||||||
|
//await fixupIconNames();
|
||||||
|
await generateMapping();
|
||||||
|
}
|
||||||
|
main().then(undefined);
|
|
@ -1,17 +0,0 @@
|
||||||
import {Device} from "tc-shared/audio/player";
|
|
||||||
|
|
||||||
export function initialize() : boolean;
|
|
||||||
export function initialized() : boolean;
|
|
||||||
|
|
||||||
export function get_master_volume() : number;
|
|
||||||
export function set_master_volume(volume: number);
|
|
||||||
|
|
||||||
export function on_ready(cb: () => any);
|
|
||||||
|
|
||||||
export function available_devices() : Promise<Device[]>;
|
|
||||||
export function set_device(device_id: string) : Promise<void>;
|
|
||||||
export function current_device() : Device;
|
|
||||||
|
|
||||||
export function initializeFromGesture();
|
|
||||||
|
|
||||||
export function globalAudioContext() : AudioContext;
|
|
|
@ -1,3 +0,0 @@
|
||||||
import {SoundFile} from "tc-shared/sound/Sounds";
|
|
||||||
|
|
||||||
export function play_sound(file: SoundFile) : Promise<void>;
|
|
|
@ -1,6 +0,0 @@
|
||||||
import {AddressTarget, ResolveOptions} from "tc-shared/dns";
|
|
||||||
import {ServerAddress} from "tc-shared/tree/Server";
|
|
||||||
|
|
||||||
export function supported();
|
|
||||||
export function resolve_address(address: ServerAddress, options?: ResolveOptions) : Promise<AddressTarget>;
|
|
||||||
export function resolve_address_ipv4(address: string) : Promise<string>;
|
|
|
@ -1,12 +0,0 @@
|
||||||
import {KeyEvent, KeyHook, SpecialKey} from "tc-shared/PPTListener";
|
|
||||||
|
|
||||||
export function initialize() : Promise<void>;
|
|
||||||
export function finalize(); // most the times not really required
|
|
||||||
|
|
||||||
export function register_key_listener(listener: (_: KeyEvent) => any);
|
|
||||||
export function unregister_key_listener(listener: (_: KeyEvent) => any);
|
|
||||||
|
|
||||||
export function register_key_hook(hook: KeyHook);
|
|
||||||
export function unregister_key_hook(hook: KeyHook);
|
|
||||||
|
|
||||||
export function key_pressed(code: string | SpecialKey) : boolean;
|
|
|
@ -1,2 +0,0 @@
|
||||||
This folder contains declarations files which are required to be implemented
|
|
||||||
Else the UI shared pack wound work
|
|
|
@ -1,74 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
cd "$(dirname "$0")" || exit 1
|
|
||||||
#find css/static/ -name '*.css' -exec cat {} \; | npm run csso -- --output `pwd`/generated/static/base.css
|
|
||||||
|
|
||||||
|
|
||||||
#File order
|
|
||||||
files=(
|
|
||||||
"css/static/properties.css"
|
|
||||||
"css/static/main-layout.css"
|
|
||||||
"css/static/general.css"
|
|
||||||
"css/static/channel-tree.css"
|
|
||||||
"css/static/connection_handlers.css"
|
|
||||||
"css/static/context_menu.css"
|
|
||||||
"css/static/frame-chat.css"
|
|
||||||
"css/static/server-log.css"
|
|
||||||
"css/static/scroll.css"
|
|
||||||
"css/static/hostbanner.css"
|
|
||||||
"css/static/htmltags.css"
|
|
||||||
"css/static/menu-bar.css"
|
|
||||||
"css/static/mixin.css"
|
|
||||||
"css/static/modal.css"
|
|
||||||
"css/static/modals.css"
|
|
||||||
"css/static/modal-about.css"
|
|
||||||
"css/static/modal-avatar.css"
|
|
||||||
"css/static/modal-banclient.css"
|
|
||||||
"css/static/modal-banlist.css"
|
|
||||||
"css/static/modal-bookmarks.css"
|
|
||||||
"css/static/modal-channel.css"
|
|
||||||
"css/static/modal-channelinfo.css"
|
|
||||||
"css/static/modal-clientinfo.css"
|
|
||||||
"css/static/modal-connect.css"
|
|
||||||
"css/static/modal-group-assignment.css"
|
|
||||||
"css/static/modal-icons.css"
|
|
||||||
"css/static/modal-identity.css"
|
|
||||||
"css/static/modal-newcomer.css"
|
|
||||||
"css/static/modal-invite.css"
|
|
||||||
"css/static/modal-keyselect.css"
|
|
||||||
"css/static/modal-poke.css"
|
|
||||||
"css/static/modal-query.css"
|
|
||||||
"css/static/modal-server.css"
|
|
||||||
"css/static/modal-musicmanage.css"
|
|
||||||
"css/static/modal-serverinfobandwidth.css"
|
|
||||||
"css/static/modal-serverinfo.css"
|
|
||||||
"css/static/modal-settings.css"
|
|
||||||
"css/static/overlay-image-preview.css"
|
|
||||||
|
|
||||||
"css/static/ts/tab.css"
|
|
||||||
"css/static/ts/chat.css"
|
|
||||||
"css/static/ts/icons.css"
|
|
||||||
"css/static/ts/icons_em.css"
|
|
||||||
"css/static/ts/country.css"
|
|
||||||
)
|
|
||||||
|
|
||||||
target_file=`pwd`/../generated/static/base.css
|
|
||||||
|
|
||||||
if [[ ! -d $(dirname ${target_file}) ]]; then
|
|
||||||
echo "Creating target path ($(dirname "${target_file}"))"
|
|
||||||
mkdir -p $(dirname "${target_file}")
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "Failed to create target path!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "/* Auto generated merged CSS file */" > "${target_file}"
|
|
||||||
for file in "${files[@]}"; do
|
|
||||||
if [[ ${file} =~ css/* ]]; then
|
|
||||||
file="./${file:4}"
|
|
||||||
fi
|
|
||||||
cat "${file}" >> "${target_file}"
|
|
||||||
done
|
|
||||||
|
|
||||||
cat "${target_file}" | npm run csso -- --output "$(pwd)/../generated/static/base.css"
|
|
|
@ -1,37 +1,26 @@
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/properties.scss"
|
import "./static/properties.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/main-layout.scss"
|
import "./static/main-layout.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/general.scss"
|
import "./static/general.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/frame-chat.scss"
|
import "./static/frame-chat.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/server-log.scss"
|
import "./static/htmltags.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/scroll.scss"
|
import "./static/mixin.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/hostbanner.scss"
|
import "./static/modal.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/htmltags.scss"
|
import "./static/modals.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/menu-bar.scss"
|
import "./static/modal-banclient.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/mixin.scss"
|
import "./static/modal-banlist.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal.scss"
|
import "./static/modal-clientinfo.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modals.scss"
|
import "./static/modal-identity.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-about.scss"
|
import "./static/modal-newcomer.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-avatar.scss"
|
import "./static/modal-keyselect.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-banclient.scss"
|
import "./static/modal-query.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-banlist.scss"
|
import "./static/modal-server.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-bookmarks.scss"
|
import "./static/modal-musicmanage.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-channelinfo.scss"
|
import "./static/modal-settings.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-clientinfo.scss"
|
import "./static/overlay-image-preview.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-connect.scss"
|
import "./static/color-variables.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-group-assignment.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-icons.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-identity.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-newcomer.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-invite.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-keyselect.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-poke.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-query.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-server.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-musicmanage.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-serverinfobandwidth.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-serverinfo.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/modal-settings.scss"
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/overlay-image-preview.scss"
|
|
||||||
|
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/ts/tab.scss"
|
import "./static/ts/tab.scss"
|
||||||
import "!style-loader!css-loader?url=false!sass-loader?sourceMap=true!./static/ts/country.scss"
|
import "./static/ts/country.scss"
|
||||||
|
|
||||||
|
/* Currently not in use */
|
||||||
|
//import "./static/modal-avatar.scss"
|
|
@ -0,0 +1,62 @@
|
||||||
|
html:root {
|
||||||
|
/* Permission editor modal */
|
||||||
|
--modal-permissions-header-text: #e1e1e1;
|
||||||
|
--modal-permissions-header-background: #19191b;
|
||||||
|
--modal-permissions-header-hover: #4e4e4e;
|
||||||
|
--modal-permissions-header-selected: #0073d4;
|
||||||
|
|
||||||
|
--modal-permission-right: #303036;
|
||||||
|
--modal-permission-left: #222226;
|
||||||
|
|
||||||
|
--modal-permissions-entry-hover: #28282c;
|
||||||
|
--modal-permissions-entry-selected: #111111;
|
||||||
|
--modal-permissions-current-group: #101012;
|
||||||
|
|
||||||
|
--modal-permissions-buttons-background: #0f0f0f;
|
||||||
|
--modal-permissions-buttons-hover: #262626;
|
||||||
|
--modal-permissions-buttons-disabled: #1b1b1b;
|
||||||
|
|
||||||
|
--modal-permissions-seperator: #1e1e1e; /* the seperator for the "enter a unique id" and "client info" part */
|
||||||
|
--modal-permissions-container-seperator: #222224; /* the seperator between left and right */
|
||||||
|
|
||||||
|
--modal-permissions-icon-select: #121213;
|
||||||
|
--modal-permissions-icon-select-border: #0d0d0d;
|
||||||
|
--modal-permissions-icon-select-hover: #17171a;
|
||||||
|
--modal-permissions-icon-select-hover-border: #333333;
|
||||||
|
|
||||||
|
--modal-permission-no-permnissions: #18171c;
|
||||||
|
--modal-permissions-table-border: #1e2025;
|
||||||
|
|
||||||
|
--modal-permissions-table-header: #303036;
|
||||||
|
--modal-permissions-table-row-odd: #303036;
|
||||||
|
--modal-permissions-table-row-even: #25252a;
|
||||||
|
--modal-permissions-table-row-hover: #343a47;
|
||||||
|
|
||||||
|
--modal-permissions-table-header-text: #e1e1e1;
|
||||||
|
--modal-permissions-table-row-text: #535455;
|
||||||
|
--modal-permissions-table-entry-active-text: #e1e1e1;
|
||||||
|
--modal-permissions-table-entry-group-text: #e1e1e1;
|
||||||
|
|
||||||
|
--modal-permissions-table-input: #e1e1e1;
|
||||||
|
--modal-permissions-table-input-focus: #3f7dbf;
|
||||||
|
|
||||||
|
/* The host banner */
|
||||||
|
--hostbanner-background: #2e2e2e;
|
||||||
|
|
||||||
|
/* Server Info */
|
||||||
|
--serverinfo-background: #2f2f35;
|
||||||
|
--serverinfo-hostbanner-background: #26222a;
|
||||||
|
|
||||||
|
--serverinfo-group-border: #1f2122;
|
||||||
|
--serverinfo-group-background: #28292b;
|
||||||
|
|
||||||
|
--serverinfo-key: #557edc;
|
||||||
|
--serverinfo-value: #d6d6d7;
|
||||||
|
|
||||||
|
/* Server bandwidth */
|
||||||
|
--serverinfo-bandwidth-upload: #0a5eaa;
|
||||||
|
--serverinfo-bandwidth-download: #9f2712;
|
||||||
|
|
||||||
|
--serverinfo-title: #e3e3e4;
|
||||||
|
--serverinfo-statistics-title: #244c78;
|
||||||
|
}
|
|
@ -1,83 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
html:root {
|
|
||||||
--hostbanner-background: #2e2e2e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hostbanner {
|
|
||||||
.container-hostbanner {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
height: 1000px; /* allocate some height to be truncated by the flex :) */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:not(.no-background) {
|
|
||||||
background-color: var(--hostbanner-background);
|
|
||||||
border-top-left-radius: 5px;
|
|
||||||
border-top-right-radius: 5px;
|
|
||||||
-moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);
|
|
||||||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);
|
|
||||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
padding-bottom: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition(height 0.5s ease-in-out);
|
|
||||||
|
|
||||||
.hostbanner-image-container {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-height: 0;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&.hostbanner-mode-0 {
|
|
||||||
/* do not adjust */
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hostbanner-mode-1 {
|
|
||||||
/* do adjust and ignore ration */
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hostbanner-mode-2 {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-around;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
object-fit: contain;
|
|
||||||
max-height: 100%;
|
|
||||||
|
|
||||||
/* "Normal" third more */
|
|
||||||
//max-width: 100%;
|
|
||||||
|
|
||||||
/* better adoptable mode */
|
|
||||||
width: min-content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,7 @@
|
||||||
.htmltag-client, .htmltag-channel {
|
:global {
|
||||||
color: var(--text);
|
.htmltag-client, .htmltag-channel {
|
||||||
font-weight: bold;
|
color: var(--text);
|
||||||
cursor: pointer;
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -16,77 +16,59 @@ html:root {
|
||||||
|
|
||||||
--channel-chat-seperator: #1e1e1e;
|
--channel-chat-seperator: #1e1e1e;
|
||||||
--channel-chat-seperator-selected: #707070;
|
--channel-chat-seperator-selected: #707070;
|
||||||
|
|
||||||
|
--server-log-text: #6e6e6e;
|
||||||
|
--server-log-error: #e62222;
|
||||||
|
--server-log-tree-entry: #d8d8d8;
|
||||||
|
|
||||||
|
--hostbanner-background: #2e2e2e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-small {
|
:global {
|
||||||
opacity: 1;
|
/* Still in use for the global hang in point */
|
||||||
transition: opacity $animation_length linear;
|
.app-container {
|
||||||
}
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
.show-small {
|
overflow: auto;
|
||||||
display: none;
|
padding: 0;
|
||||||
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity $animation_length linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-container {
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: $small_device) {
|
|
||||||
.hide-small {
|
|
||||||
display: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity $animation_length linear;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-small {
|
$animation_seperator_length: .1s;
|
||||||
display: block !important;
|
.container-seperator {
|
||||||
|
|
||||||
opacity: 1 !important;
|
|
||||||
transition: opacity $animation_length linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$animation_seperator_length: .1s;
|
|
||||||
.container-seperator {
|
|
||||||
@include transition(all $animation_seperator_length ease-in-out);
|
|
||||||
background: var(--channel-chat-seperator);
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
&.horizontal {
|
|
||||||
height: $separator_thickness;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
cursor: row-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.vertical {
|
|
||||||
width: $separator_thickness;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
cursor: col-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.seperator-selected {
|
|
||||||
@include transition(all $animation_seperator_length ease-in-out);
|
@include transition(all $animation_seperator_length ease-in-out);
|
||||||
|
background: var(--channel-chat-seperator);
|
||||||
|
|
||||||
background-color: var(--channel-chat-seperator-selected);
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&.horizontal {
|
||||||
|
height: $separator_thickness;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
cursor: row-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.vertical {
|
||||||
|
width: $separator_thickness;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
cursor: col-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.seperator-selected {
|
||||||
|
@include transition(all $animation_seperator_length ease-in-out);
|
||||||
|
|
||||||
|
background-color: var(--channel-chat-seperator-selected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--app-background)!important;
|
background: var(--app-background)!important;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,133 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
.top-menu-bar {
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
height: 1.5em;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
background: #fafafa;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
z-index: 201;
|
|
||||||
|
|
||||||
font-family: Arial, serif;
|
|
||||||
|
|
||||||
.container-menu-item {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.menu-item {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
padding-left: .4em;
|
|
||||||
padding-right: .4em;
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
width: max-content;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-icon {
|
|
||||||
height: 1.2em;
|
|
||||||
width: 1.2em;
|
|
||||||
padding: .1em;
|
|
||||||
font-size: 1em;
|
|
||||||
|
|
||||||
margin-right: .2em;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-label {
|
|
||||||
display: inline-block;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
a {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background-color: rgba(0, 0, 0, 0.27);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
background-color: rgba(0, 0, 0, 0.13);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-menu {
|
|
||||||
z-index: 1000;
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
background: white;
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
top: 100%;
|
|
||||||
border: 1px solid black;
|
|
||||||
|
|
||||||
> .container-menu-item {
|
|
||||||
padding-right: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.type-side {
|
|
||||||
&.sub-entries:after {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
content: '>';
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
right: .4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .sub-menu {
|
|
||||||
top: -1px; /* border */
|
|
||||||
left: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
> .sub-menu {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: rgba(0, 0, 0, 0.27);
|
|
||||||
|
|
||||||
> .sub-menu {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .container-menu-item {
|
|
||||||
> .menu-item {
|
|
||||||
.container-icon {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin-top: .125em;
|
|
||||||
margin-bottom: .125em;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -66,29 +66,29 @@
|
||||||
user-select: $mode;
|
user-select: $mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin chat-scrollbar() {
|
@mixin chat-scrollbar($width: .5em) {
|
||||||
& {
|
& {
|
||||||
/* for moz */
|
/* for moz */
|
||||||
scrollbar-color: #353535 #555;
|
scrollbar-color: #353535 #555;
|
||||||
scrollbarWidth: .5em;
|
scrollbarWidth: $width;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
border-radius: .25em;
|
border-radius: $width / 2;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: .5em;
|
width: $width;
|
||||||
height: .5em;
|
height: $width;
|
||||||
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
border-radius: .25em;
|
border-radius: $width / 2;
|
||||||
background-color: #555;
|
background-color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
.modal-about {
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: row!important;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
color: #999999;
|
|
||||||
|
|
||||||
.container-left {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-right {
|
|
||||||
text-align: left;
|
|
||||||
padding-left: 2em;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 1.5em;
|
|
||||||
margin-block-start: 0.35em;
|
|
||||||
margin-block-end: 0.35em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 1.25em;
|
|
||||||
margin-block-start: 0.10em;
|
|
||||||
margin-block-end: 0.10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-block-start: .25em;
|
|
||||||
margin-block-end: .25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.version {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
a {
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
.value {
|
|
||||||
padding-left: .25em;
|
|
||||||
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,289 +1,291 @@
|
||||||
.modal-avatar-list {
|
:global {
|
||||||
display: flex!important;;
|
.modal-avatar-list {
|
||||||
flex-direction: row!important;;
|
display: flex!important;;
|
||||||
|
flex-direction: row!important;;
|
||||||
|
|
||||||
.container-list {
|
.container-list {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.column {
|
|
||||||
&.column-username {
|
|
||||||
width: calc(50% - 100px);
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.column-unique-id {
|
|
||||||
width: calc(50% - 100px);
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.column-size {
|
|
||||||
width: 75px;
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.column-timestamp {
|
|
||||||
width: 150px;
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-header {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
.column {
|
|
||||||
border: 1px solid lightgray;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-entries-container {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: start;
|
justify-content: stretch;
|
||||||
overflow-y: auto;
|
|
||||||
min-height: 250px;
|
|
||||||
|
|
||||||
.entry {
|
.column {
|
||||||
|
&.column-username {
|
||||||
|
width: calc(50% - 100px);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.column-unique-id {
|
||||||
|
width: calc(50% - 100px);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.column-size {
|
||||||
|
width: 75px;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.column-timestamp {
|
||||||
|
width: 150px;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
margin-left: 2px;
|
border: 1px solid lightgray;
|
||||||
}
|
text-align: center;
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: lightblue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.scrollbar {
|
.list-entries-container {
|
||||||
.column-username {
|
|
||||||
width: calc(50% - 100px + 30px)
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-unique-id {
|
|
||||||
width: calc(50% - 100px + 30px)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-info {
|
|
||||||
margin-left: 10px;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
.container-data {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-preview {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.container-image {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
width: 302px;
|
|
||||||
height: 302px;
|
|
||||||
|
|
||||||
background-color: whitesmoke;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 2px;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-image-data {
|
|
||||||
margin-left: 10px;
|
|
||||||
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: start;
|
||||||
|
overflow-y: auto;
|
||||||
|
min-height: 250px;
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.column {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: lightblue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scrollbar {
|
||||||
|
.column-username {
|
||||||
|
width: calc(50% - 100px + 30px)
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-unique-id {
|
||||||
|
width: calc(50% - 100px + 30px)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-info {
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
width: 50%;
|
||||||
|
|
||||||
|
.container-data {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-preview {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.container-image {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
width: 302px;
|
||||||
|
height: 302px;
|
||||||
|
|
||||||
|
background-color: whitesmoke;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-image-data {
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-buttons {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled-overlay {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
background-color: gray;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.disabled-overlay {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
background-color: gray;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-around;
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.modal-avatar-upload {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.container-upload {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.bmd-form-group {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="file"] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-preview {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
|
.modal-avatar-upload {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
.title {
|
.container-upload {
|
||||||
font-size: 1.2em;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
border-bottom: 1px solid gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.previews {
|
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-evenly;
|
justify-content: space-between;
|
||||||
|
|
||||||
align-self: center;
|
.bmd-form-group {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.preview {
|
input[type="file"] {
|
||||||
flex-shrink: 1;
|
display: none;
|
||||||
flex-grow: 1;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: 11rem;
|
.container-preview {
|
||||||
min-width: 11rem;
|
flex-grow: 1;
|
||||||
max-width: 11rem;
|
flex-shrink: 1;
|
||||||
|
|
||||||
height: 13rem;
|
display: flex;
|
||||||
min-height: 13rem;
|
flex-direction: column;
|
||||||
max-height: 13rem;
|
justify-content: stretch;
|
||||||
|
|
||||||
text-align: center;
|
.title {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previews {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
justify-content: flex-end;
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
width: 11rem;
|
||||||
|
min-width: 11rem;
|
||||||
|
max-width: 11rem;
|
||||||
|
|
||||||
|
height: 13rem;
|
||||||
|
min-height: 13rem;
|
||||||
|
max-height: 13rem;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
.container-avatar {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
justify-content: space-around;
|
justify-content: flex-end;
|
||||||
|
|
||||||
.avatar {
|
.container-avatar {
|
||||||
position: relative;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
height: 1em;
|
.avatar {
|
||||||
width: 1em;
|
position: relative;
|
||||||
|
|
||||||
overflow: hidden;
|
height: 1em;
|
||||||
border-radius: 50%;
|
width: 1em;
|
||||||
|
|
||||||
> img {
|
overflow: hidden;
|
||||||
position: absolute;
|
border-radius: 50%;
|
||||||
|
|
||||||
top: 0;
|
> img {
|
||||||
left: 0;
|
position: absolute;
|
||||||
|
|
||||||
height: 100%;
|
top: 0;
|
||||||
width: 100%;
|
left: 0;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
|
||||||
|
|
||||||
&.preview-client-info {
|
|
||||||
.container-avatar {
|
|
||||||
font-size: 10rem;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.preview-chat {
|
&.preview-client-info {
|
||||||
.container-avatar {
|
.container-avatar {
|
||||||
font-size: 2.5rem;
|
font-size: 10rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.preview-chat-entry {
|
&.preview-chat {
|
||||||
.container-avatar {
|
.container-avatar {
|
||||||
font-size: 2rem;
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.preview-chat-entry {
|
||||||
|
.container-avatar {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,7 +294,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 40rem) {
|
@media all and (max-width: 40rem) {
|
||||||
.modal-avatar-upload .container-preview .previews {
|
:global {
|
||||||
flex-direction: column;
|
.modal-avatar-upload .container-preview .previews {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,293 +1,295 @@
|
||||||
@import "mixin";
|
@import "mixin";
|
||||||
@import "properties";
|
@import "properties";
|
||||||
|
|
||||||
//TODO: Resize style!
|
:global {
|
||||||
.modal-body.modal-ban-client {
|
//TODO: Resize style!
|
||||||
padding: 0!important;
|
.modal-body.modal-ban-client {
|
||||||
|
padding: 0!important;
|
||||||
|
|
||||||
display: flex!important;
|
display: flex!important;
|
||||||
flex-direction: column!important;
|
flex-direction: column!important;
|
||||||
justify-content: stretch!important;
|
justify-content: stretch!important;
|
||||||
|
|
||||||
//min-width: 30em!important;
|
//min-width: 30em!important;
|
||||||
max-height: calc(100vh - 10em);
|
max-height: calc(100vh - 10em);
|
||||||
width: 40em;
|
width: 40em;
|
||||||
|
|
||||||
min-height: 20em;
|
min-height: 20em;
|
||||||
|
|
||||||
.container-tooltip {
|
.container-tooltip {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1.6em;
|
width: 1.6em;
|
||||||
|
|
||||||
margin-left: .5em;
|
margin-left: .5em;
|
||||||
margin-right: .25em;
|
margin-right: .25em;
|
||||||
|
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 1em;
|
height: 1em;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.container-info {
|
||||||
display: none;
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
padding: .5em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.container {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
min-width: 4em;
|
||||||
|
width: 10em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #557edc;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-height: 2em;
|
||||||
|
|
||||||
|
padding: .5em;
|
||||||
|
|
||||||
|
border-radius: 0.2em;
|
||||||
|
border: 1px solid #111112;
|
||||||
|
background-color: #121213;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
@include chat-scrollbar-vertical();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.container-info {
|
.container-duration {
|
||||||
flex-shrink: 0;
|
margin: 1em;
|
||||||
flex-grow: 0;
|
margin-top: 0em;
|
||||||
|
|
||||||
padding: .5em;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
display: flex;
|
> a {
|
||||||
flex-direction: row;
|
flex-grow: 0;
|
||||||
justify-content: stretch;
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container-value {
|
||||||
flex-grow: 1;
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.input-boxed.value {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
min-width: 6em;
|
||||||
|
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 7em;
|
||||||
|
padding-left: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-reason {
|
||||||
|
margin: 1em;
|
||||||
|
margin-top: 0em;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
flex-grow: 0;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
|
||||||
min-width: 4em;
|
min-height: 5em;
|
||||||
width: 10em;
|
max-height: 22.5em;
|
||||||
|
|
||||||
|
border-radius: .2em;
|
||||||
|
border: 1px solid #111112;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
.title {
|
.toolbar {
|
||||||
text-transform: uppercase;
|
flex-shrink: 0;
|
||||||
color: #557edc;
|
flex-grow: 0;
|
||||||
|
|
||||||
overflow: hidden;
|
display: flex;
|
||||||
white-space: nowrap;
|
flex-direction: row;
|
||||||
text-overflow: ellipsis;
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 2.5em;
|
||||||
|
|
||||||
|
background-color: #17171a;
|
||||||
|
font-size: .8em;
|
||||||
|
|
||||||
|
padding: .25em;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
padding: .5em;
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-left: .25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
border-radius: .2em;
|
||||||
|
border: 1px solid #111112;
|
||||||
|
|
||||||
|
background-color: #121213;
|
||||||
|
|
||||||
|
height: 2em;
|
||||||
|
width: 2em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
&.button-bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.button-italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.button-underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.button-color {
|
||||||
|
input {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #0f0f0f;
|
||||||
|
@include transition(background-color $button_hover_animation_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
> .input-boxed {
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
min-height: 2em;
|
flex-grow: 1;
|
||||||
|
|
||||||
padding: .5em;
|
min-height: 2.5em;
|
||||||
|
height: 5em;
|
||||||
|
max-height: 20em;
|
||||||
|
|
||||||
border-radius: 0.2em;
|
border: none;
|
||||||
border: 1px solid #111112;
|
border-radius: 0;
|
||||||
background-color: #121213;
|
border-top: 1px solid #111112;
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
overflow-x: hidden;;
|
||||||
text-overflow: ellipsis;
|
overflow-y: auto;
|
||||||
|
|
||||||
|
resize: vertical;
|
||||||
|
|
||||||
@include chat-scrollbar-vertical();
|
@include chat-scrollbar-vertical();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-duration {
|
&:focus-within {
|
||||||
margin: 1em;
|
background-color: #131b22;
|
||||||
margin-top: 0em;
|
//border-color: #284262;
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-value {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.input-boxed.value {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 6em;
|
|
||||||
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
width: 7em;
|
|
||||||
padding-left: .5em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.container-reason {
|
.container-criteria {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
margin-top: 0em;
|
margin-top: 0em;
|
||||||
position: relative;
|
padding: .5em;
|
||||||
|
|
||||||
flex-grow: 0;
|
border-radius: 0.2em;
|
||||||
flex-shrink: 1;
|
border: 1px solid #111112;
|
||||||
|
background-color: #121213;
|
||||||
min-height: 5em;
|
|
||||||
max-height: 22.5em;
|
|
||||||
|
|
||||||
border-radius: .2em;
|
|
||||||
border: 1px solid #111112;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 2.5em;
|
|
||||||
|
|
||||||
background-color: #17171a;
|
|
||||||
font-size: .8em;
|
|
||||||
|
|
||||||
padding: .25em;
|
|
||||||
|
|
||||||
.button {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
&:not(:first-child) {
|
|
||||||
margin-left: .25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
border-radius: .2em;
|
|
||||||
border: 1px solid #111112;
|
|
||||||
|
|
||||||
background-color: #121213;
|
|
||||||
|
|
||||||
height: 2em;
|
|
||||||
width: 2em;
|
|
||||||
|
|
||||||
|
.criteria {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
|
|
||||||
text-align: center;
|
a {
|
||||||
align-self: center;
|
flex-shrink: 1;
|
||||||
|
min-width: 4em;
|
||||||
|
|
||||||
&.button-bold {
|
text-transform: uppercase;
|
||||||
font-weight: bold;
|
color: #557edc;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.button-italic {
|
label {
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.button-underline {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.button-color {
|
|
||||||
input {
|
|
||||||
position: absolute;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #0f0f0f;
|
|
||||||
@include transition(background-color $button_hover_animation_time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .input-boxed {
|
.container-buttons {
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-height: 2.5em;
|
|
||||||
height: 5em;
|
|
||||||
max-height: 20em;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
border-top: 1px solid #111112;
|
|
||||||
|
|
||||||
|
|
||||||
overflow-x: hidden;;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
resize: vertical;
|
|
||||||
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus-within {
|
|
||||||
background-color: #131b22;
|
|
||||||
//border-color: #284262;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-criteria {
|
|
||||||
margin: 1em;
|
|
||||||
margin-top: 0em;
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
border-radius: 0.2em;
|
|
||||||
border: 1px solid #111112;
|
|
||||||
background-color: #121213;
|
|
||||||
|
|
||||||
.criteria {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: flex-end;
|
||||||
|
|
||||||
a {
|
margin: 1em;
|
||||||
flex-shrink: 1;
|
margin-top: 0em;
|
||||||
min-width: 4em;
|
|
||||||
|
|
||||||
text-transform: uppercase;
|
button:not(:first-of-type) {
|
||||||
color: #557edc;
|
margin-left: 1em;
|
||||||
|
width: 6em;
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
margin: 1em;
|
|
||||||
margin-top: 0em;
|
|
||||||
|
|
||||||
button:not(:first-of-type) {
|
|
||||||
margin-left: 1em;
|
|
||||||
width: 6em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,498 +0,0 @@
|
||||||
@import "properties";
|
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
.modal .modal-bookmark-create {
|
|
||||||
.property {
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.key {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
select, input {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
text-align: right;
|
|
||||||
|
|
||||||
button {
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body.modal-bookmarks {
|
|
||||||
padding: 0!important;
|
|
||||||
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: row!important;
|
|
||||||
justify-content: stretch!important;
|
|
||||||
|
|
||||||
min-width: 30em!important;
|
|
||||||
height: 45em;
|
|
||||||
width: 80em;
|
|
||||||
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
.container-tooltip {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
width: 1.6em;
|
|
||||||
margin-left: .5em;
|
|
||||||
font-size: .9em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-boxed {
|
|
||||||
height: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
|
||||||
min-width: 12em;
|
|
||||||
width: 30%;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
background-color: #212125;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
font-size: 1.5em;
|
|
||||||
color: #557edc;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
@include text-dotdotdot();
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-bookmarks {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-height: 6em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
@include chat-scrollbar-horizontal();
|
|
||||||
|
|
||||||
.bookmark, .directory {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
border-radius: $border_radius_middle;
|
|
||||||
padding: .25em .5em;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
margin-right: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 5em;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
@include text-dotdotdot();
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #2c2d2f;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: #1a1a1b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
width: 1.5em;
|
|
||||||
|
|
||||||
$line_width: 2px;
|
|
||||||
$color: hsla(0, 0%, 35%, 1);
|
|
||||||
&:not(.hidden) {
|
|
||||||
&:before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
height: 2.25em; /* connect with the previous one */
|
|
||||||
width: .75em;
|
|
||||||
|
|
||||||
left: .5em; /* icons have a width of 1em */
|
|
||||||
bottom: calc(.75em - #{$line_width / 2});
|
|
||||||
|
|
||||||
border-left: $line_width solid $color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.connected {
|
|
||||||
&:before {
|
|
||||||
border-bottom: $line_width solid $color;
|
|
||||||
|
|
||||||
border-bottom-left-radius: .3em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-start {
|
|
||||||
.link.connected {
|
|
||||||
&:before {
|
|
||||||
height: 1.25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory {
|
|
||||||
.name {
|
|
||||||
//color: #557edc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
padding-top: .5em;
|
|
||||||
|
|
||||||
button {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
min-width: 25em;
|
|
||||||
width: 30%;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
background-color: #2f2f35;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
.header {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
height: 10em;
|
|
||||||
|
|
||||||
background: url('../../../img/bookmark_background.png'), url('../../img/bookmark_background.png'), url('img/bookmark_background.png') no-repeat;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
.container-name {
|
|
||||||
font-size: 2em;
|
|
||||||
color: #fcfcfc;
|
|
||||||
|
|
||||||
@include text-dotdotdot();
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-address {
|
|
||||||
font-size: 1.5em;
|
|
||||||
color: #fcfcfc;
|
|
||||||
|
|
||||||
@include text-dotdotdot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-settings {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-height: 10em;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
|
|
||||||
.group {
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
border-radius: .2em;
|
|
||||||
border: 1px solid #1f2122;
|
|
||||||
|
|
||||||
background-color: #28292b;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
> .row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.key {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
width: 15em;
|
|
||||||
min-width: 2em;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
color: #557edc;
|
|
||||||
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 2em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.info {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-image {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
max-width: 15em;
|
|
||||||
max-height: 9em; /* minus one padding */
|
|
||||||
width: 15em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition(.25s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-properties {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-width: 23em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
height: inherit;
|
|
||||||
|
|
||||||
.row {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
height: 1.8em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
.key {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
color: #557edc;
|
|
||||||
text-transform: uppercase;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
width: 15em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
color: #d6d6d7;
|
|
||||||
align-self: center;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
&.server-region {
|
|
||||||
> div {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.country {
|
|
||||||
margin-right: .25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.connect-count, .connect-never {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
color: #7a3131;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-network {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.container-button {
|
|
||||||
margin-right: 1em;
|
|
||||||
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 5em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: 2.5em;
|
|
||||||
width: 12em;
|
|
||||||
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
@include text-dotdotdot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
padding: .5em;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
.button-duplicate {
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-width: 2em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media all and (max-width: 50em) {
|
|
||||||
.modal-body.modal-bookmarks {
|
|
||||||
.container-image {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 0!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
@import "properties";
|
|
||||||
|
|
||||||
.modal-body.modal-channel-info {
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
justify-content: stretch!important;
|
|
||||||
|
|
||||||
min-width: 30em!important;
|
|
||||||
max-height: calc(100vh - 10em)!important;
|
|
||||||
padding: 0 !important;
|
|
||||||
|
|
||||||
.row {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
padding-top: 1em;
|
|
||||||
padding-left: .5em;
|
|
||||||
padding-right: .5em;
|
|
||||||
|
|
||||||
.column {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 6em;
|
|
||||||
width: 10em;
|
|
||||||
|
|
||||||
margin-right: .5em;
|
|
||||||
margin-left: .5em;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: #557edc;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.audio-encrypted {
|
|
||||||
/* looks better */
|
|
||||||
.value {
|
|
||||||
height: 1.6em;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-description {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-height: 8em; /* description plus title */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
padding-top: 1em;
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: 1em;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: #557edc;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
.button-copy {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
margin-top: .1em; /* looks a bit better */
|
|
||||||
margin-left: .5em;
|
|
||||||
border-radius: .2em;
|
|
||||||
|
|
||||||
width: 1.3em;
|
|
||||||
height: 1.3em;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
div {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #313135;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition($button_hover_animation_time ease-in-out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
display: block;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
border-radius: 0.2em;
|
|
||||||
border: 1px solid #212324;
|
|
||||||
background-color: #3a3b3f;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
height: max-content;
|
|
||||||
min-height: 6em;
|
|
||||||
max-height: 40em;
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-value {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
font-size: 1.25em;
|
|
||||||
height: (6em / 1.25); /* min value height and a bit more */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,353 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
.modal .modal-connect {
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
font-size: 1rem;
|
|
||||||
max-width: 100000px; /* max 100000px width, else we shrink the modal */
|
|
||||||
padding: 0!important; /* override the default padding */
|
|
||||||
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
justify-content: stretch!important;
|
|
||||||
|
|
||||||
.container-connect-input {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
/* apply the default padding */
|
|
||||||
padding: .75em 24px;
|
|
||||||
|
|
||||||
border-left: 2px solid #0073d4;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
> .row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
> *:not(:last-of-type) {
|
|
||||||
margin-right: 3em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-address-password {
|
|
||||||
.container-address {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-password {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 4;
|
|
||||||
|
|
||||||
min-width: 21.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-profile-manage {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 4;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.container-select-profile {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 14em;
|
|
||||||
|
|
||||||
> .invalid-feedback {
|
|
||||||
width: max-content; /* allow overflow here */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-manage {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 4;
|
|
||||||
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-manage-profiles {
|
|
||||||
min-width: 7em;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-nickname {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
padding-top: 1em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.container-buttons-connect {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-right {
|
|
||||||
min-width: 7em;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-left {
|
|
||||||
min-width: 14em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.arrow {
|
|
||||||
border-color: #7a7a7a;
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-last-servers {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
max-height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
border-left: 2px solid #7a7a7a;
|
|
||||||
|
|
||||||
@include transition(max-height .5s ease-in-out, opacity .5s ease-in-out, padding .5s ease-in-out);
|
|
||||||
&.shown {
|
|
||||||
/* apply the default padding */
|
|
||||||
padding: 0 24px 24px;
|
|
||||||
|
|
||||||
max-height: 100%;
|
|
||||||
opacity: 1;
|
|
||||||
|
|
||||||
@include transition(max-height .5s ease-in-out, opacity .5s ease-in-out, padding .5s ease-in-out)
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
height: 0;
|
|
||||||
width: calc(100% + 46px);
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
margin: 0 0 0 -23px;
|
|
||||||
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
border-top: 1px solid #090909;
|
|
||||||
|
|
||||||
margin-bottom: .75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
color: #7a7a7a;
|
|
||||||
|
|
||||||
/* general table class */
|
|
||||||
.table {
|
|
||||||
width: 100em;
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.head {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid #161618;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.body {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
.row {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #202022;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: #131315;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.body-empty {
|
|
||||||
height: 3em;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-around;
|
|
||||||
font-size: 1.25em;
|
|
||||||
color: rgba(121, 121, 121, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.column {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
padding-right: .25em;
|
|
||||||
padding-left: .25em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
&:not(:last-of-type) {
|
|
||||||
border-right: 1px solid #161618;
|
|
||||||
}
|
|
||||||
|
|
||||||
> a {
|
|
||||||
max-width: 100%;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* connect table */
|
|
||||||
.table {
|
|
||||||
margin-left: -1.5em; /* the delete row */
|
|
||||||
|
|
||||||
.head {
|
|
||||||
margin-left: 1.5em; /* the delete row */
|
|
||||||
.column.delete {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.column {
|
|
||||||
align-self: center;
|
|
||||||
.country, .icon-container {
|
|
||||||
align-self: center;
|
|
||||||
margin-right: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@mixin fixed-column($name, $width) {
|
|
||||||
&.#{$name} {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
width: $width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include fixed-column(delete, 1.5em);
|
|
||||||
@include fixed-column(password, 5em);
|
|
||||||
@include fixed-column(country-name, 7em);
|
|
||||||
@include fixed-column(clients, 4em);
|
|
||||||
@include fixed-column(connections, 6.5em);
|
|
||||||
|
|
||||||
&.delete {
|
|
||||||
opacity: 0;
|
|
||||||
border-right: none;
|
|
||||||
border-bottom: none;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
@include transition(opacity .25 ease-in-out);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 1;
|
|
||||||
@include transition(opacity .25 ease-in-out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.address {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
width: 40%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.name {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 55rem) {
|
|
||||||
.modal .modal-connect {
|
|
||||||
min-width: calc(21.25em + 24px * 2)!important;
|
|
||||||
width: 1000em; /* allocate space */
|
|
||||||
|
|
||||||
.container-address-password {
|
|
||||||
.container-password {
|
|
||||||
min-width: unset!important;
|
|
||||||
margin-left: 1em!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
justify-content: flex-end!important;
|
|
||||||
|
|
||||||
.button-toggle-last-servers {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-profile-name {
|
|
||||||
flex-direction: column!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-connect-input {
|
|
||||||
> .row {
|
|
||||||
> div {
|
|
||||||
margin-right: 0!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-last-servers {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
@import "properties";
|
|
||||||
|
|
||||||
.modal-server-group-assignments {
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
min-width: 25em!important;
|
|
||||||
max-height: calc(100vh - 10rem)!important;
|
|
||||||
min-height: 10em!important;
|
|
||||||
|
|
||||||
width: 30em!important;
|
|
||||||
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
justify-content: stretch!important;
|
|
||||||
|
|
||||||
background-color: #2f2f35;
|
|
||||||
padding: .5em!important;
|
|
||||||
|
|
||||||
.group-assignment-list {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-height: 6em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
color: #999999;
|
|
||||||
|
|
||||||
a {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
.htmltag-client {
|
|
||||||
display: inline;
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-list {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
min-height: 4em;
|
|
||||||
|
|
||||||
padding: 3px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
border: 1px #161616 solid;
|
|
||||||
border-radius: $border_radius_middle;
|
|
||||||
background-color: #28292b;
|
|
||||||
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
|
|
||||||
.group-entry {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
height: 1.75em;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-width: 6em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
margin-right: .25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
align-self: center;
|
|
||||||
margin-right: 4px;
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
padding-top: 1em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,508 +0,0 @@
|
||||||
@import "properties";
|
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
.modal-icon-select {
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
justify-content: stretch!important;
|
|
||||||
|
|
||||||
width: 50em!important;
|
|
||||||
|
|
||||||
/*
|
|
||||||
.right, .left {
|
|
||||||
.header {
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: #557edc;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.container-icons {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content, .container-icons-list {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-icons-list {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-icons-remote, .container-icons-local {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 300px;
|
|
||||||
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
background-color: $color_list_background;
|
|
||||||
border: 1px $color_list_border solid;
|
|
||||||
|
|
||||||
border-radius: $border_radius_large;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
flex-direction: row;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: baseline;
|
|
||||||
|
|
||||||
&.container-icons-local {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container, .icon {
|
|
||||||
margin-left: 1px;
|
|
||||||
margin-right: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.icon-select {
|
|
||||||
.icon-container, .icon {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-radius: .1em;
|
|
||||||
|
|
||||||
background-color: rgba(0, 0, 0, 0.07);
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border-radius: .1em;
|
|
||||||
|
|
||||||
background-color: rgba(0, 51, 0, 0.07);
|
|
||||||
border: 1px solid red;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &.selected {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
|
|
||||||
margin: -1px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-loading, .container-no-permissions, .container-error {
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
font-size: 1.1em;
|
|
||||||
color: hsla(0, 0%, 40%, 1);
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
background-color: rgba(0, 0, 0, 0.27);
|
|
||||||
|
|
||||||
cursor: not-allowed;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-around;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
padding-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-loading {
|
|
||||||
z-index: 40;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-error {
|
|
||||||
z-index: 30;
|
|
||||||
}
|
|
||||||
.container-no-permissions {
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.spacer {
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
width: 8em;
|
|
||||||
min-width: 4em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-select {
|
|
||||||
margin-left: 10px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
a, div {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
> div {
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
margin-left: .5rem;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-select-no-icon {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-icon-upload {
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
width: 50em;
|
|
||||||
min-width: 300px;
|
|
||||||
|
|
||||||
padding: 0!important;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.container-select {
|
|
||||||
padding: 1em;
|
|
||||||
min-height: 130px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.container-icons {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
width: min-content;
|
|
||||||
min-width: 150px;
|
|
||||||
min-height: 130px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
margin-right: 1em;
|
|
||||||
|
|
||||||
background-color: $color_list_background;
|
|
||||||
border: 1px $color_list_border solid;
|
|
||||||
|
|
||||||
border-radius: $border_radius_large;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-radius: .1em;
|
|
||||||
|
|
||||||
background-color: rgba(0, 0, 0, 0.07);
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border-radius: .1em;
|
|
||||||
|
|
||||||
background-color: rgba(0, 51, 0, 0.07);
|
|
||||||
border: 1px solid red;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &.selected {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
|
|
||||||
margin: -1px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> img {
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 2;
|
|
||||||
|
|
||||||
min-width: 50px;
|
|
||||||
max-width: 200px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.buttons-manage {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
> button:not(:first-of-type) {
|
|
||||||
margin-top: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-upload {
|
|
||||||
-webkit-box-shadow: 0px -5px 5px 0px rgba(0,0,0,0.25);
|
|
||||||
-moz-box-shadow: 0px -5px 5px 0px rgba(0,0,0,0.25);
|
|
||||||
box-shadow: 0px -5px 2px 0px rgba(0, 0, 0, 0.25);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
padding: .5em 1em 1em;
|
|
||||||
|
|
||||||
.container-error, .container-success {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 60px;
|
|
||||||
|
|
||||||
border: 2px solid;
|
|
||||||
border-radius: $border_radius_middle;
|
|
||||||
|
|
||||||
&.container-error {
|
|
||||||
border-color: rgba(128, 0, 0, 0.5);
|
|
||||||
background-color: rgba(128, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.container-success {
|
|
||||||
margin-top: .5em;
|
|
||||||
|
|
||||||
border-color: rgba(50, 143, 51, 0.25);
|
|
||||||
background-color: rgba(50, 143, 51, 0.13);
|
|
||||||
}
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
align-self: center;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
width: 6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
opacity: 0;
|
|
||||||
height: 0;
|
|
||||||
min-height: 0;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition(.25s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-process {
|
|
||||||
margin-top: .5em;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
min-height: 100px;
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
background-color: $color_list_background;
|
|
||||||
border: 1px $color_list_border solid;
|
|
||||||
|
|
||||||
border-radius: $border_radius_large;
|
|
||||||
|
|
||||||
.upload-entry {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.container-icon {
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
margin: 1px 1px 1px 4px;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
min-width: 2em;
|
|
||||||
|
|
||||||
margin: 2px 5px 2px 3px;
|
|
||||||
height: 16px;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: .75rem;
|
|
||||||
|
|
||||||
background-color: #222222;
|
|
||||||
border: 1px solid hsla(0, 0%, 10%, 1);
|
|
||||||
border-radius: .25rem;
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
&.bg-danger {
|
|
||||||
background-color: rgba(128, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.bg-success {
|
|
||||||
background-color: rgba(50, 143, 51, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition(width 1s ease-in-out, background-color $button_hover_animation_time ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-message {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 1em;
|
|
||||||
line-height: normal;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="file"] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 650px) {
|
|
||||||
.modal-icon-upload {
|
|
||||||
.container-select {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.container-icons {
|
|
||||||
width: 100%;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
max-width: unset;
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
> button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons-manage {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
> button {
|
|
||||||
width: 50%;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-upload {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +1,85 @@
|
||||||
@import "mixin";
|
@import "mixin";
|
||||||
|
|
||||||
.modal-body.modal-identity-improve {
|
:global {
|
||||||
padding: 0!important;
|
.modal-body.modal-identity-improve {
|
||||||
|
padding: 0!important;
|
||||||
|
|
||||||
display: flex!important;
|
display: flex!important;
|
||||||
flex-direction: column!important;
|
flex-direction: column!important;
|
||||||
justify-content: flex-start!important;
|
justify-content: flex-start!important;
|
||||||
|
|
||||||
.container-tooltip {
|
.container-tooltip {
|
||||||
flex-grow: 0!important;
|
flex-grow: 0!important;
|
||||||
flex-shrink: 0!important;
|
flex-shrink: 0!important;
|
||||||
min-width: unset!important;
|
min-width: unset!important;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: .8em;
|
width: .8em;
|
||||||
margin-right: .5em;
|
margin-right: .5em;
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-bottom: .1em;
|
margin-bottom: .1em;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 1em;
|
height: 1em;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.options, .status {
|
||||||
display: none;
|
flex-grow: 0;
|
||||||
}
|
flex-shrink: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.options, .status {
|
padding: 1em;
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
padding: 1em;
|
.title {
|
||||||
|
color: #387fb5;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.row {
|
||||||
color: #387fb5;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
div {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-width: 4em;
|
||||||
|
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.status {
|
||||||
|
border-top: 3px solid #20262d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
margin: 0 1em 1em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: flex-end;
|
||||||
|
|
||||||
div {
|
button {
|
||||||
flex-grow: 1;
|
min-width: 8em;
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 4em;
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
&:not(:first-of-type) {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
|
@ -63,126 +88,103 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status {
|
.modal-body.modal-identity-import {
|
||||||
border-top: 3px solid #20262d;
|
padding: 0!important;
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
margin: 0 1em 1em;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-start;
|
||||||
|
|
||||||
button {
|
@include user-select(none);
|
||||||
min-width: 8em;
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
.container-status {
|
||||||
margin-left: 1em;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
margin: 1em 1em -1em;
|
||||||
|
height: 1.6em;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
color: #389738;
|
||||||
|
&.error {
|
||||||
|
color: #973838;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
color: #96903a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include transition(.2s ease-in-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-text, .container-file {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
width: 10em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
padding-left: .25em;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
margin-right: 1em;
|
||||||
|
|
||||||
|
.radio-button {
|
||||||
|
align-self: center;
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1.75em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
min-width: 8em;
|
||||||
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body.modal-identity-import {
|
.footer {
|
||||||
padding: 0!important;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
.container-status {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
margin: 1em 1em -1em;
|
|
||||||
height: 1.6em;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
color: #389738;
|
|
||||||
&.error {
|
|
||||||
color: #973838;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.loading {
|
|
||||||
color: #96903a;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition(.2s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-text, .container-file {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
> label {
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
||||||
width: 10em;
|
padding: 1em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: flex-end;
|
||||||
|
|
||||||
padding-left: .25em;
|
button {
|
||||||
align-self: center;
|
min-width: 8em;
|
||||||
|
|
||||||
margin-right: 1em;
|
|
||||||
|
|
||||||
.radio-button {
|
|
||||||
align-self: center;
|
|
||||||
margin-right: .5em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> * {
|
.file-selector {
|
||||||
align-self: center;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
|
||||||
margin-bottom: 1.75em;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
min-width: 8em;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
padding: 1em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
button {
|
|
||||||
min-width: 8em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-selector {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,73 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
@import "properties";
|
|
||||||
|
|
||||||
.modal-invite {
|
|
||||||
padding: .5em!important;
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
.general-properties {
|
|
||||||
flex: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.form-group {
|
|
||||||
flex: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-settings {
|
|
||||||
flex: 0;
|
|
||||||
|
|
||||||
margin-bottom: .5em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-output {
|
|
||||||
background-color: $color_list_background;
|
|
||||||
border: 1px $color_list_border solid;
|
|
||||||
|
|
||||||
border-radius: $border_radius_large;
|
|
||||||
|
|
||||||
padding: .5em;
|
|
||||||
min-height: 5em;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
resize: none;
|
|
||||||
|
|
||||||
color: #999999;
|
|
||||||
|
|
||||||
@include user-select(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +1,52 @@
|
||||||
.modal-body.modal-keyselect {
|
:global {
|
||||||
width: max-content!important;
|
.modal-body.modal-keyselect {
|
||||||
|
width: max-content!important;
|
||||||
.body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
.container-select {
|
|
||||||
margin-top: .5em;
|
|
||||||
|
|
||||||
|
.body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
a {
|
.container-select {
|
||||||
align-self: center;
|
margin-top: .5em;
|
||||||
margin-right: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-key {
|
|
||||||
background-color: #272626;
|
|
||||||
border-radius: 0.15em;
|
|
||||||
-webkit-box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5);
|
|
||||||
-moz-box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5);
|
|
||||||
box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5);
|
|
||||||
|
|
||||||
min-width: 12em;
|
|
||||||
height: 2em;
|
|
||||||
padding: 0 .5em;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
a {
|
||||||
|
align-self: center;
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-key {
|
||||||
|
background-color: #272626;
|
||||||
|
border-radius: 0.15em;
|
||||||
|
-webkit-box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5);
|
||||||
|
-moz-box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5);
|
||||||
|
box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
|
min-width: 12em;
|
||||||
|
height: 2em;
|
||||||
|
padding: 0 .5em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
margin-top: 1em;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
margin-top: 1em;
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,84 +1,86 @@
|
||||||
@import "mixin";
|
@import "mixin";
|
||||||
@import "properties";
|
@import "properties";
|
||||||
|
|
||||||
.modal-body.modal-latency {
|
:global {
|
||||||
@include user-select(none);
|
.modal-body.modal-latency {
|
||||||
@include transform(all $button_hover_animation_time ease-in-out);
|
@include user-select(none);
|
||||||
|
@include transform(all $button_hover_animation_time ease-in-out);
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.htmltag-client {
|
|
||||||
color: #999!important;
|
|
||||||
margin-left: .25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
.htmltag-client {
|
||||||
margin-left: .25em;
|
color: #999!important;
|
||||||
}
|
margin-left: .25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-min, .container-max {
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
}
|
||||||
height: 2em;
|
|
||||||
|
|
||||||
.container-value {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
margin-right: 1em;
|
|
||||||
width: 9em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
|
margin-left: .25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-min, .container-max {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
height: 2em;
|
||||||
|
|
||||||
|
.container-value {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
margin-right: 1em;
|
||||||
|
width: 9em;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-max {
|
||||||
|
padding-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-slider {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
margin-top: 2em;
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:last-of-type) {
|
||||||
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-max {
|
|
||||||
padding-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-slider {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
margin-top: 2em;
|
|
||||||
|
|
||||||
.spacer {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:not(:last-of-type) {
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -6,154 +6,156 @@ html:root {
|
||||||
--modal-newcomer-divider: #313135;
|
--modal-newcomer-divider: #313135;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body.modal-newcomer {
|
:global {
|
||||||
display: flex!important;
|
.modal-body.modal-newcomer {
|
||||||
flex-direction: column!important;
|
display: flex!important;
|
||||||
justify-content: stretch!important;
|
flex-direction: column!important;
|
||||||
|
justify-content: stretch!important;
|
||||||
|
|
||||||
padding: 0!important;
|
padding: 0!important;
|
||||||
|
|
||||||
min-width: 20em;
|
min-width: 20em;
|
||||||
width: 60em;
|
width: 60em;
|
||||||
|
|
||||||
@include user-select(none);
|
@include user-select(none);
|
||||||
|
|
||||||
.container-header {
|
.container-header {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
||||||
color: var(--modal-newcommer-header-color);
|
color: var(--modal-newcommer-header-color);
|
||||||
padding: .5em .5em .25em;
|
padding: .5em .5em .25em;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
||||||
.step {
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: ' ';
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
height: 1.25px;
|
|
||||||
//background: linear-gradient(90deg, rgba(49,49,53,1) 80%, rgba(49,49,53,0) 100%);
|
|
||||||
background: var(--modal-newcomer-divider);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
&::after {
|
|
||||||
content: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-body {
|
|
||||||
//flex-grow: 1;
|
|
||||||
//flex-shrink: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-height: 18em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
@include chat-scrollbar-horizontal();
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
|
|
||||||
background-color: #19191b;
|
|
||||||
|
|
||||||
.body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
padding: .5em .5em .5em;
|
|
||||||
|
|
||||||
&.height-transition {
|
|
||||||
@include transition(max-height .25s ease-in-out, min-height .25s ease-in-out);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step {
|
.step {
|
||||||
&.step-welcome, &.step-finish {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.text {
|
|
||||||
align-self: center;
|
|
||||||
h1 {
|
|
||||||
line-height: 1.1em;
|
|
||||||
|
|
||||||
margin-bottom: .8em;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.step-welcome h1 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
max-height: 15em;
|
|
||||||
max-width: 15em;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
margin-right: 1em;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for step-identity or step-microphone */
|
|
||||||
.container-settings-identity-profile {
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
.left .body {
|
|
||||||
background-color: #202122;
|
|
||||||
.overlay {
|
|
||||||
background-color: #202122;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile.selected {
|
|
||||||
background-color: #141415;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.step-identity { }
|
|
||||||
|
|
||||||
&.hidden {
|
&.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: ' ';
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
height: 1.25px;
|
||||||
|
//background: linear-gradient(90deg, rgba(49,49,53,1) 80%, rgba(49,49,53,0) 100%);
|
||||||
|
background: var(--modal-newcomer-divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
&::after {
|
||||||
|
content: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
.container-body {
|
||||||
flex-shrink: 0;
|
//flex-grow: 1;
|
||||||
flex-grow: 0;
|
//flex-shrink: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-height: 18em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: center;
|
||||||
|
|
||||||
border-top: 1.25px solid var(--modal-newcomer-divider);
|
overflow: auto;
|
||||||
padding: .5em;
|
@include chat-scrollbar-horizontal();
|
||||||
|
@include chat-scrollbar-vertical();
|
||||||
|
|
||||||
|
background-color: #19191b;
|
||||||
|
|
||||||
|
.body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
padding: .5em .5em .5em;
|
||||||
|
|
||||||
|
&.height-transition {
|
||||||
|
@include transition(max-height .25s ease-in-out, min-height .25s ease-in-out);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step {
|
||||||
|
&.step-welcome, &.step-finish {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
align-self: center;
|
||||||
|
h1 {
|
||||||
|
line-height: 1.1em;
|
||||||
|
|
||||||
|
margin-bottom: .8em;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.step-welcome h1 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
max-height: 15em;
|
||||||
|
max-width: 15em;
|
||||||
|
|
||||||
|
align-self: center;
|
||||||
|
margin-right: 1em;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for step-identity or step-microphone */
|
||||||
|
.container-settings-identity-profile {
|
||||||
|
padding: .5em;
|
||||||
|
|
||||||
|
.left .body {
|
||||||
|
background-color: #202122;
|
||||||
|
.overlay {
|
||||||
|
background-color: #202122;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile.selected {
|
||||||
|
background-color: #141415;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.step-identity { }
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
border-top: 1.25px solid var(--modal-newcomer-divider);
|
||||||
|
padding: .5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,88 +0,0 @@
|
||||||
html:root {
|
|
||||||
--modal-poke-date: cornflowerblue;
|
|
||||||
--modal-poke-text: #004d00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-poke {
|
|
||||||
display: flex!important;;
|
|
||||||
flex-direction: column!important;;
|
|
||||||
|
|
||||||
.container-servers {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.server {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.server-name {
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
font-weight: bold;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poke-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: auto;
|
|
||||||
|
|
||||||
.entry {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date, .user, .text {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date {
|
|
||||||
color: var(--modal-poke-date);
|
|
||||||
}
|
|
||||||
.text {
|
|
||||||
color: var(--modal-poke-text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
margin-top: 5px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
.spacer {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-close {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
margin-top: 5px;
|
|
||||||
width: 150px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,375 +1,377 @@
|
||||||
@import "properties";
|
@import "properties";
|
||||||
@import "mixin";
|
@import "mixin";
|
||||||
|
|
||||||
.query-create {
|
:global {
|
||||||
display: flex!important;
|
.query-create {
|
||||||
flex-direction: column!important;
|
display: flex!important;
|
||||||
|
flex-direction: column!important;
|
||||||
|
|
||||||
.row-name {
|
.row-name {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
input {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
margin-top: 5px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.query-created {
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-row {
|
|
||||||
margin-right: 0!important;
|
|
||||||
margin-left: 0!important;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.icon_x32 {
|
|
||||||
align-self: center;
|
|
||||||
margin-right: 5px;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html:root {
|
|
||||||
--modal-query-title: #e0e0e0;
|
|
||||||
|
|
||||||
--modal-query-list: #28292b;
|
|
||||||
--modal-query-list-border: #1f2122;
|
|
||||||
|
|
||||||
--modal-query-empty: #4d4d4d;
|
|
||||||
--modal-query-error: #732626;
|
|
||||||
|
|
||||||
--modal-query-entry-hover: #2c2d2f;
|
|
||||||
--modal-query-entry-selected: #1a1a1b;
|
|
||||||
|
|
||||||
--modal-query-key: #557edc;
|
|
||||||
--modal-query-copy-hover: #28292b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body.modal-query-manage {
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: row!important;
|
|
||||||
justify-content: stretch!important;
|
|
||||||
|
|
||||||
padding: 1em!important;
|
|
||||||
|
|
||||||
min-width: 25em!important; /* 23em to be exact */
|
|
||||||
min-height: 20em!important;
|
|
||||||
|
|
||||||
width: 60em; /* recommend width */
|
|
||||||
height: 50em;
|
|
||||||
|
|
||||||
@include user-select(none);
|
|
||||||
|
|
||||||
.container {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 20em;
|
|
||||||
min-height: 10em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left, .right {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
> .title {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-bottom: .5em;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
a {
|
input {
|
||||||
font-weight: bold;
|
|
||||||
color: var(--modal-query-title);
|
|
||||||
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
font-size: 1.05em;
|
.buttons {
|
||||||
min-width: 5em;
|
margin-top: 5px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
align-self: flex-end;
|
.query-created {
|
||||||
line-height: normal;
|
display: flex!important;
|
||||||
|
flex-direction: column!important;
|
||||||
|
|
||||||
white-space: nowrap;
|
.buttons {
|
||||||
overflow: hidden;
|
text-align: right;
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
margin-right: 0!important;
|
||||||
|
margin-left: 0!important;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.icon_x32 {
|
||||||
|
align-self: center;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
.form-group {
|
||||||
flex-grow: 0;
|
flex-grow: 1;
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
height: 2em;
|
|
||||||
font-size: .9em;
|
|
||||||
|
|
||||||
width: 10em;
|
|
||||||
min-width: 5em;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
html:root {
|
||||||
margin-right: .4em;
|
--modal-query-title: #e0e0e0;
|
||||||
min-width: 10em;
|
|
||||||
|
|
||||||
.container-list {
|
--modal-query-list: #28292b;
|
||||||
|
--modal-query-list-border: #1f2122;
|
||||||
|
|
||||||
|
--modal-query-empty: #4d4d4d;
|
||||||
|
--modal-query-error: #732626;
|
||||||
|
|
||||||
|
--modal-query-entry-hover: #2c2d2f;
|
||||||
|
--modal-query-entry-selected: #1a1a1b;
|
||||||
|
|
||||||
|
--modal-query-key: #557edc;
|
||||||
|
--modal-query-copy-hover: #28292b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body.modal-query-manage {
|
||||||
|
display: flex!important;
|
||||||
|
flex-direction: row!important;
|
||||||
|
justify-content: stretch!important;
|
||||||
|
|
||||||
|
padding: 1em!important;
|
||||||
|
|
||||||
|
min-width: 25em!important; /* 23em to be exact */
|
||||||
|
min-height: 20em!important;
|
||||||
|
|
||||||
|
width: 60em; /* recommend width */
|
||||||
|
height: 50em;
|
||||||
|
|
||||||
|
@include user-select(none);
|
||||||
|
|
||||||
|
.container {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
min-width: 20em;
|
||||||
|
min-height: 10em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left, .right {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
border-radius: 0.2em;
|
> .title {
|
||||||
border: 1px solid var(--modal-query-list-border);
|
|
||||||
background-color: var(--modal-query-list);
|
|
||||||
|
|
||||||
.container-entries {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-height: 5em;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
|
|
||||||
.container-empty, .container-error {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
font-size: 2em;
|
|
||||||
|
|
||||||
background-color: var(--modal-query-list);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-empty {
|
|
||||||
color: var(--modal-query-empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-error {
|
|
||||||
color: var(--modal-query-error);
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 4em;
|
|
||||||
|
|
||||||
padding-left: .5em;
|
|
||||||
padding-right: .5em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--modal-query-entry-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: var(--modal-query-entry-selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-search {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
padding: 0 .5em;
|
margin-bottom: .5em;
|
||||||
|
|
||||||
border-top: 1px solid var(--modal-query-list-border);
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--modal-query-title);
|
||||||
|
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
font-size: 1.05em;
|
||||||
|
min-width: 5em;
|
||||||
|
|
||||||
|
align-self: flex-end;
|
||||||
|
line-height: normal;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
|
||||||
height: 2em;
|
height: 2em;
|
||||||
min-width: 2em;
|
font-size: .9em;
|
||||||
|
|
||||||
|
width: 10em;
|
||||||
|
min-width: 5em;
|
||||||
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
margin-top: .8em;
|
|
||||||
|
|
||||||
margin-right: .5em;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 5em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
.left {
|
||||||
min-width: 10em;
|
margin-right: .4em;
|
||||||
margin-left: .4em;
|
min-width: 10em;
|
||||||
|
|
||||||
.container-details {
|
.container-list {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.detail {
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: stretch;
|
||||||
|
|
||||||
margin-bottom: 1em;
|
border-radius: 0.2em;
|
||||||
|
border: 1px solid var(--modal-query-list-border);
|
||||||
|
background-color: var(--modal-query-list);
|
||||||
|
|
||||||
.title, .title a {
|
.container-entries {
|
||||||
text-transform: uppercase;
|
flex-shrink: 1;
|
||||||
color: var(--modal-query-key);
|
flex-grow: 1;
|
||||||
|
|
||||||
white-space: nowrap;
|
min-height: 5em;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
position: relative;
|
||||||
@include user-select(text);
|
|
||||||
|
|
||||||
white-space: nowrap;
|
overflow-x: hidden;
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
text-overflow: ellipsis;
|
@include chat-scrollbar-vertical();
|
||||||
}
|
|
||||||
|
|
||||||
&.unique-id {
|
.container-empty, .container-error {
|
||||||
.title {
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2em;
|
||||||
|
|
||||||
|
background-color: var(--modal-query-list);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-empty {
|
||||||
|
color: var(--modal-query-empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-error {
|
||||||
|
color: var(--modal-query-error);
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
.button {
|
flex-shrink: 1;
|
||||||
display: flex;
|
min-width: 4em;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
width: 1.2em;
|
padding-left: .5em;
|
||||||
height: 1.2em;
|
padding-right: .5em;
|
||||||
|
|
||||||
align-self: center;
|
white-space: nowrap;
|
||||||
margin-left: .25em;
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: .2em;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--modal-query-copy-hover);
|
background-color: var(--modal-query-entry-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
margin-bottom: .2em; /* "text sub" */
|
&.selected {
|
||||||
|
background-color: var(--modal-query-entry-selected);
|
||||||
> div {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include transition($button_hover_animation_time ease-in-out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.spacer { flex-grow: 1; flex-shrink: 1; min-height: 0; }
|
.container-search {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
.buttons {
|
padding: 0 .5em;
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
button {
|
border-top: 1px solid var(--modal-query-list-border);
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 5em;
|
|
||||||
|
|
||||||
height: 2em;
|
display: flex;
|
||||||
font-size: .9em;
|
flex-direction: row;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
width: 14em;
|
button {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
white-space: nowrap;
|
height: 2em;
|
||||||
overflow: hidden;
|
min-width: 2em;
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
align-self: center;
|
||||||
margin-left: 1em;
|
margin-top: .8em;
|
||||||
|
|
||||||
|
margin-right: .5em;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
min-width: 5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.container-seperator {
|
.right {
|
||||||
background: transparent;
|
min-width: 10em;
|
||||||
|
margin-left: .4em;
|
||||||
|
|
||||||
|
.container-details {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
.title, .title a {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--modal-query-key);
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
@include user-select(text);
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unique-id {
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 1.2em;
|
||||||
|
height: 1.2em;
|
||||||
|
|
||||||
|
align-self: center;
|
||||||
|
margin-left: .25em;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: .2em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--modal-query-copy-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
margin-bottom: .2em; /* "text sub" */
|
||||||
|
|
||||||
|
> div {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include transition($button_hover_animation_time ease-in-out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer { flex-grow: 1; flex-shrink: 1; min-height: 0; }
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-width: 5em;
|
||||||
|
|
||||||
|
height: 2em;
|
||||||
|
font-size: .9em;
|
||||||
|
|
||||||
|
width: 14em;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-seperator {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,263 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
html:root {
|
|
||||||
--serverinfo-background: #2f2f35;
|
|
||||||
--serverinfo-hostbanner-background: #26222a;
|
|
||||||
|
|
||||||
--serverinfo-group-border: #1f2122;
|
|
||||||
--serverinfo-group-background: #28292b;
|
|
||||||
|
|
||||||
--serverinfo-key: #557edc;
|
|
||||||
--serverinfo-value: #d6d6d7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body.modal-server-info {
|
|
||||||
padding: 0!important;
|
|
||||||
width: 55em;
|
|
||||||
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
justify-content: flex-start!important;
|
|
||||||
|
|
||||||
background-color: var(--serverinfo-background);
|
|
||||||
|
|
||||||
.container-tooltip {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
width: 1.6em;
|
|
||||||
margin-left: .5em;
|
|
||||||
margin-right: .5em;
|
|
||||||
font-size: .9em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-top {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
max-height: 9em;
|
|
||||||
//width: 30em; /* set a default width where we have to grow/shrink */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.container-hostbanner {
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: var(--serverinfo-hostbanner-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-body {
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-height: 12em; /* 10em + 2 * 1em margin */
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
@include chat-scrollbar-vertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
.group {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
margin: 1em;
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
border-radius: .2em;
|
|
||||||
border: 1px solid var(--serverinfo-group-border);
|
|
||||||
|
|
||||||
background-color: var(--serverinfo-group-background);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
height: 10em;
|
|
||||||
max-height: 10em;
|
|
||||||
|
|
||||||
.container-image {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
max-width: 15em;
|
|
||||||
max-height: 9em; /* minus one padding */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
margin-right: 2em;
|
|
||||||
@include transition(.25s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-properties {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-width: 20em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
height: inherit;
|
|
||||||
|
|
||||||
.row {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
height: 1.8em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
.key {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
color: var(--serverinfo-key);
|
|
||||||
text-transform: uppercase;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
width: 15em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
color: var(--serverinfo-value);
|
|
||||||
align-self: center;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
.country {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: .25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.server-version {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
a {
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-network {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.container-button {
|
|
||||||
margin-right: 1em;
|
|
||||||
|
|
||||||
flex-shrink: 1e8;
|
|
||||||
min-width: 5em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: 2.5em;
|
|
||||||
width: 12em;
|
|
||||||
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
min-width: 10em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.reverse {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
text-align: right;
|
|
||||||
|
|
||||||
.container-image {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-properties {
|
|
||||||
.row {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-buttons {
|
|
||||||
margin: 1em;
|
|
||||||
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
button {
|
|
||||||
min-width: 8em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 50em) {
|
|
||||||
.modal-body.modal-server-info {
|
|
||||||
.container-image {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 0!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,218 +0,0 @@
|
||||||
@import "mixin";
|
|
||||||
|
|
||||||
html:root {
|
|
||||||
--serverinfo-bandwidth-upload: #0a5eaa;
|
|
||||||
--serverinfo-bandwidth-download: #9f2712;
|
|
||||||
|
|
||||||
--serverinfo-title: #e3e3e4;
|
|
||||||
--serverinfo-statistics-title: #244c78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body.modal-server-info-bandwidth {
|
|
||||||
padding: 0!important;
|
|
||||||
width: 55em;
|
|
||||||
|
|
||||||
display: flex!important;
|
|
||||||
flex-direction: column!important;
|
|
||||||
justify-content: flex-start!important;
|
|
||||||
|
|
||||||
background-color: #2f2f35;
|
|
||||||
|
|
||||||
.container-tooltip {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
width: 1.6em;
|
|
||||||
margin-left: .5em;
|
|
||||||
font-size: .9em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
|
|
||||||
align-self: center;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.top {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
margin: 1em;
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
height: 12em;
|
|
||||||
max-height: 12em;
|
|
||||||
|
|
||||||
.container-image {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
max-width: 18em;
|
|
||||||
max-height: 11em; /* minus one padding */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
margin-right: 2em;
|
|
||||||
@include transition(.25s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-stats {
|
|
||||||
flex-shrink: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
min-width: 25em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
|
|
||||||
.statistic {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
font-size: 1.25em;
|
|
||||||
color: var(--serverinfo-title);
|
|
||||||
line-height: normal;
|
|
||||||
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.values {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
font-size: 1.2em;
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload {
|
|
||||||
color: var(--serverinfo-bandwidth-upload);
|
|
||||||
}
|
|
||||||
|
|
||||||
.download {
|
|
||||||
color: var(--serverinfo-bandwidth-download);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
margin: 1em;
|
|
||||||
padding: .5em;
|
|
||||||
|
|
||||||
border-radius: .2em;
|
|
||||||
border: 1px solid #1f2122;
|
|
||||||
|
|
||||||
background-color: #28292b;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
//height: 15em;
|
|
||||||
//max-height: 10em;
|
|
||||||
|
|
||||||
.statistic {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
color: var(--serverinfo-statistics-title);
|
|
||||||
font-size: 1.25em;
|
|
||||||
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: stretch;
|
|
||||||
|
|
||||||
height: 7em;
|
|
||||||
|
|
||||||
.container-canvas {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
min-width: 6em;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.values {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
width: 8em;
|
|
||||||
text-align: right;
|
|
||||||
|
|
||||||
.upload {
|
|
||||||
color: var(--serverinfo-bandwidth-upload);
|
|
||||||
}
|
|
||||||
|
|
||||||
.download {
|
|
||||||
color: var(--serverinfo-bandwidth-download);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: 1.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 50em) {
|
|
||||||
.modal-body.modal-server-info {
|
|
||||||
.container-image {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 0!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|