From 525cb6116e0a8d52af32625446ddbfc703dd0a72 Mon Sep 17 00:00:00 2001 From: Khyretos Date: Thu, 28 Dec 2023 16:25:52 +0100 Subject: [PATCH] various updates. --- .editorconfig | 9 + .eslintignore | 5 + .eslintrc.js | 16 + .prettierrc.yaml | 5 + package.json | 9 +- src/backend/loquendoBot_backend.py | 47 +- src/css/chat.css | 580 +++++------ src/css/checkbox.css | 86 +- src/css/home.css | 292 +++--- src/css/logger.css | 28 +- src/css/menu.css | 262 ++--- src/css/sliders.css | 208 ++-- src/css/tabs.css | 506 +++++----- src/css/tts-menu.css | 190 ++-- src/css/volume-slider.css | 108 +- src/index.html | 1314 +++++++++++++------------ src/js/amazon.js | 188 ++-- src/js/auth.js | 294 ++++-- src/js/backend.js | 265 ++--- src/js/chat.js | 190 ++-- src/js/customEmojis.js | 9 + src/js/google.js | 44 +- src/js/languages.js | 647 ++++++------ src/js/logger.js | 102 +- src/js/mediaDevices.js | 76 +- src/js/messageTemplates.js | 30 +- src/js/renderer.js | 290 +++--- src/js/responses.js | 33 +- src/js/server.js | 89 +- src/js/settings.js | 782 ++++++++------- src/js/sound.js | 193 ++-- src/js/theme.js | 156 ++- src/js/twitch.js | 240 +++-- src/main.js | 306 +++--- src/modules/chat/index.html | 42 +- src/modules/chat/main.css | 202 ++-- src/modules/chat/main.js | 168 ++-- src/modules/vtuber/css/about.css | 16 +- src/modules/vtuber/css/main.css | 396 ++++---- src/modules/vtuber/html/about.html | 2 +- src/modules/vtuber/index.html | 142 +-- src/modules/vtuber/js/main.js | 379 ++++--- src/modules/vtuber/js/motion.js | 64 +- src/modules/vtuber/js/movable_view.js | 101 +- src/modules/vtuber/js/perlin_noise.js | 1188 +++++----------------- 45 files changed, 5022 insertions(+), 5277 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .prettierrc.yaml create mode 100644 src/js/customEmojis.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3dce414 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..241edf9 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules +docs +dist +out +build diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..4a51dd8 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + root: true, + env: { + es6: true, + node: true + }, + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021 + }, + extends: ['eslint:recommended', '@electron-internal', '@electron-toolkit'], + rules: { + 'space-before-function-paren': 'off', + vendorPrefix: 'off' + } +}; diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..80c0f12 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,5 @@ +singleQuote: true +semi: true +printWidth: 140 +trailingComma: none +arrowParens: avoid diff --git a/package.json b/package.json index eb8957b..7e63f61 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "axios": "^1.4.0", "electron-squirrel-startup": "^1.0.0", + "emoji-picker-element": "^1.21.0", "express": "^4.18.2", "ini": "^2.0.0", "kill-process-by-name": "^1.0.5", @@ -38,6 +39,12 @@ "@electron-forge/maker-squirrel": "^6.2.1", "@electron-forge/maker-zip": "^6.2.1", "@electron-forge/plugin-auto-unpack-natives": "^6.2.1", - "electron": "^25.9.8" + "@electron-internal/eslint-config": "^1.0.1", + "@electron-toolkit/eslint-config": "^1.0.2", + "electron": "^25.9.8", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.2", + "prettier": "^3.1.1" } } diff --git a/src/backend/loquendoBot_backend.py b/src/backend/loquendoBot_backend.py index f539204..43e472d 100644 --- a/src/backend/loquendoBot_backend.py +++ b/src/backend/loquendoBot_backend.py @@ -1,7 +1,15 @@ +# from wsgiref.simple_server import WSGIServer from flask import Flask, Response, jsonify, request import gevent + +import re import gevent.monkey import json +from waitress import serve +import logging + +logger = logging.getLogger("waitress") +logger.setLevel(logging.INFO) gevent.monkey.patch_all() import gevent.queue @@ -40,6 +48,7 @@ q = queue.Queue() # gobal functions + # classes class LanguageDetection: def __init__(self): @@ -55,10 +64,8 @@ class LanguageDetection: language_detection_model = os.path.join( resources_folder, "language_detection_model", f"lid.176.bin" ) - - language_detection_model = ( - rf"{language_detection_model}" - ) + + language_detection_model = rf"{language_detection_model}" self.model = fasttext.load_model(language_detection_model) def predict_lang(self, text): @@ -69,6 +76,7 @@ class LanguageDetection: return language_codes + class STT: samplerate = None args = "" @@ -92,9 +100,7 @@ class STT: resources_folder, "speech_to_text_models", settings["STT"]["LANGUAGE"] ) - self.model = Model( - rf"{vosk_model}" - ) + self.model = Model(rf"{vosk_model}") self.dump_fn = None self.q = gevent.queue.Queue() @@ -180,6 +186,7 @@ text_to_speech_service = TTS() # endpoints + @app.route("/stream", methods=["GET"]) def stream_recognition(): def generate(): @@ -239,9 +246,14 @@ def trigger_backend_event(): try: request_data = request.json message = request_data.get("message", "") + filteredMessage = re.sub( + r"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)", + "a link", + message, + ) voice = request_data.get("voice") count = request_data.get("count") - text_to_speech_service.say(message, voice, count) + text_to_speech_service.say(filteredMessage, voice, count) except Exception as e: return jsonify({"error": "An error occurred"}), 500 return jsonify({"message": "Audio triggered"}), 200 @@ -257,14 +269,14 @@ def get_voices(): if __name__ == "__main__": - LANGUAGE = LanguageDetection() - lang = LANGUAGE.predict_lang("hola cómo estás") - print(lang) - text = "Keep it up. You are awesome" - translated = MyMemoryTranslator( - source="english", target="spanish latin america" - ).translate(text) - print(translated) + # LANGUAGE = LanguageDetection() + # lang = LANGUAGE.predict_lang("hola cómo estás") + # print(lang) + # text = "Keep it up. You are awesome" + # translated = MyMemoryTranslator( + # source="english", target="spanish latin america" + # ).translate(text) + # print(translated) if len(sys.argv) > 1: settings.read(settingsPath) port = int(settings["GENERAL"]["PORT"]) @@ -273,5 +285,4 @@ if __name__ == "__main__": port = 9000 stream_recognition() - app.run(host="127.0.0.1", port=port) - app.terminate() + serve(app, host="0.0.0.0", port=port) diff --git a/src/css/chat.css b/src/css/chat.css index bcc1767..53042b2 100644 --- a/src/css/chat.css +++ b/src/css/chat.css @@ -1,462 +1,469 @@ @font-face { - font-family: 'FRAMDCN'; + font-family: 'FRAMDCN'; + src: url(../fonts/FRAMCDN/FRAMDCN.woff); } h1 { - font-family: 'FRAMDCN'; + font-family: 'FRAMDCN'; } .message-window { - height: calc(100% - 60px); - overflow: hidden; - overflow-y: auto; - display: flex; - align-items: center; - flex-direction: column; - background-color: var(--mid-section); - padding-left: 50px; - padding-right: 50px; - font-family: 'FRAMDCN'; - position: relative; - z-index: 1; + height: calc(100% - 60px); + overflow: hidden; + overflow-y: auto; + display: flex; + align-items: center; + flex-direction: column; + background-color: var(--mid-section); + padding-left: 50px; + padding-right: 50px; + font-family: 'FRAMDCN'; + position: relative; + z-index: 1; } .input-box { - display: flex; - border: none; - width: 100%; - height: 30px; - font-size: 16px; + display: flex; + border: none; + width: 100%; + height: 30px; + font-size: 16px; } .userText { - color: var(--chat-bubble-message); - font-family: Helvetica; - font-size: 16px; - text-align: right; - clear: both; + color: var(--chat-bubble-message); + font-family: Helvetica; + font-size: 16px; + text-align: right; + clear: both; } .userText span { - line-height: 1.5em; - display: inline-block; - background: #5ca6fa; - padding: 10px; - border-radius: 8px; - border-bottom-right-radius: 2px; - max-width: 80%; - margin-right: 10px; - animation: floatup 0.5s forwards; + line-height: 1.5em; + display: inline-block; + background: #5ca6fa; + padding: 10px; + border-radius: 8px; + border-bottom-right-radius: 2px; + max-width: 80%; + margin-right: 10px; + animation: floatup 0.5s forwards; } .botText { - color: #000; - font-family: Helvetica; - font-weight: normal; - font-size: 16px; - text-align: left; + color: #000; + font-family: Helvetica; + font-weight: normal; + font-size: 16px; + text-align: left; } .botText span { - line-height: 1.5em; - display: inline-block; - background: #e0e0e0; - padding: 10px; - border-radius: 8px; - border-bottom-left-radius: 2px; - max-width: 80%; - margin-left: 10px; - animation: floatup 0.5s forwards; + line-height: 1.5em; + display: inline-block; + background: #e0e0e0; + padding: 10px; + border-radius: 8px; + border-bottom-left-radius: 2px; + max-width: 80%; + margin-left: 10px; + animation: floatup 0.5s forwards; } @keyframes floatup { - from { - transform: translateY(14px); - opacity: 0; - } + from { + transform: translateY(14px); + opacity: 0; + } - to { - transform: translateY(0px); - opacity: 1; - } + to { + transform: translateY(0px); + opacity: 1; + } } @media screen and (max-width: 600px) { - .full-chat-block { - width: 100%; - border-radius: 0px; - } + .full-chat-block { + width: 100%; + border-radius: 0px; + } - .chat-bar-collapsible { - position: fixed; - bottom: 0; - right: 0; - width: 100%; - } + .chat-bar-collapsible { + position: fixed; + bottom: 0; + right: 0; + width: 100%; + } - .collapsible { - width: 100%; - border: 0px; - border-radius: 0px; - } + .collapsible { + width: 100%; + border: 0px; + border-radius: 0px; + } } ::-webkit-scrollbar { - width: 4px; + width: 4px; } ::-webkit-scrollbar-thumb { - background-color: #4c4c6a; - border-radius: 2px; + background-color: #4c4c6a; + border-radius: 2px; } .chatBox { - width: 300px; - height: 400px; - max-height: 400px; - display: flex; - flex-direction: column; - overflow: hidden; - box-shadow: 0 0 4px var(--main-color4); + width: 300px; + height: 400px; + max-height: 400px; + display: flex; + flex-direction: column; + overflow: hidden; + box-shadow: 0 0 4px var(--main-color4); } .chat-window { - flex: auto; - max-height: calc(100% - 60px); - background: #2f323b; - overflow: auto; + flex: auto; + max-height: calc(100% - 60px); + background: #2f323b; + overflow: auto; } .chat-input { - height: 30px; - display: flex; - flex: 0 0 auto; - height: 60px; - background: var(--main-color3); + height: 30px; + display: flex; + flex: 0 0 auto; + height: 60px; + background: var(--main-color3); } .chat-input input { - height: 59px; - line-height: 60px; - outline: 0 none; - border: none; - width: calc(100% - 60px); - color: var(--chat-bubble-message); - text-indent: 10px; - font-size: 12pt; - padding: 0; - background: var(--main-color3); + height: 59px; + line-height: 60px; + outline: 0 none; + border: none; + width: calc(100% - 60px); + color: var(--chat-bubble-message); + text-indent: 10px; + font-size: 12pt; + padding: 0; + background: var(--main-color3); } .chat-input button { - float: right; - outline: 0 none; - border: none; - background: var(--main-color3); - height: 40px; - width: 40px; - border-radius: 50%; - padding: 2px 0 0 0; - margin: 10px; + float: right; + outline: 0 none; + border: none; + background: var(--main-color3); + height: 40px; + width: 40px; + border-radius: 50%; + padding: 2px 0 0 0; + margin: 10px; } .chat-input input[good] + button { - box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); + box-shadow: + 0 0 2px rgba(0, 0, 0, 0.12), + 0 2px 4px rgba(0, 0, 0, 0.24); } .chat-input input[good] + button:hover { - box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); - /* filter: brightness(150%); */ + box-shadow: + 0 8px 17px 0 rgba(0, 0, 0, 0.2), + 0 6px 20px 0 rgba(0, 0, 0, 0.19); + /* filter: brightness(150%); */ } .chat-input input[good] + button path { - fill: var(--chat-bubble-message); + fill: var(--chat-bubble-message); } .msg-container { - direction: ltr; - position: static; - width: 100%; - padding: 10px 0px 0px 0px; - display: grid; - grid-template: 1fr / 1fr; - align-self: start; + direction: ltr; + position: static; + width: 100%; + padding: 10px 0px 0px 0px; + display: grid; + grid-template: 1fr / 1fr; + align-self: start; } .msg-container > * { - grid-column: 1 / 1; - grid-row: 1 / 1; + grid-column: 1 / 1; + grid-row: 1 / 1; } .msg-container.sender { - place-items: self-start; + place-items: self-start; } .msg-container.user { - place-items: self-end; + place-items: self-end; } .msg-box { - background: var(--chat-bubble); - color: white; - min-width: 100px; - border-radius: 5px; - padding: 18px 5px 5px 5px; - box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); - width: fit-content; - position: relative; - align-self: start; + background: var(--chat-bubble); + color: white; + min-width: 100px; + border-radius: 5px; + padding: 18px 5px 5px 5px; + box-shadow: + 0 0 2px rgba(0, 0, 0, 0.12), + 0 2px 4px rgba(0, 0, 0, 0.24); + width: fit-content; + position: relative; + align-self: start; } .msg-box.sender { - margin: 25px 25px 0px 35px; + margin: 25px 25px 0px 35px; } .msg-box.user { - text-align: left; - margin: 25px 35px 0px 0px; + text-align: left; + margin: 25px 35px 0px 0px; } .msg-box-user-temp { - background: var(--chat-bubble-temp); + background: var(--chat-bubble-temp); } .user-img { - display: inline-block; - position: relative; - border-radius: 50%; - height: 50px; - width: 50px; - z-index: 5; - align-self: start; + display: inline-block; + position: relative; + border-radius: 50%; + height: 50px; + width: 50px; + z-index: 5; + align-self: start; } .messages.user { - margin-right: 20px; + margin-right: 20px; } .msg { - font-size: 12pt; - color: var(--chat-bubble-message); - margin: 0 0 0 0; + font-size: 12pt; + color: var(--chat-bubble-message); + margin: 0 0 0 0; } .msg-temp { - color: var(--chat-bubble-message-temp); + color: var(--chat-bubble-message-temp); } .timestamp { - color: var(--chat-bubble-header); - font-size: 10pt; - align-items: center; - font-family: 'xxii_avenmedium'; + color: var(--chat-bubble-header); + font-size: 10pt; + align-items: center; + font-family: 'xxii_avenmedium'; } .timestamp-temp { - color: var(--chat-bubble-header-temp); + color: var(--chat-bubble-header-temp); } .username { - background-color: var(--main-color4); - color: white; - position: relative; - border-radius: 5px; - z-index: 3; - align-self: start; + background-color: var(--main-color4); + color: white; + position: relative; + border-radius: 5px; + z-index: 3; + align-self: start; } .username.sender { - padding: 0px 5px 5px 30px; - margin: 20px 5px 5px 30px; + padding: 0px 5px 5px 30px; + margin: 20px 5px 5px 30px; } .username.user { - padding: 0px 30px 5px 5px; - margin: 20px 30px 5px 5px; + padding: 0px 30px 5px 5px; + margin: 20px 30px 5px 5px; } .username-temp { - color: var(--chat-bubble-header-temp); + color: var(--chat-bubble-header-temp); } .post-time { - font-size: 8pt; - color: white; - display: inline-block; - background-color: var(--main-color4); - position: relative; - z-index: 2; - border-radius: 5px; - align-self: start; + font-size: 8pt; + color: white; + display: inline-block; + background-color: var(--main-color4); + position: relative; + z-index: 2; + border-radius: 5px; + align-self: start; } .post-time.sender { - padding: 5px 5px 0px 15px; - margin: 0px 0px 0px 50px; + padding: 5px 5px 0px 15px; + margin: 0px 0px 0px 50px; } .post-time.user { - padding: 5px 15px 0px 5px; - margin: 0px 50px 0px 0px; + padding: 5px 15px 0px 5px; + margin: 0px 50px 0px 0px; } .mmg { - display: flex; + display: flex; } .img { - height: 100%; - width: 100%; - border-radius: 50%; + height: 100%; + width: 100%; + border-radius: 50%; } .status-circle { - width: 20px; - border-radius: 50%; - z-index: 6; - position: relative; - align-self: start; + width: 20px; + border-radius: 50%; + z-index: 6; + position: relative; + align-self: start; } .status-circle.sender { - margin-left: 40px; + margin-left: 40px; } .status-circle.user { - margin-right: 40px; + margin-right: 40px; } .menu-select { - font-size: 0.9rem; - height: 40px; - border-radius: 20px; - background-color: var(--main-color3); - color: var(--main-color2); - align-items: center; - border: 0px; - padding-left: 10px; - width: 300px; - font-size: 100%; - padding: 10px; - padding-right: 25px; - outline: none; - -webkit-appearance: none; - -moz-appearance: none; - background-image: url("data:image/svg+xml;utf8,"); - background-repeat: no-repeat; - background-position-x: 100%; - background-position-y: 5px; + font-size: 0.9rem; + height: 40px; + border-radius: 20px; + background-color: var(--main-color3); + color: var(--main-color2); + align-items: center; + border: 0px; + padding-left: 10px; + width: 300px; + font-size: 100%; + padding: 10px; + padding-right: 25px; + outline: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-position-x: 100%; + background-position-y: 5px; } .top-select { - width: auto; - height: 24px; - padding: 0px; - margin: 0px; - background-color: transparent; - color: white; - -webkit-appearance: none; - -moz-appearance: none; - border: none; + width: auto; + height: 24px; + padding: 0px; + margin: 0px; + background-color: transparent; + color: white; + -webkit-appearance: none; + -moz-appearance: none; + border: none; } .info-image { - width: 50px; - height: 50px; + width: 50px; + height: 50px; } .top-select option { - margin: 40px; - background: rgba(0, 0, 0, 0.3); - color: #fff; - text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4); - background-color: var(--top-bar); + margin: 40px; + background: rgba(0, 0, 0, 0.3); + color: #fff; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4); + background-color: var(--top-bar); } .AdvancedMenu { - border: 1px var(--main-color2) solid; - margin-top: 10px; - min-width: 555px; - border-radius: 5px; - border-radius: 5px; + border: 1px var(--main-color2) solid; + margin-top: 10px; + min-width: 555px; + border-radius: 5px; + border-radius: 5px; } .legendStyle { - margin-left: 1em; - padding: 0.2em 0.8em; - display: flex; - align-items: center; + margin-left: 1em; + padding: 0.2em 0.8em; + display: flex; + align-items: center; } .AdvancedMenuRow { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - justify-content: left; - margin-bottom: 10px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + justify-content: left; + margin-bottom: 10px; } .AdvancedMenuLabel { - font-size: 10pt; - padding-right: 5px; - margin-left: 10px; - width: 125px; + font-size: 10pt; + padding-right: 5px; + margin-left: 10px; + width: 125px; } .AdvancedMenuLabel2 { - font-size: 10pt; - padding-right: 5px; - margin-left: 10px; + font-size: 10pt; + padding-right: 5px; + margin-left: 10px; } .AdvancedMenuLabel3 { - font-size: 12pt; - padding-right: 5px; - margin-left: 10px; + font-size: 12pt; + padding-right: 5px; + margin-left: 10px; } #SaveAdvancedSettingsButton { - margin-left: 10px; + margin-left: 10px; } .toggle { - position: relative; - display: inline-block; - width: 60px; - height: 40px; - background-color: var(--main-color3); - border-radius: 20px; + position: relative; + display: inline-block; + width: 60px; + height: 40px; + background-color: var(--main-color3); + border-radius: 20px; } /* After slide changes */ .toggle:after { - content: ''; - position: absolute; - width: 30px; - height: 30px; - border-radius: 50%; - background-color: var(--main-color2); - left: 5px; - top: 5px; + content: ''; + position: absolute; + width: 30px; + height: 30px; + border-radius: 50%; + background-color: var(--main-color2); + left: 5px; + top: 5px; } /* Checkbox checked effect */ .checkbox:checked + .toggle::after { - left: 25px; + left: 25px; } /* Checkbox checked toggle label bg color */ .checkbox:checked + .toggle { - background-color: var(--main-color1); + background-color: var(--main-color1); } /* Checkbox vanished */ .checkbox { - display: none; + display: none; } /* Small toggle */ @@ -464,36 +471,45 @@ h1 { /* toggle in label designing */ .toggle-small { - position: relative; - display: inline-block; - width: 30px; - height: 20px; - background-color: var(--main-color3); - border-radius: 10px; - margin-left: 10px; + position: relative; + display: inline-block; + width: 30px; + height: 20px; + background-color: var(--main-color3); + border-radius: 10px; + margin-left: 10px; } /* After slide changes */ .toggle-small:after { - content: ''; - position: absolute; - width: 15px; - height: 15px; - border-radius: 50%; - background-color: white; - left: 2px; - top: 2px; + content: ''; + position: absolute; + width: 15px; + height: 15px; + border-radius: 50%; + background-color: white; + left: 2px; + top: 2px; } /* Checkbox checked effect */ .checkbox:checked + .toggle-small::after { - left: 13px; + left: 13px; } /* Checkbox checked toggle label bg color */ .checkbox:checked + .toggle-small { - background-color: var(--main-color1); + background-color: var(--main-color1); +} + +.emoji-picker { + margin-left: auto; + visibility: hidden; + bottom: 50px; + left: 0px; + position: absolute; + z-index: 1; } diff --git a/src/css/checkbox.css b/src/css/checkbox.css index 2a01657..15b2bdb 100644 --- a/src/css/checkbox.css +++ b/src/css/checkbox.css @@ -1,62 +1,62 @@ -input[type="radio"]:checked { - visibility: hidden; - position: absolute; +input[type='radio']:checked { + visibility: hidden; + position: absolute; } -input[type="radio"] { - visibility: hidden; - position: absolute; +input[type='radio'] { + visibility: hidden; + position: absolute; } label.btn span { - font-size: 1.5em; + font-size: 1.5em; } -label input[type="radio"]~i.fa.fa-square { - color: var(--main-color3); - display: inline; +label input[type='radio'] ~ i.fa.fa-square { + color: var(--main-color3); + display: inline; } -label input[type="radio"]~i.fa.fa-check-square { - display: none; +label input[type='radio'] ~ i.fa.fa-check-square { + display: none; } -label input[type="radio"]:checked~i.fa.fa-square { - display: none; +label input[type='radio']:checked ~ i.fa.fa-square { + display: none; } -label input[type="radio"]:checked~i.fa.fa-check-square { - display: inline; - color: var(--main-color2); +label input[type='radio']:checked ~ i.fa.fa-check-square { + display: inline; + color: var(--main-color2); } -label:hover input[type="radio"]~i.fa { - color: var(--main-color1); - /* filter: brightness(150%); */ +label:hover input[type='radio'] ~ i.fa { + color: var(--main-color1); + /* filter: brightness(150%); */ } -div[data-toggle="buttons"] label { - display: inline-block; - padding: 3px 12px; - margin-bottom: 0; - font-size: 20px; - font-weight: normal; - line-height: 2em; - text-align: left; - white-space: nowrap; - vertical-align: top; - cursor: pointer; - background-color: none; - border-radius: 3px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; +div[data-toggle='buttons'] label { + display: inline-block; + padding: 3px 12px; + margin-bottom: 0; + font-size: 20px; + font-weight: normal; + line-height: 2em; + text-align: left; + white-space: nowrap; + vertical-align: top; + cursor: pointer; + background-color: none; + border-radius: 3px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; } -div[data-toggle="buttons"] label:active, -div[data-toggle="buttons"] label.active { - -webkit-box-shadow: none; - box-shadow: none; -} \ No newline at end of file +div[data-toggle='buttons'] label:active, +div[data-toggle='buttons'] label.active { + -webkit-box-shadow: none; + box-shadow: none; +} diff --git a/src/css/home.css b/src/css/home.css index b612164..5dcccf6 100644 --- a/src/css/home.css +++ b/src/css/home.css @@ -1,253 +1,273 @@ /* Basic styling */ :root { - overflow: hidden; - --main-color1: #6e2c8c; - --main-color1-temp: #6e2c8c; - /*Left bar and top right bar*/ - --main-color2: white; - --main-color2-temp: white; - /*Icons and text*/ - --main-color3: #211e1e; - --main-color3-temp: #211e1e; - /*Buttons and input*/ - --main-color4: #2f2c34; - --main-color4-temp: #2f2c34; - --top-bar: #100b12; - --top-bar-temp: #100b12; - --mid-section: #352d3d; - --mid-section-temp: #352d3d; - --chat-bubble: #7a6d7f; - --chat-bubble-header: #141414; - --chat-bubble-username: white; - --chat-bubble-message: white; - --chat-bubble-temp: #7a6d7f; - --chat-bubble-header-temp: #141414; - --chat-bubble-message-temp: white; + overflow: hidden; + --main-color1: #6e2c8c; + --main-color1-temp: #6e2c8c; + /*Left bar and top right bar*/ + --main-color2: white; + --main-color2-temp: white; + /*Icons and text*/ + --main-color3: #211e1e; + --main-color3-temp: #211e1e; + /*Buttons and input*/ + --main-color4: #2f2c34; + --main-color4-temp: #2f2c34; + --top-bar: #100b12; + --top-bar-temp: #100b12; + --mid-section: #352d3d; + --mid-section-temp: #352d3d; + --chat-bubble: #7a6d7f; + --chat-bubble-header: #141414; + --chat-bubble-username: white; + --chat-bubble-message: white; + --chat-bubble-temp: #7a6d7f; + --chat-bubble-header-temp: #141414; + --chat-bubble-message-temp: white; } html { - box-sizing: border-box; + box-sizing: border-box; } *, *:before, *:after { - box-sizing: inherit; + box-sizing: inherit; } html, body { - height: 100%; - margin: 0; - /* border-top-left-radius: 20px; */ - /* border-top-right-radius: 20px; */ - overflow-x: hidden; + height: 100%; + margin: 0; + /* border-top-left-radius: 20px; */ + /* border-top-right-radius: 20px; */ + overflow-x: hidden; } body { - font-family: 'Segoe UI', sans-serif; - background: transparent; + font-family: 'Segoe UI', sans-serif; + background: transparent; } /* Styling of window frame and titlebar */ body { - /* border: 1px solid #48545c; */ - overflow-y: hidden; + /* border: 1px solid #48545c; */ + overflow-y: hidden; } #titlebar { - display: block; - /* position: fixed; */ - height: 32px; - width: calc(100%); - background-color: var(--top-bar); - /* border-top-left-radius: 20px; + display: block; + /* position: fixed; */ + height: 32px; + width: calc(100%); + background-color: var(--top-bar); + /* border-top-left-radius: 20px; border-top-right-radius: 20px; */ } .maximized #titlebar { - width: 100%; - padding: 0; + width: 100%; + padding: 0; } #main { - height: calc(100% - 32px); - margin-top: 32px; - padding: 20px; - overflow-y: auto; - display: flex; + height: calc(100% - 32px); + margin-top: 32px; + padding: 20px; + overflow-y: auto; + display: flex; } #titlebar { - padding: 4px; + padding: 4px; } #titlebar #drag-region { - width: 100%; - height: 100%; - -webkit-app-region: drag; - display: inline-flex; + width: 100%; + height: 100%; + -webkit-app-region: drag; + display: inline-flex; } #titlebar { - color: var(--main-color2); + color: var(--main-color2); } #window-title { - grid-column: 1; - display: flex; - align-items: center; - margin-left: 8px; - overflow: hidden; - font-family: 'Segoe UI', sans-serif; - font-size: 12px; + grid-column: 1; + display: flex; + align-items: center; + margin-left: 8px; + overflow: hidden; + font-family: 'Segoe UI', sans-serif; + font-size: 12px; } .maximized #window-title { - margin-left: 12px; + margin-left: 12px; } #window-title span { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - line-height: 1.5; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + line-height: 1.5; } #window-controls { - display: grid; - grid-template-columns: repeat(3, 46px); - position: absolute; - top: 0; - right: 0; - height: 32px; - -webkit-app-region: no-drag; + display: grid; + grid-template-columns: repeat(3, 46px); + position: absolute; + top: 0; + right: 0; + height: 32px; + -webkit-app-region: no-drag; } #window-controls .button { - grid-row: 1 / span 1; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 32px; + grid-row: 1 / span 1; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 32px; } @media (-webkit-device-pixel-ratio: 1.5), - (device-pixel-ratio: 1.5), - (-webkit-device-pixel-ratio: 2), - (device-pixel-ratio: 2), - (-webkit-device-pixel-ratio: 3), - (device-pixel-ratio: 3) { - #window-controls .icon { - width: 10px; - height: 10px; - } + (device-pixel-ratio: 1.5), + (-webkit-device-pixel-ratio: 2), + (device-pixel-ratio: 2), + (-webkit-device-pixel-ratio: 3), + (device-pixel-ratio: 3) { + #window-controls .icon { + width: 10px; + height: 10px; + } } #window-controls .button { - user-select: none; + user-select: none; } #window-controls .button:hover { - background: rgba(255, 255, 255, 0.1); - /* filter: brightness(150%); */ + background: rgba(255, 255, 255, 0.1); + /* filter: brightness(150%); */ } #window-controls .button:active { - background: rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.2); } #close-button:hover { - background: rgba(255, 255, 255, 0.1); - /* border-top-right-radius: 20px; */ - background: #f1707a !important; + background: rgba(255, 255, 255, 0.1); + /* border-top-right-radius: 20px; */ + background: #f1707a !important; } #close-button:active { - background: #f1707a !important; + background: #f1707a !important; } #close-button:active .icon { - filter: invert(1); - background: #f1707a !important; + filter: invert(1); + background: #f1707a !important; } #min-button { - grid-column: 1; + grid-column: 1; } #max-button, #restore-button { - grid-column: 2; + grid-column: 2; } #close-button { - grid-column: 3; + grid-column: 3; } #restore-button { - display: none !important; + display: none !important; } .maximized #restore-button { - display: flex !important; + display: flex !important; } .maximized #max-button { - display: none; + display: none; } .active-mic { - position: absolute; - bottom: 0; + position: absolute; + bottom: 0; } .about { - -webkit-app-region: no-drag; - position: absolute; - left: 0; - width: 32px; - text-align: -webkit-center; + -webkit-app-region: no-drag; + position: absolute; + left: 0; + width: 32px; + text-align: -webkit-center; } .language-selector { - position: absolute; - -webkit-app-region: no-drag; - display: inline-block; - background-color: transparent; - cursor: pointer; - font-family: 'NotoColorEmojiLimited', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, - 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; - left: 50%; - transform: translateX(-50%); + position: absolute; + -webkit-app-region: no-drag; + display: inline-block; + background-color: transparent; + cursor: pointer; + font-family: + 'NotoColorEmojiLimited', + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Helvetica, + Arial, + sans-serif, + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol'; + left: 50%; + transform: translateX(-50%); } .language-dropdown { - display: none; - position: absolute; - background-color: #fff; - width: 55px; - box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); - z-index: 2; - font-family: 'NotoColorEmojiLimited', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, - 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + display: none; + position: absolute; + background-color: #fff; + width: 55px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + z-index: 2; + font-family: + 'NotoColorEmojiLimited', + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Helvetica, + Arial, + sans-serif, + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol'; } .language-item { - padding: 5px; - cursor: pointer; - background-color: var(--top-bar); + padding: 5px; + cursor: pointer; + background-color: var(--top-bar); } -.language-item:hover { - /* filter: brightness(150%); */ -} +/* .language-item:hover { + filter: brightness(150%); +} */ @font-face { - font-family: NotoColorEmojiLimited; - unicode-range: U+1F1E6-1F1FF; - src: url(https://raw.githack.com/googlefonts/noto-emoji/main/fonts/NotoColorEmoji.ttf); + font-family: NotoColorEmojiLimited; + unicode-range: U+1F1E6-1F1FF; + src: url(https://raw.githack.com/googlefonts/noto-emoji/main/fonts/NotoColorEmoji.ttf); } diff --git a/src/css/logger.css b/src/css/logger.css index 6b40515..4e2fae4 100644 --- a/src/css/logger.css +++ b/src/css/logger.css @@ -1,34 +1,34 @@ table { - margin-left: 10px; - background-color: white; - border-collapse: collapse; - width: 100%; - margin-top: 60px; + margin-left: 10px; + background-color: white; + border-collapse: collapse; + width: 100%; + margin-top: 60px; } th, td { - border: 1px solid black; - padding: 8px; - text-align: left; + border: 1px solid black; + padding: 8px; + text-align: left; } .info { - background-color: lightblue !important; + background-color: lightblue !important; } .warn { - background-color: #f39c12 !important; + background-color: #f39c12 !important; } .error { - background-color: #e74c3c !important; + background-color: #e74c3c !important; } #logTable { - width: 95%; + width: 95%; } #Logs { - overflow: auto; -} \ No newline at end of file + overflow: auto; +} diff --git a/src/css/menu.css b/src/css/menu.css index d34ca4f..0c17438 100644 --- a/src/css/menu.css +++ b/src/css/menu.css @@ -1,226 +1,230 @@ .container { - display: flex; - height: calc(100vh - 32px); - width: 100%; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - /* will contain if #first is longer than #second */ + display: flex; + height: calc(100vh - 32px); + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + /* will contain if #first is longer than #second */ } .mid { - flex: 3; - display: block; - position: relative; + flex: 3; + display: block; + position: relative; } .OptionPanel { - /* visibility: hidden; */ - background-color: var(--mid-section); - flex: 3; - display: none; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; + /* visibility: hidden; */ + background-color: var(--mid-section); + flex: 3; + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; } .OptionPanel.show { - display: block; - overflow: auto; + display: block; + overflow: auto; } .menu { - height: 100%; - display: block; - width: 100%; - background: var(--main-color1); - z-index: 1; - position: relative; + height: 100%; + display: block; + width: 100%; + background: var(--main-color1); + z-index: 1; + position: relative; } .menu .items { - list-style: none; - margin: auto; - padding: 0; + list-style: none; + margin: auto; + padding: 0; } #rpe { - font-size: 8pt; - margin: 2px 0px 0px 0px; + font-size: 8pt; + margin: 2px 0px 0px 0px; } .menu .items .item { - width: 100%; - height: 50px; - display: flex; - justify-content: center; - align-items: center; - background: var(--main-color1); - color: var(--main-color2); + width: 100%; + height: 50px; + display: flex; + justify-content: center; + align-items: center; + background: var(--main-color1); + color: var(--main-color2); } .hdp:hover { - position: fixed; - /* filter: brightness(150%); */ + position: fixed; + /* filter: brightness(150%); */ } .menu .items .item-active { - background: -webkit-linear-gradient(left, var(--main-color2) 10%, var(--main-color2), var(--main-color1) 10%, var(--main-color1) 10%); - color: var(--main-color2); - filter: brightness(90%); + background: -webkit-linear-gradient(left, var(--main-color2) 10%, var(--main-color2), var(--main-color1) 10%, var(--main-color1) 10%); + color: var(--main-color2); + filter: brightness(90%); } .menu .items .item:hover { - cursor: pointer; - color: var(--main-color2); - filter: brightness(120%); + cursor: pointer; + color: var(--main-color2); + filter: brightness(120%); } .sidepanel-left { - position: relative; - width: 50px; - font-size: 1.5em; - line-height: 1.5em; - font-family: Helvetica; - text-align: center; - box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; - transition: 0.3s ease-in-out; + position: relative; + width: 50px; + font-size: 1.5em; + line-height: 1.5em; + font-family: Helvetica; + text-align: center; + box-shadow: + rgba(0, 0, 0, 0.16) 0px 3px 6px, + rgba(0, 0, 0, 0.23) 0px 3px 6px; + transition: 0.3s ease-in-out; } .sidepanel-right { - position: relative; - width: 200px; - font-size: 1.5em; - line-height: 1.5em; - font-family: Helvetica; - text-align: center; - box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px; - transition: 0.3s ease-in-out; + position: relative; + width: 200px; + font-size: 1.5em; + line-height: 1.5em; + font-family: Helvetica; + text-align: center; + box-shadow: + rgba(0, 0, 0, 0.16) 0px 3px 6px, + rgba(0, 0, 0, 0.23) 0px 3px 6px; + transition: 0.3s ease-in-out; } .collapse-menu-left { - margin-left: -50px; + margin-left: -50px; } .collapse-menu-right { - margin-right: -200px; + margin-right: -200px; } .sidepanel-left span { - position: relative; - display: block; + position: relative; + display: block; } .sidepanel-right span { - position: relative; - display: block; + position: relative; + display: block; } .circle-left { - position: absolute; - width: 50px; - height: 50px; - -webkit-clip-path: polygon(100% 0, 0 0, 0 100%); - clip-path: ellipse(68% 50% at 6% 50%); - font-size: 20px; - background-color: var(--main-color3); - color: var(--main-color2); - justify-content: left; - top: 32px; - left: 50px; - cursor: pointer; - display: flex; - z-index: 2; - transition: 0.3s ease-in-out; + position: absolute; + width: 50px; + height: 50px; + -webkit-clip-path: polygon(100% 0, 0 0, 0 100%); + clip-path: ellipse(68% 50% at 6% 50%); + font-size: 20px; + background-color: var(--main-color3); + color: var(--main-color2); + justify-content: left; + top: 32px; + left: 50px; + cursor: pointer; + display: flex; + z-index: 2; + transition: 0.3s ease-in-out; } .collapse-circle-left { - left: 0px; + left: 0px; } .circle-right { - position: absolute; - width: 50px; - height: 50px; - -webkit-clip-path: polygon(100% 100%, 0 0, 100% 0); - clip-path: ellipse(68% 50% at 94% 50%); - font-size: 20px; - background-color: var(--main-color3); - color: var(--main-color2); - justify-content: right; - top: 32px; - right: 199px; - cursor: pointer; - display: flex; - z-index: 1; - transition: 0.3s ease-in-out; + position: absolute; + width: 50px; + height: 50px; + -webkit-clip-path: polygon(100% 100%, 0 0, 100% 0); + clip-path: ellipse(68% 50% at 94% 50%); + font-size: 20px; + background-color: var(--main-color3); + color: var(--main-color2); + justify-content: right; + top: 32px; + right: 199px; + cursor: pointer; + display: flex; + z-index: 1; + transition: 0.3s ease-in-out; } .collapse-circle-right { - right: 0px; + right: 0px; } .fa-cog { - align-items: center; - align-self: center; - margin-left: 7px; + align-items: center; + align-self: center; + margin-left: 7px; } .fa-eye { - align-self: center; - margin-right: 7px; + align-self: center; + margin-right: 7px; } #min-button { - grid-column: 1; + grid-column: 1; } #max-button, #restore-button { - grid-column: 2; + grid-column: 2; } #close-button { - grid-column: 3; + grid-column: 3; } #mini-container { - width: 100%; - height: 300px; - display: flex; - flex-direction: column; - margin-bottom: 25px; + width: 100%; + height: 300px; + display: flex; + flex-direction: column; + margin-bottom: 25px; } #mini-main { - display: flex; - height: 100%; - flex-direction: row; + display: flex; + height: 100%; + flex-direction: row; } #mini-top-bar { - height: 30px; - background-color: var(--top-bar-temp); - /* border-top-left-radius: 20px; + height: 30px; + background-color: var(--top-bar-temp); + /* border-top-left-radius: 20px; border-top-right-radius: 20px; */ } #mini-left { - flex: 1; - background-color: var(--main-color1-temp); - height: 100%; + flex: 1; + background-color: var(--main-color1-temp); + height: 100%; } #mini-mid { - flex: 8; - background-color: var(--mid-section-temp); - height: 100%; + flex: 8; + background-color: var(--mid-section-temp); + height: 100%; } #mini-right { - flex: 2; - background-color: var(--main-color4-temp); - height: 100%; + flex: 2; + background-color: var(--main-color4-temp); + height: 100%; } diff --git a/src/css/sliders.css b/src/css/sliders.css index ce80bf7..3742d78 100644 --- a/src/css/sliders.css +++ b/src/css/sliders.css @@ -1,179 +1,195 @@ /*generated with Input range slider CSS style generator (version 20211225) https://toughengineer.github.io/demo/slider-styler*/ input[type='range'].styled-slider { - /* height: 500px; */ - background: transparent; - -webkit-appearance: none; - width: 300px; + /* height: 500px; */ + background: transparent; + -webkit-appearance: none; + width: 300px; } /*progress support*/ input[type='range'].styled-slider.slider-progress1 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } input[type='range'].styled-slider.slider-progress2 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } input[type='range'].styled-slider.slider-progress3 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } input[type='range'].styled-slider.slider-progress4 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } /*webkit*/ input[type='range'].styled-slider::-webkit-slider-thumb { - -webkit-appearance: none; - width: 2em; - height: 40px; - border-radius: 20px; - background: #ffffff; - border: none; - box-shadow: 0 0 2px black; - margin-top: calc(2em * 0.5 - 2em * 0.5); + -webkit-appearance: none; + width: 2em; + height: 40px; + border-radius: 20px; + background: #ffffff; + border: none; + box-shadow: 0 0 2px black; + margin-top: calc(2em * 0.5 - 2em * 0.5); } input[type='range'].styled-slider::-webkit-slider-runnable-track { - height: 40px; - border: none; - border-radius: 20px; - background: #1a1a1a; - box-shadow: none; + height: 40px; + border: none; + border-radius: 20px; + background: #1a1a1a; + box-shadow: none; } input[type='range'].styled-slider.slider-progress1::-webkit-slider-runnable-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #1a1a1a; } input[type='range'].styled-slider.slider-progress2::-webkit-slider-runnable-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #1a1a1a; } input[type='range'].styled-slider.slider-progress3::-webkit-slider-runnable-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #1a1a1a; } input[type='range'].styled-slider.slider-progress4::-webkit-slider-runnable-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #1a1a1a; } /*mozilla*/ input[type='range'].styled-slider::-moz-range-thumb { - width: 2em; - height: 40px; - border-radius: 20px; - background: #ffffff; - border: none; - box-shadow: 0 0 2px black; + width: 2em; + height: 40px; + border-radius: 20px; + background: #ffffff; + border: none; + box-shadow: 0 0 2px black; } input[type='range'].styled-slider::-moz-range-track { - height: 40px; - border: none; - border-radius: 20px; - background: var(--main-color3); - box-shadow: none; + height: 40px; + border: none; + border-radius: 20px; + background: var(--main-color3); + box-shadow: none; } input[type='range'].styled-slider.slider-progress1::-moz-range-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #464646; } input[type='range'].styled-slider.slider-progress2::-moz-range-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #464646; } input[type='range'].styled-slider.slider-progress3::-moz-range-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #464646; } input[type='range'].styled-slider.slider-progress4::-moz-range-track { - background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646; + background: + linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, + #464646; } /*ms*/ input[type='range'].styled-slider::-ms-fill-upper { - background: transparent; - border-color: transparent; + background: transparent; + border-color: transparent; } input[type='range'].styled-slider::-ms-fill-lower { - background: transparent; - border-color: transparent; + background: transparent; + border-color: transparent; } input[type='range'].styled-slider::-ms-thumb { - width: 2em; - height: 40px; - border-radius: 20px; - background: #ffffff; - border: none; - box-shadow: 0 0 2px black; - margin-top: 0; - box-sizing: border-box; + width: 2em; + height: 40px; + border-radius: 20px; + background: #ffffff; + border: none; + box-shadow: 0 0 2px black; + margin-top: 0; + box-sizing: border-box; } input[type='range'].styled-slider::-ms-track { - height: 40px; - border-radius: 20px; - background: var(--main-color3); - border: none; - box-shadow: none; - box-sizing: border-box; + height: 40px; + border-radius: 20px; + background: var(--main-color3); + border: none; + box-shadow: none; + box-sizing: border-box; } input[type='range'].styled-slider.slider-progress1::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: var(--main-color1); - border: none; - border-right-width: 0; + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: var(--main-color1); + border: none; + border-right-width: 0; } input[type='range'].styled-slider.slider-progress2::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: var(--main-color1); - border: none; - border-right-width: 0; + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: var(--main-color1); + border: none; + border-right-width: 0; } input[type='range'].styled-slider.slider-progress3::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: var(--main-color1); - border: none; - border-right-width: 0; + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: var(--main-color1); + border: none; + border-right-width: 0; } input[type='range'].styled-slider.slider-progress4::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: var(--main-color1); - border: none; - border-right-width: 0; + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: var(--main-color1); + border: none; + border-right-width: 0; } .inputBox { - border: none; - width: 38px; - border-radius: 10px; - text-align: center; - font-size: 14pt; - font-weight: bold; + border: none; + width: 38px; + border-radius: 10px; + text-align: center; + font-size: 14pt; + font-weight: bold; } diff --git a/src/css/tabs.css b/src/css/tabs.css index e0eaaff..8e71345 100644 --- a/src/css/tabs.css +++ b/src/css/tabs.css @@ -1,394 +1,398 @@ .viewer-list { - background-color: var(--main-color4); - height: 100%; - flex: 1; - font-size: 14px; - height: 100%; - display: block; + background-color: var(--main-color4); + height: 100%; + flex: 1; + font-size: 14px; + height: 100%; + display: block; } ul.no-bullets { - list-style-type: none; - list-style-position: outside; - margin: 0%; - padding: 0%; - padding-left: 5px; - text-align: left; + list-style-type: none; + list-style-position: outside; + margin: 0%; + padding: 0%; + padding-left: 5px; + text-align: left; } li { - line-height: 1em; + line-height: 1em; } h1.titles { - margin: 0px; - padding: 0%; - text-align: left; - padding-left: 5px; + margin: 0px; + padding: 0%; + text-align: left; + padding-left: 5px; } main { - background: var(--main-color1); - box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - display: flex; - justify-content: space-between; - height: 32px; + background: var(--main-color1); + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); + display: flex; + justify-content: space-between; + height: 32px; } main label { - text-align: center; - display: flex; - justify-content: center; - align-items: center; + text-align: center; + display: flex; + justify-content: center; + align-items: center; } p { - font-size: 13px; + font-size: 13px; } main input { - display: none; + display: none; } section { - clear: both; - padding-top: 10px; - display: none; - height: calc(100% - 60px); + clear: both; + padding-top: 10px; + display: none; + height: calc(100% - 60px); } .Basiclabel { - font-weight: bold; - font-size: 14px; - display: block; - float: left; - flex: auto; - font-size: 20px; - padding: 0px 10px; - width: 50px; - align-self: baseline; - text-align: center; + font-weight: bold; + font-size: 14px; + display: block; + float: left; + flex: auto; + font-size: 20px; + padding: 0px 10px; + width: 50px; + align-self: baseline; + text-align: center; } .scale { - height: 2em; - width: 2em; - vertical-align: bottom; + height: 2em; + width: 2em; + vertical-align: bottom; } .tab { - /* filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); */ - align-items: flex-start; - margin: auto; - cursor: pointer; + /* filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); */ + align-items: flex-start; + margin: auto; + cursor: pointer; } input:checked + label { - border-top-color: #ffb03d; - border-right-color: #ddd; - border-left-color: #ddd; - border-bottom-color: transparent; - text-decoration: none; + border-top-color: #ffb03d; + border-right-color: #ddd; + border-left-color: #ddd; + border-bottom-color: transparent; + text-decoration: none; } /* --------------------------------- */ .radius { - border-radius: 5px; + border-radius: 5px; } .radius .tabx:active::before { - border-radius: 5px !important; + border-radius: 5px !important; } .tabx-bar { - background-color: var(--main-color1); - /* padding: 5px; */ - box-shadow: 1px 4px 20px rgba(0, 0, 0, 0.2); - display: flex; - /* margin: 10px; */ - color: black; - height: 50px; + background-color: var(--main-color1); + /* padding: 5px; */ + box-shadow: 1px 4px 20px rgba(0, 0, 0, 0.2); + display: flex; + /* margin: 10px; */ + color: black; + height: 50px; } .tabx-bar .tabx { - box-sizing: border-box; - text-decoration: none; - color: inherit; - width: 70px; - height: 50px; - background: inherit; - display: inherit; - flex-direction: column; - justify-content: center; - align-items: center; - position: relative; - transition: all 0.3s; + box-sizing: border-box; + text-decoration: none; + color: inherit; + width: 70px; + height: 50px; + background: inherit; + display: inherit; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; + transition: all 0.3s; } .tabx-bar .tabx::before { - position: absolute; - content: ''; - width: 26%; - height: 13%; - border-top-left-radius: 200px; - border-top-right-radius: 200px; - border-bottom: none; - background-color: #607d8b; - /* bottom: -8px; */ - opacity: 0; - transition: all 0.3s ease-in-out; + position: absolute; + content: ''; + width: 26%; + height: 13%; + border-top-left-radius: 200px; + border-top-right-radius: 200px; + border-bottom: none; + background-color: #607d8b; + /* bottom: -8px; */ + opacity: 0; + transition: all 0.3s ease-in-out; } .tabx-bar .tabx:active::before { - width: 100%; - height: 100%; - background-color: #5fef8d; - border-radius: 0; + width: 100%; + height: 100%; + background-color: #5fef8d; + border-radius: 0; } .tabx-bar .tabx:hover::before { - opacity: 1; - bottom: 0px; + opacity: 1; + bottom: 0px; } -.tabx-bar .tabx::after { -} +/* .tabx-bar .tabx::after { +} */ .tabx-bar .tabx:hover { - padding-bottom: 10px; + padding-bottom: 10px; } .tabx-bar .tabx:hover::after { - opacity: 1; - top: 6px; + opacity: 1; + top: 6px; } .tabx-bar .tabx.selected { - background-color: rgba(0, 0, 0, 0.1); - border-radius: inherit; - padding-top: 0px; + background-color: rgba(0, 0, 0, 0.1); + border-radius: inherit; + padding-top: 0px; } .tabx-bar .tabx.selected::after { - opacity: 1; - top: -10px; + opacity: 1; + top: -10px; } .tabx-bar .tabx.selected::before { - opacity: 1; - bottom: 0px; + opacity: 1; + bottom: 0px; } .tabx-bar .tabx .icon { - color: inherit; - font-size: 24px; - display: inherit; + color: inherit; + font-size: 24px; + display: inherit; } .tabx-bar .tabx .icon img { - margin: auto; - height: 32 px; + margin: auto; + height: 32 px; } .language { - width: 80px; - text-align: center; + width: 80px; + text-align: center; } #AdvancedMenu_mask { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - margin-top: 0px; - width: 100%; - height: 100%; - visibility: hidden; - overflow: auto; - overflow-x: hidden; - background-color: var(--mid-section); - font-family: 'xxii_avenmedium'; - padding-left: 50px; - padding-right: 50px; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin-top: 0px; + width: 100%; + height: 100%; + visibility: hidden; + overflow: auto; + overflow-x: hidden; + background-color: var(--mid-section); + font-family: 'xxii_avenmedium'; + padding-left: 50px; + padding-right: 50px; } #ThemeCreator_mask { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - margin-top: 0px; - width: 100%; - height: 100%; - visibility: hidden; - flex-direction: column; - justify-content: center; - overflow: auto; - overflow-x: hidden; - background-color: var(--mid-section); - font-family: 'xxii_avenmedium'; - padding-left: 50px; - padding-right: 50px; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin-top: 0px; + width: 100%; + height: 100%; + visibility: hidden; + flex-direction: column; + justify-content: center; + overflow: auto; + overflow-x: hidden; + background-color: var(--mid-section); + font-family: 'xxii_avenmedium'; + padding-left: 50px; + padding-right: 50px; } .fname { - background: var(--main-color3); - border: none; - height: 40px; - border-radius: 40px; - width: 300px; - outline: none; - color: var(--main-color2); - font-size: 10pt; - padding-left: 10px; + background: var(--main-color3); + border: none; + height: 40px; + border-radius: 40px; + width: 300px; + outline: none; + color: var(--main-color2); + font-size: 10pt; + padding-left: 10px; } input[type='password'] { - background: var(--main-color3); - border: none; - height: 40px; - border-radius: 40px; - width: 300px; - outline: none; - color: var(--main-color2); - font-size: 10pt; - padding-left: 10px; - padding-right: 40px; - /* To make space for the reveal button */ + background: var(--main-color3); + border: none; + height: 40px; + border-radius: 40px; + width: 300px; + outline: none; + color: var(--main-color2); + font-size: 10pt; + padding-left: 10px; + padding-right: 40px; + /* To make space for the reveal button */ } input[type='url'] { - background: var(--main-color3); - border: none; - height: 40px; - border-radius: 40px; - width: 260px; - outline: none; - color: var(--main-color2); - font-size: 10pt; - margin-left: 10px; + background: var(--main-color3); + border: none; + height: 40px; + border-radius: 40px; + width: 260px; + outline: none; + color: var(--main-color2); + font-size: 10pt; + margin-left: 10px; } input[type='lol'] { - background: var(--main-color3); - border: none; - height: 40px; - border-radius: 40px; - width: 300px; - outline: none; - color: var(--main-color2); - font-size: 10pt; - padding-left: 10px; - padding-right: 40px; - /* To make space for the reveal button */ + background: var(--main-color3); + border: none; + height: 40px; + border-radius: 40px; + width: 300px; + outline: none; + color: var(--main-color2); + font-size: 10pt; + padding-left: 10px; + padding-right: 40px; + /* To make space for the reveal button */ } /* Style for the reveal button */ .password-toggle-btn { - position: absolute; - background-color: transparent; - border: none; - cursor: pointer; - left: 450px; + position: absolute; + background-color: transparent; + border: none; + cursor: pointer; + left: 450px; } /* Hide the default appearance of the button */ .password-toggle-btn::-moz-focus-inner { - border: 0; + border: 0; } /* Style the reveal icon (you can use your preferred icon or font) */ .password-toggle-icon { - font-size: 16px; - color: var(--main-color2); + font-size: 16px; + color: var(--main-color2); } #toasts { - position: absolute; - bottom: 20px; - /* Adjust the distance from the bottom of the screen */ - right: 0%; - /* Center the toasts horizontally */ - display: flex; - flex-direction: column; - z-index: 999; + position: absolute; + bottom: 20px; + /* Adjust the distance from the bottom of the screen */ + right: 0%; + /* Center the toasts horizontally */ + display: flex; + flex-direction: column; + z-index: 999; } .toast { - background-color: #333; - color: white; - border-radius: 5px; - padding: 1rem 2rem; - margin: 0.5rem; - opacity: 0; - transform: translateY(100%); - animation: toastAnimation 0.5s ease-in-out forwards, toastDisappear 0.5s ease-in-out 9s forwards; + background-color: #333; + color: white; + border-radius: 5px; + padding: 1rem 2rem; + margin: 0.5rem; + opacity: 0; + transform: translateY(100%); + animation: + toastAnimation 0.5s ease-in-out forwards, + toastDisappear 0.5s ease-in-out 9s forwards; } /* Apply different colors based on the toast type */ .info { - background-color: lightblue !important; + background-color: lightblue !important; } .success { - background-color: #2ecc71 !important; + background-color: #2ecc71 !important; } .warning { - background-color: #f39c12 !important; + background-color: #f39c12 !important; } .error { - background-color: #e74c3c !important; + background-color: #e74c3c !important; } /* CSS animation for the toast appearance */ @keyframes toastAnimation { - from { - opacity: 0; - transform: translateY(100%); - } + from { + opacity: 0; + transform: translateY(100%); + } - to { - opacity: 1; - transform: translateY(0); - } + to { + opacity: 1; + transform: translateY(0); + } } /* CSS animation for the toast disappearance */ @keyframes toastDisappear { - from { - opacity: 1; - } + from { + opacity: 1; + } - to { - opacity: 0; - } + to { + opacity: 0; + } } .menu-icon { - font-size: 17pt; + font-size: 17pt; } .tooltip { - position: absolute; - display: inline-block; - visibility: hidden; - font-size: 12px; - line-height: 20px; - padding: 5px; - background: var(--main-color3); - border-radius: 5px; - visibility: hidden; - opacity: 1; - box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2); - transition: opacity 0.3s, visibility 0s; - color: var(--main-color2); - font-family: 'xxii_avenmedium'; - z-index: 999; + position: absolute; + display: inline-block; + visibility: hidden; + font-size: 12px; + line-height: 20px; + padding: 5px; + background: var(--main-color3); + border-radius: 5px; + visibility: hidden; + opacity: 1; + box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2); + transition: + opacity 0.3s, + visibility 0s; + color: var(--main-color2); + font-family: 'xxii_avenmedium'; + z-index: 999; } /* .tooltip .tooltiptext { @@ -413,29 +417,29 @@ input[type='lol'] { } */ div[type='text']:disabled { - background: #4b4b4b; - display: none; + background: #4b4b4b; + display: none; } input[type='text']:disabled { - background: #4b4b4b; + background: #4b4b4b; } button[type='text']:disabled { - background: #4b4b4b; - display: none; + background: #4b4b4b; + display: none; } input[type2='text']:disabled { - background: #4b4b4b; + background: #4b4b4b; } div:disabled { - background: #4b4b4b; - filter: brightness(200%); + background: #4b4b4b; + filter: brightness(200%); } div:disabled { - background: #4b4b4b; - filter: brightness(200%); + background: #4b4b4b; + filter: brightness(200%); } diff --git a/src/css/tts-menu.css b/src/css/tts-menu.css index fd36954..77f8b99 100644 --- a/src/css/tts-menu.css +++ b/src/css/tts-menu.css @@ -1,161 +1,169 @@ #tstx { - display: flex; - flex-direction: row; - margin-left: 40px; + display: flex; + flex-direction: row; + margin-left: 40px; } .optionrow { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - justify-content: left; - margin-bottom: 10px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + justify-content: left; + margin-bottom: 10px; } .LabelText { - margin-bottom: 5px; - color: var(--main-color2); - margin: 0px 0px 5px 0px; + margin-bottom: 5px; + color: var(--main-color2); + margin: 0px 0px 5px 0px; } #volume-icon { - color: var(--main-color2); - scale: 0.75; - cursor: pointer; - text-align: center; - align-self: center; + color: var(--main-color2); + scale: 0.75; + cursor: pointer; + text-align: center; + align-self: center; } #image { - width: 100px; - height: 100px; - margin-bottom: 10px; + width: 100px; + height: 100px; + margin-bottom: 10px; } .TTSVolume { - color: var(--main-color2); - font-size: 12pt; - text-align: center; + color: var(--main-color2); + font-size: 12pt; + text-align: center; } #SoundVolume { - color: var(--main-color2); - font-size: 12pt; + color: var(--main-color2); + font-size: 12pt; } .testLabel { - color: var(--main-color2); - font-size: 12pt; + color: var(--main-color2); + font-size: 12pt; } textarea { - height: 60px; - padding: 5px; - width: 300px; - resize: none; - border-radius: 5px; - background: var(--main-color3); - color: var(--main-color2); - font-family: 'xxii_avenmedium'; - border: none; + height: 60px; + padding: 5px; + width: 300px; + resize: none; + border-radius: 5px; + background: var(--main-color3); + color: var(--main-color2); + font-family: 'xxii_avenmedium'; + border: none; } .SaveConfig { - align-content: center; - display: flex; - flex-direction: column; - justify-content: center; - color: var(--main-color2); - margin-bottom: 10px; + align-content: center; + display: flex; + flex-direction: column; + justify-content: center; + color: var(--main-color2); + margin-bottom: 10px; } .SmallButton { - color: var(--main-color2); - width: 50px; - cursor: pointer; - text-shadow: 0 0 5px #070607, 0 0 5px #070607, 0 0 5px #070607; - /* transition: all 0.15s ease-in-out; */ - text-align: center; + color: var(--main-color2); + width: 50px; + cursor: pointer; + text-shadow: + 0 0 5px #070607, + 0 0 5px #070607, + 0 0 5px #070607; + /* transition: all 0.15s ease-in-out; */ + text-align: center; } .SmallButton:hover { - /* color: var(--main-color1); */ - width: 50px; - cursor: pointer; - /* filter: brightness(150%); */ + /* color: var(--main-color1); */ + width: 50px; + cursor: pointer; + /* filter: brightness(150%); */ } .SmallButton:active { - color: var(--main-color1); - transform: translateY(4px); - text-shadow: 0 0 5px #000, 0 0 5px #000, 0 0 5px #000; + color: var(--main-color1); + transform: translateY(4px); + text-shadow: + 0 0 5px #000, + 0 0 5px #000, + 0 0 5px #000; } .AdvancedMenuButton { - width: 300px; - height: 40px; - border-radius: 20px; - background-color: var(--main-color3); - color: var(--main-color2); - padding: 0; - border: none; - font-family: 'xxii_avenmedium'; - font-size: 14pt; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - transition: box-shadow 0.3s ease, background-color 0.3s ease; - /* Add a smooth transition for box-shadow and background-color */ + width: 300px; + height: 40px; + border-radius: 20px; + background-color: var(--main-color3); + color: var(--main-color2); + padding: 0; + border: none; + font-family: 'xxii_avenmedium'; + font-size: 14pt; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + transition: + box-shadow 0.3s ease, + background-color 0.3s ease; + /* Add a smooth transition for box-shadow and background-color */ } .AdvancedMenuButton:hover { - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); - background-color: var(--main-color3); - filter: brightness(150%); - /* Darken the background color on hover */ - cursor: pointer; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + background-color: var(--main-color3); + filter: brightness(150%); + /* Darken the background color on hover */ + cursor: pointer; } .AdvancedMenuButton:active { - transform: translateY(2px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - background-color: var(--main-color3); - /* Reset the background color on click */ + transform: translateY(2px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + background-color: var(--main-color3); + /* Reset the background color on click */ } .AdvancedMenuIcon { - filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); - align-items: flex-start; - margin: auto; - height: 24px; - width: 24px; + filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); + align-items: flex-start; + margin: auto; + height: 24px; + width: 24px; } .AdvancedMenuIcon2 { - align-items: flex-start; - margin: auto; - height: 24px; - width: 24px; + align-items: flex-start; + margin: auto; + height: 24px; + width: 24px; } input:hover { - filter: brightness(120%); + filter: brightness(120%); } select:hover { - filter: brightness(120%); + filter: brightness(120%); } textarea:hover { - filter: brightness(120%); + filter: brightness(120%); } label:hover { - filter: brightness(120%); + filter: brightness(120%); } .circle-right:hover { - filter: brightness(120%); + filter: brightness(120%); } .circle-left:hover { - filter: brightness(120%); + filter: brightness(120%); } diff --git a/src/css/volume-slider.css b/src/css/volume-slider.css index 15fc8d9..ff7242f 100644 --- a/src/css/volume-slider.css +++ b/src/css/volume-slider.css @@ -1,87 +1,87 @@ .middle { - width: 100%; - height: 50px; - border-radius: 10px; - display: flex; - align-items: center; + width: 100%; + height: 50px; + border-radius: 10px; + display: flex; + align-items: center; } .slider-container { - width: 300px; - height: 100%; - position: relative; + width: 300px; + height: 100%; + position: relative; } .slider-container .bar { - display: block; - width: 100%; - height: 100%; - border-radius: 10px; - background-color: var(--main-color3); + display: block; + width: 100%; + height: 100%; + border-radius: 10px; + background-color: var(--main-color3); } .slider-container .bar .fill { - display: block; - width: 50%; - height: 100%; - border-radius: inherit; - background-color: var(--main-color1); + display: block; + width: 50%; + height: 100%; + border-radius: inherit; + background-color: var(--main-color1); } .slider-container .slider { - position: absolute; - top: 50%; - -webkit-appearance: none; - margin: 0; - width: 100%; - height: 0; - border-radius: 5px; - outline: none; - background-color: transparent; + position: absolute; + top: 50%; + -webkit-appearance: none; + margin: 0; + width: 100%; + height: 0; + border-radius: 5px; + outline: none; + background-color: transparent; } .slider-container .slider::-webkit-slider-thumb { - -webkit-appearance: none; - width: 30px; - height: 30px; - background-color: var(--main-color2); - border-top-left-radius: 50%; - border-top-right-radius: 50%; - border-bottom-right-radius: 50%; - border-bottom-left-radius: 50%; - transform: rotate(-45deg) translate(0%, 0%); - cursor: pointer; - outline: none; - /* box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); */ - box-shadow: 0 0 3px rgb(0 0 0 / 10%); - /* transition: .3s ease-in-out; */ + -webkit-appearance: none; + width: 30px; + height: 30px; + background-color: var(--main-color2); + border-top-left-radius: 50%; + border-top-right-radius: 50%; + border-bottom-right-radius: 50%; + border-bottom-left-radius: 50%; + transform: rotate(-45deg) translate(0%, 0%); + cursor: pointer; + outline: none; + /* box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); */ + box-shadow: 0 0 3px rgb(0 0 0 / 10%); + /* transition: .3s ease-in-out; */ } .slider-container .slider:active::-webkit-slider-thumb, .slider-container .slider::-webkit-slider-thumb:hover { - border-bottom-left-radius: 0; - transform: rotate(-45deg) translate(50%, -50%); + border-bottom-left-radius: 0; + transform: rotate(-45deg) translate(50%, -50%); } .slider-container .slider:active::-webkit-slider-thumb { - box-shadow: 0 0 0 3px rgba(255, 255, 255, 1); + box-shadow: 0 0 0 3px rgba(255, 255, 255, 1); } .option-icon-container { - display: flex; - flex-direction: column; - /* justify-content: center; */ - align-items: center; - /* width: 78px; */ - /* float: right; */ - flex-grow: 1; + display: flex; + flex-direction: column; + /* justify-content: center; */ + align-items: center; + /* width: 78px; */ + /* float: right; */ + flex-grow: 1; } .brush-icon-container { - margin-left: -20px; - font-size: 20pt; + margin-left: -20px; + font-size: 20pt; } .icon { - fill: var(--main-color2); + fill: var(--main-color2); } diff --git a/src/index.html b/src/index.html index 4a0caef..89111e2 100644 --- a/src/index.html +++ b/src/index.html @@ -1,652 +1,670 @@ - + - - - - - LoquendoBot + + + + + LoquendoBot - - - - - - - - - - - - - - - - - -
- -
-
-
- -  -
-
- - -
-
-
- -
-
- -
-
- -
-
-
-
- -
- - - -
- -
-
-
- -
-
- - - -
- -
- - - - - - - - - - -
LevelMessageMetadataTimestamp
-
- - - -
- - - -
- - - -
-
-
-
-
- -  -
General settings
-
-
-
Port
- - -
-
-
Default TTS Service
- -
-
-
2nd TTS Service
- -
-
-
TTS Output Device
- - -
-
-
TTS Volume
-
- -
-
- - -
-
-
- -
- -  - - -
Enable STT
-
-
-
STT Input Device
- -
-
-
Voice Language
- -
-
- -
- - - - -
Enable Language detection
-
-
-
Language detection service
- -
-
-
Translate incoming chat messages to
- - - -
-
-
Default TTS language
- -
-
-
2nd TTS language
- -
-
- -
- -  - - -
Enable internal TTS
-
-
-
Default Internal Voice
- -
-
-
Test default Internal Voice
- -
- - -
-
-
-
2nd Internal Voice
- -
-
-
Test 2nd Internal Voice
- -
- - -
-
-
-
- -  - - -
Enable notification sounds
-
-
-
Notification Volume
-
- -
-
- - -
-
-
-
Notification Sound
- -
- - -
-
-
- -
- -  - - -
Enable Twitch
-
-
-
Channel Name
- - -
-
-
Oauth Token
- - - -
-
-
Test credentials
- - -
-
- -
- - - - -
Enable Modules
-
-
-
Use Vtuber
- - - - -
-
-
Use ChatBubble
- - - - -
-
- -
- - - - -
Enable Amazon services
-
-
-
Access Key
- - -
-
-
Access Secret
- - -
-
-
Test credentials
- - -
-
-
Characters used
- - -
-
-
Default Amazon Voice
- -
-
-
Test Default Amazon Voice
- -
- - -
-
-
-
2nd Amazon Voice
- -
-
-
Test 2nd Amazon Voice
- -
- - -
-
-
- -
- - - - -
Enable Google services
-
-
-
API Key
- - -
-
-
Test credentials
- - -
-
-
Characters used
- - -
-
-
Default Google Voice
- -
-
-
Test default Google Voice
- -
- - -
-
-
-
2nd Google Voice
- -
-
-
Test 2nd Google Voice
- -
- - -
-
-
-
-
-
-
- - - -
-
- -
- - - - - -
-
- - -
-
-
- - -
- -
-
-
-
-
-
-
-
- -
- - - - -
Enable Custom Theme
-
-
- -
Main Color 1
-
-
- -
Main Color 2
-
-
- -
Main Color 3
-
-
- -
Main Color 4
-
-
- -
Top Bar
-
-
- -
Mid Section
-
-
- -
Chat Bubble Background
-
-
- -
Chat Bubble Header
-
-
- -
Chat Bubble Message
-
-
-
-
- -
-
- - - -
-
-
- -  - -
-
-

Moderators

-
    -

    Viewers

    -
      -
      -
      -
        -
      • a
      • -
      • b
      • -
      • c
      • -
      -
      -
      -
        -
      • 1
      • -
      • 2
      • -
      • 3
      • -
      -
      -
      -
      -
      -
      - -
      -
      - -
      - - - + + + + + + + + + + + + + + + + + +
      + +
      +
      +
      + +  +
      +
      + + +
      +
      +
      + +
      +
      + +
      +
      + +
      +
      +
      +
      + +
      + + + +
      + +
      +
      +
      + +
      +
      + + + +
      + +
      + + + + + + + + + + +
      LevelMessageMetadataTimestamp
      +
      + + + +
      + + + +
      + + + +
      +
      +
      +
      +
      + +  +
      General settings
      +
      +
      +
      Port
      + + +
      +
      +
      Zoom level %
      + + +
      +
      + +
      + +  + + +
      Enable TTS
      +
      +
      +
      Default TTS Service
      + +
      +
      +
      Default TTS language
      + +
      +
      +
      2nd TTS Service
      + +
      +
      +
      2nd TTS language
      + +
      +
      +
      TTS Output Device
      + + +
      +
      +
      TTS Volume
      +
      + +
      +
      + + +
      +
      +
      +
      Default Internal Voice
      + +
      +
      +
      Test default Internal Voice
      + +
      + + +
      +
      +
      +
      2nd Internal Voice
      + +
      +
      +
      Test 2nd Internal Voice
      + +
      + + +
      +
      +
      + +
      + +  + + +
      Enable STT
      +
      +
      +
      STT Input Device
      + +
      +
      +
      Voice Language
      + +
      +
      + +
      + + + + +
      Enable Language detection
      +
      +
      +
      Translate chat messages to
      + +
      +
      +
      Broadcast translation
      + + +
      +
      +
      Output to TTS service
      + +
      +
      + +
      + +  + + +
      Enable notification sounds
      +
      +
      +
      Notification sounds Output Device
      + + +
      + +
      +
      Notification Volume
      +
      + +
      +
      + + +
      +
      +
      +
      Notification Sound
      + +
      + + +
      +
      +
      + +
      + +  + + +
      Enable Twitch
      +
      +
      +
      Channel Name
      + + +
      +
      +
      Oauth Token
      + + + +
      +
      +
      Test credentials
      + + +
      +
      + +
      + + + + +
      Enable Modules
      +
      +
      +
      Use PNGtuber
      + + + + +
      +
      +
      Use Vtuber
      + + + + +
      +
      +
      Use ChatBubble
      + + + + +
      +
      +
      Use Finger
      + + + + +
      +
      + +
      + + + + +
      Enable Amazon services
      +
      +
      +
      Access Key
      + + +
      +
      +
      Access Secret
      + + +
      +
      +
      Test credentials
      + + +
      +
      +
      Characters used
      + + +
      +
      +
      Default Amazon Voice
      + +
      +
      +
      Test Default Amazon Voice
      + +
      + + +
      +
      +
      +
      2nd Amazon Voice
      + +
      +
      +
      Test 2nd Amazon Voice
      + +
      + + +
      +
      +
      + +
      + + + + +
      Enable Google services
      +
      +
      +
      API Key
      + + +
      +
      +
      Test credentials
      + + +
      +
      +
      Characters used
      + + +
      +
      +
      Default Google Voice
      + +
      +
      +
      Test default Google Voice
      + +
      + + +
      +
      +
      +
      2nd Google Voice
      + +
      +
      +
      Test 2nd Google Voice
      + +
      + + +
      +
      +
      +
      +
      +
      +
      + + + +
      +
      + +
      +
      + +
      + + + + + + +
      +
      + + +
      +
      +
      + + +
      + +
      +
      +
      +
      +
      +
      +
      +
      + +
      + + + + +
      Enable Custom Theme
      +
      +
      + +
      Main Color 1
      +
      +
      + +
      Main Color 2
      +
      +
      + +
      Main Color 3
      +
      +
      + +
      Main Color 4
      +
      +
      + +
      Top Bar
      +
      +
      + +
      Mid Section
      +
      +
      + +
      Chat Bubble Background
      +
      +
      + +
      Chat Bubble Header
      +
      +
      + +
      Chat Bubble Message
      +
      +
      +
      +
      + +
      +
      + + + +
      +
      +
      + +  + +
      +
      +

      Moderators

      +
        +

        Viewers

        +
          +
          +
          +
            +
          • a
          • +
          • b
          • +
          • c
          • +
          +
          +
          +
            +
          • 1
          • +
          • 2
          • +
          • 3
          • +
          +
          +
          +
          +
          +
          + +
          +
          + +
          + + + + diff --git a/src/js/amazon.js b/src/js/amazon.js index fd2de7a..0ec9b52 100644 --- a/src/js/amazon.js +++ b/src/js/amazon.js @@ -1,118 +1,118 @@ +/* global settings, callback, addVoiceService, amazonVoices, */ + const https = require('https'); const querystring = require('querystring'); const aws4 = require('aws4'); function getAmazonVoices() { - if (!settings.AMAZON.USE_AMAZON) { - callback(); - return; - } + if (!settings.AMAZON.USE_AMAZON) { + callback(); + return; + } - addVoiceService('Amazon'); + addVoiceService('Amazon'); - let primaryVoice = document.querySelector('#primaryAmazonVoice'); - let secondaryVoice = document.querySelector('#secondaryAmazonVoice'); + const primaryVoice = document.querySelector('#primaryAmazonVoice'); + const secondaryVoice = document.querySelector('#secondaryAmazonVoice'); - function setVoicesinSelect(voiceSelect) { - const voices = Object.values(amazonVoices); - voices.forEach((voice) => { - const option = document.createElement('option'); - option.classList.add('option'); + function setVoicesinSelect(voiceSelect) { + const voices = Object.values(amazonVoices); + voices.forEach(voice => { + const option = document.createElement('option'); + option.classList.add('option'); - option.value = voice; - option.innerHTML = voice; + option.value = voice; + option.innerHTML = voice; - voiceSelect.appendChild(option); - }); - } - setVoicesinSelect(primaryVoice); - primaryVoice.value = settings.AMAZON.PRIMARY_VOICE; - setVoicesinSelect(secondaryVoice); - secondaryVoice.value = settings.AMAZON.SECONDARY_VOICE; + voiceSelect.appendChild(option); + }); + } + setVoicesinSelect(primaryVoice); + primaryVoice.value = settings.AMAZON.PRIMARY_VOICE; + setVoicesinSelect(secondaryVoice); + secondaryVoice.value = settings.AMAZON.SECONDARY_VOICE; } if (settings.AMAZON.USE_AMAZON) { - getAmazonVoices(); + getAmazonVoices(); } class PollyTTS { - constructor() {} + textToSpeech(options, callback) { + if (!options) { + return callback(new Error('Options are missing')); + } - textToSpeech(options, callback) { - if (!options) { - return callback(new Error('Options are missing')); + const qs = { + Text: options.text, + TextType: options.textType || 'text', + VoiceId: options.voiceId || 'Mia', + SampleRate: options.sampleRate || 22050, + OutputFormat: options.outputFormat || 'mp3', + Engine: options.engine || 'neural' + }; + + const opts = { + service: 'polly', + region: options.region || 'us-east-1', + path: `/v1/speech?${querystring.stringify(qs)}`, + signQuery: true + }; + + // you can also pass AWS credentials in explicitly (otherwise taken from process.env) + aws4.sign(opts, this.credentials); + https + .get(opts, res => { + if (res.statusCode !== 200) { + return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`)); + } + callback(null, res); + return true; + }) + .on('error', e => { + callback(e); + }); + + return null; + } + + describeVoices(callback, credentials) { + this.credentials = credentials; + const qs = { + Engine: 'neural' + }; + + const opts = { + service: 'polly', + region: 'us-east-1', + path: `/v1/voices?${querystring.stringify(qs)}`, + signQuery: true + }; + + // you can also pass AWS credentials in explicitly (otherwise taken from process.env) + aws4.sign(opts, this.credentials); + https + .get(opts, res => { + if (res.statusCode !== 200) { + return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`)); } - const qs = { - Text: options.text, - TextType: options.textType || 'text', - VoiceId: options.voiceId || 'Mia', - SampleRate: options.sampleRate || 22050, - OutputFormat: options.outputFormat || 'mp3', - Engine: options.engine || 'neural', - }; + let body = ''; + res.on('readable', () => { + body += res.read(); + }); + res.on('end', () => { + callback(null, body); + }); - const opts = { - service: 'polly', - region: options.region || 'us-east-1', - path: `/v1/speech?${querystring.stringify(qs)}`, - signQuery: true, - }; + return undefined; + }) + .on('error', e => { + callback(e); + }); - // you can also pass AWS credentials in explicitly (otherwise taken from process.env) - aws4.sign(opts, this.credentials); - https - .get(opts, (res) => { - if (res.statusCode !== 200) { - return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`)); - } - callback(null, res); - return true; - }) - .on('error', (e) => { - callback(e); - }); - - return null; - } - - describeVoices(callback, credentials) { - this.credentials = credentials; - const qs = { - Engine: 'neural', - }; - - const opts = { - service: 'polly', - region: 'us-east-1', - path: `/v1/voices?${querystring.stringify(qs)}`, - signQuery: true, - }; - - // you can also pass AWS credentials in explicitly (otherwise taken from process.env) - aws4.sign(opts, this.credentials); - https - .get(opts, (res) => { - if (res.statusCode !== 200) { - return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`)); - } - - let body = ''; - res.on('readable', () => { - body += res.read(); - }); - res.on('end', () => { - callback(null, body); - }); - - return undefined; - }) - .on('error', (e) => { - callback(e); - }); - - return null; - } + return null; + } } const pollyTTS = new PollyTTS(); diff --git a/src/js/auth.js b/src/js/auth.js index ec2d6a8..926ea4b 100644 --- a/src/js/auth.js +++ b/src/js/auth.js @@ -1,103 +1,217 @@ +/* global settings, fs, settingsPath, ini, shell, options, axios */ + const twitchAuthentication = () => - new Promise((resolve) => { - const http = require('http'); - const redirectUri = 'http://localhost:1989/auth'; - const scopes = ['chat:edit', 'chat:read']; + new Promise(resolve => { + const http = require('http'); + const redirectUri = 'http://localhost:1989/auth'; + const scopes = ['chat:edit', 'chat:read']; - const express = require('express'); - let tempAuthServer = express(); - const port = 1989; + const express = require('express'); + const tempAuthServer = express(); + const port = 1989; - const { parse: parseQueryString } = require('querystring'); + const { parse: parseQueryString } = require('querystring'); - tempAuthServer.use(function (req, res, next) { - if (req.url !== '/auth') { - let token = parseQueryString(req.query.auth); - settings.TWITCH.OAUTH_TOKEN = token['#access_token']; - fs.writeFileSync(settingsPath, ini.stringify(settings)); + tempAuthServer.use(function (req, res, next) { + if (req.url !== '/auth') { + const token = parseQueryString(req.query.auth); + settings.TWITCH.OAUTH_TOKEN = token['#access_token']; + fs.writeFileSync(settingsPath, ini.stringify(settings)); - resolve(token['#access_token']); - stopServer(); - } - next(); - }); - - function stopServer() { - tempAuthServer.close(); - } - - const htmlString = ` - - - - Authentication - - -

          Authentication successful! You can close this window now.

          -
          - -
          - - - - `; - - tempAuthServer.get('/auth', (req, res) => { - res.send(htmlString); - }); - - tempAuthServer.post('/auth', (req, res) => { - res.render('authentication', { name: req.body.name }); - }); - - const server = http.createServer(tempAuthServer); - - server.listen(port, () => { - const authURL = `https://id.twitch.tv/oauth2/authorize?client_id=${settings.TWITCH.CLIENT_ID}&redirect_uri=${encodeURIComponent( - redirectUri, - )}&response_type=token&scope=${scopes.join(' ')}`; - shell.openExternal(authURL); - }); - - function stopServer() { - server.close(() => {}); - } + resolve(token['#access_token']); + stopServer(); + } + next(); }); + // function stopServer() { + // tempAuthServer.close(); + // } + + const htmlString = ` + + + + Authentication + + +

          Authentication successful! You can close this window now.

          +
          + +
          + + + + `; + + tempAuthServer.get('/auth', (req, res) => { + res.send(htmlString); + }); + + tempAuthServer.post('/auth', (req, res) => { + res.render('authentication', { name: req.body.name }); + }); + + const server = http.createServer(tempAuthServer); + + server.listen(port, () => { + const authURL = `https://id.twitch.tv/oauth2/authorize?client_id=${settings.TWITCH.CLIENT_ID}&redirect_uri=${encodeURIComponent( + redirectUri + )}&response_type=token&scope=${scopes.join(' ')}`; + shell.openExternal(authURL); + }); + + function stopServer() { + server.close(() => {}); + } + }); + function getTwitchUserId() { - // Get user Logo with access token - options = { - method: 'GET', - url: `https://api.twitch.tv/helix/users`, - headers: { 'Client-ID': settings.TWITCH.CLIENT_ID, Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` }, - }; + // Get user Logo with access token + options = { + method: 'GET', + url: 'https://api.twitch.tv/helix/users', + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; - axios - .request(options) - .then((responseLogoUrl) => { - console.log(responseLogoUrl.data.data[0]); - settings.TWITCH.USERNAME = responseLogoUrl.data.data[0].display_name; - settings.TWITCH.USER_LOGO_URL = responseLogoUrl.data.data[0].profile_image_url; - settings.TWITCH.USER_ID = responseLogoUrl.data.data[0].id; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - }) - .catch((error) => { - console.error(error); - }); -} -function getTwitchOauthToken() { - return twitchAuthentication().then((res) => { - getTwitchUserId(); - return res; + axios + .request(options) + .then(responseLogoUrl => { + console.log(responseLogoUrl.data.data[0]); + settings.TWITCH.USERNAME = responseLogoUrl.data.data[0].display_name; + settings.TWITCH.USER_LOGO_URL = responseLogoUrl.data.data[0].profile_image_url; + settings.TWITCH.USER_ID = responseLogoUrl.data.data[0].id; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }) + .catch(error => { + console.error(error); }); } +function getTwitchSubscriptions(channelId) { + // Get user Logo with access token + options = { + method: 'GET', + url: `https://api.twitch.tv/helix/chat/emotes?broadcaster_id=${channelId}`, + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; + + axios + .request(options) + .then(responseLogoUrl => { + console.log(responseLogoUrl); + }) + .catch(error => { + console.error(error); + }); +} + +function getTwitchChannelEmotes(channelId) { + // Get user Logo with access token + options = { + method: 'GET', + url: `https://api.twitch.tv/helix/chat/emotes?broadcaster_id=${channelId}`, + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; + + axios + .request(options) + .then(responseLogoUrl => { + console.log(responseLogoUrl); + }) + .catch(error => { + console.error(error); + }); +} + +function getTwitchChannelFollows(channelId) { + // Get user Logo with access token + options = { + method: 'GET', + url: 'https://api.twitch.tv/helix/streams/followed', + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; + + axios + .request(options) + .then(responseLogoUrl => { + console.log(responseLogoUrl); + }) + .catch(error => { + console.error(error); + }); +} + +function getTwitchChannelSubscriptions(channelId) { + // Get user Logo with access token + options = { + method: 'GET', + url: `https://api.twitch.tv/helix/chat/emotes?broadcaster_id=${channelId}`, + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; + + axios + .request(options) + .then(responseLogoUrl => { + console.log(responseLogoUrl); + }) + .catch(error => { + console.error(error); + }); +} + +function getTwitchChannelId() { + // Get user Logo with access token + options = { + method: 'GET', + url: 'https://api.twitch.tv/helix/users?login=MelvyCoral', + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; + + axios + .request(options) + .then(responseLogoUrl => { + // console.log(responseLogoUrl); + getTwitchChannelEmotes(responseLogoUrl.data.data[0].id); + }) + .catch(error => { + console.error(error); + }); +} + +function getTwitchOauthToken() { + // getTwitchChannelId(); + getTwitchGLobalEmotes(); + // return twitchAuthentication().then(res => { + // getTwitchUserId(); + // return res; + // }); +} + module.exports = { getTwitchOauthToken }; diff --git a/src/js/backend.js b/src/js/backend.js index e576585..8e5281e 100644 --- a/src/js/backend.js +++ b/src/js/backend.js @@ -1,167 +1,178 @@ +/* global settings, addVoiceService, internalVoices, ttsRequestCount, main, path, pythonPath, settingsPath, ipcRenderer */ + const spawn = require('child_process').spawn; -var kill = require('kill-process-by-name'); +const kill = require('kill-process-by-name'); let python; async function getInstalledVoices() { - if (!settings.TTS.USE_TTS) { - return; + if (!settings.TTS.USE_TTS) { + return; + } + addVoiceService('Internal'); + + try { + const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/voices`, { method: 'GET' }); + if (response.ok) { + const responseData = await response.json(); + console.log('Response:', responseData); + internalVoices = responseData; + } else { + console.error('Failed to send termination signal to Flask server.'); } - addVoiceService('Internal'); + } catch (error) { + console.error('Error sending termination signal:', error); + } - try { - const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/voices`, { method: 'GET' }); - if (response.ok) { - const responseData = await response.json(); - console.log('Response:', responseData); - internalVoices = responseData; - } else { - console.error('Failed to send termination signal to Flask server.'); - } - } catch (error) { - console.error('Error sending termination signal:', error); - } + const primaryVoice = document.querySelector('#primaryVoice'); + const secondaryVoice = document.querySelector('#secondaryVoice'); - let primaryVoice = document.querySelector('#primaryVoice'); - let secondaryVoice = document.querySelector('#secondaryVoice'); + function setVoicesinSelect(voiceSelect) { + const voices = Object.values(internalVoices.voices); + voices.forEach(voice => { + const option = document.createElement('option'); + option.classList.add('option'); - function setVoicesinSelect(voiceSelect) { - const voices = Object.values(internalVoices.voices); - voices.forEach((voice) => { - const option = document.createElement('option'); - option.classList.add('option'); + option.value = voice; + option.innerHTML = voice; - option.value = voice; - option.innerHTML = voice; - - voiceSelect.appendChild(option); - }); - } - setVoicesinSelect(primaryVoice); - primaryVoice.value = settings.TTS.PRIMARY_VOICE; - setVoicesinSelect(secondaryVoice); - secondaryVoice.value = settings.TTS.SECONDARY_VOICE; + voiceSelect.appendChild(option); + }); + } + setVoicesinSelect(primaryVoice); + primaryVoice.value = settings.TTS.PRIMARY_VOICE; + setVoicesinSelect(secondaryVoice); + secondaryVoice.value = settings.TTS.SECONDARY_VOICE; } async function getBackendServerStatus() { - try { - const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/status`, { method: 'GET' }); - if (response.ok) { - const responseData = await response.json(); - console.log('Response:', responseData); - } else { - console.error('Failed to send termination signal to Flask server.'); - } - } catch (error) { - console.error('Error sending termination signal:', error); + console.log('getting status'); + try { + const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/status`, { method: 'GET' }); + if (response.ok) { + const responseData = await response.json(); + console.log('Response:', responseData); + } else { + console.error('Failed to send termination signal to Flask server.'); } + } catch (error) { + console.error('Error sending termination signal:', error); + } } function startSTT() { - const eventSource = new EventSource('http://127.0.0.1:9000/stream'); + const eventSource = new EventSource('http://127.0.0.1:9000/stream'); - eventSource.addEventListener('message', (event) => { - const result = event.data; - console.log(result); // Log the received data - }); + eventSource.addEventListener('message', event => { + const result = event.data; + console.log(result); // Log the received data + }); - eventSource.addEventListener('error', (event) => { - console.error('EventSource failed:', event); + eventSource.addEventListener('error', event => { + console.error('EventSource failed:', event); - eventSource.close(); - }); + eventSource.close(); + }); - window.addEventListener('beforeunload', () => { - eventSource.close(); - }); + window.addEventListener('beforeunload', () => { + eventSource.close(); + }); } async function getInternalTTSAudio(requestData) { - ttsRequestCount++; - requestData.count = ttsRequestCount; - const requestOptions = { - method: 'POST', // HTTP method - headers: { - 'Content-Type': 'application/json', // Specify the content type - }, - body: JSON.stringify(requestData), // Convert the data to JSON and include it in the request body - }; + ttsRequestCount++; + requestData.count = ttsRequestCount; + const requestOptions = { + method: 'POST', // HTTP method + headers: { + 'Content-Type': 'application/json' // Specify the content type + }, + body: JSON.stringify(requestData) // Convert the data to JSON and include it in the request body + }; - try { - const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/audio`, requestOptions); - if (response.ok) { - const responseData = await response.json(); - console.log('Response:', responseData); - return ttsRequestCount; - } else { - console.error('Failed to send termination signal to Flask server.'); - } - } catch (error) { - console.error('Error sending termination signal:', error); + try { + const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/audio`, requestOptions); + if (response.ok) { + const responseData = await response.json(); + console.log('Response:', responseData); + return ttsRequestCount; + } else { + console.error('Failed to send termination signal to Flask server.'); } + } catch (error) { + console.error('Error sending termination signal:', error); + } } const createBackendServer = () => - new Promise((resolve) => { - if (main.isPackaged) { - python = spawn(path.join(pythonPath, './loquendoBot_backend.exe'), [settingsPath, 'prod']); - } else { - python = spawn('python', ['-u', path.join(pythonPath, './loquendoBot_backend.py'), settingsPath, 'dev']); - } - // Capture the stdout of the Python process - python.stdout.on('data', (data) => { - console.info(`${data}`); - }); - - // Capture the stderr of the Python process - python.stderr.on('data', (data) => { - console.error(`${data}`); - resolve('finished'); // cannot get it to resolve with stdout - }); - - // Listen for the Python process to exit - python.on('close', (code) => { - console.log(`Python process exited with code ${code}`); - }); - - if (typeof python.pid !== 'number') { - console.log('failed'); - } else { - console.log(`Spawned subprocess correctly!, PID = ${python.pid}`); - } + new Promise(resolve => { + if (main.isPackaged) { + python = spawn(path.join(pythonPath, './loquendoBot_backend.exe'), [settingsPath, 'prod']); + } else { + python = spawn('python', ['-u', path.join(pythonPath, './loquendoBot_backend.py'), settingsPath, 'dev']); + } + // Capture the stdout of the Python process + python.stdout.on('data', data => { + console.info(`${data}`); + if (data.toString().startsWith('kees')) { + console.log('yess'); + // getBackendServerStatus(); + } }); -async function initiateBackend() { - try { - createBackendServer().then(() => { - getBackendServerStatus(); - getInstalledVoices(); - if (settings.STT.USE_STT) { - startSTT(); - } - }); - } catch (error) { - console.error('Error during backend initialization:', error); + // Capture the stderr of the Python process + python.stderr.on('data', data => { + // console.error(`${data}`); + if (data.toString().startsWith('INFO:waitress:Serving on')) { + resolve('finished'); + } else { + console.error(`${data}`); + } + }); + + // Listen for the Python process to exit + python.on('close', code => { + console.log(`Python process exited with code ${code}`); + }); + + if (typeof python.pid !== 'number') { + console.log('failed'); + } else { + // console.log(`Spawned subprocess correctly!, PID = ${python.pid}`); } + }); + +async function initiateBackend() { + try { + createBackendServer().then(() => { + getBackendServerStatus(); + getInstalledVoices(); + if (settings.STT.USE_STT) { + startSTT(); + } + }); + } catch (error) { + console.error('Error during backend initialization:', error); + } } initiateBackend(); -//TODO: convert to restartServer function +// TODO: convert to restartServer function ipcRenderer.on('quit-event', async () => { - try { - const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/terminate`, { method: 'GET' }); - if (response.ok) { - const responseData = await response.json(); - console.log('Response:', responseData); - kill('loquendoBot_backend'); - } else { - console.error('Failed to send termination signal to Flask server.'); - kill('loquendoBot_backend'); - } - } catch (error) { - console.error('Error sending termination signal:', error); - kill('loquendoBot_backend'); + try { + const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/terminate`, { method: 'GET' }); + if (response.ok) { + const responseData = await response.json(); + console.log('Response:', responseData); + kill('loquendoBot_backend'); + } else { + console.error('Failed to send termination signal to Flask server.'); + kill('loquendoBot_backend'); } + } catch (error) { + console.error('Error sending termination signal:', error); + kill('loquendoBot_backend'); + } }); module.exports = { getInternalTTSAudio }; diff --git a/src/js/chat.js b/src/js/chat.js index e4ad9de..ebc8eda 100644 --- a/src/js/chat.js +++ b/src/js/chat.js @@ -1,54 +1,76 @@ -function getResponse() { - const userText = document.querySelector('#textInput').value; +/* global messageTemplates, emojiPicker, settings, getPostTime, showChatMessage, twitch */ - // If nothing is written don't do anything - if (userText === '') { - return; - } +async function getResponse() { + const userText = document.querySelector('#textInput').value; - // Create chat message from received data - const article = document.createElement('article'); - article.className = 'msg-container user'; + // If nothing is written don't do anything + if (userText === '') { + return; + } - article.innerHTML = messageTemplates.userTemplate; + // Create chat message from received data + const article = document.createElement('article'); + article.className = 'msg-container user'; - const userImg = article.querySelector('.user-img'); - if (userImg) { - userImg.src = settings.TWITCH.USER_LOGO_URL; - } + article.innerHTML = messageTemplates.userTemplate; - const postTime = article.querySelector('.post-time'); + const userImg = article.querySelector('.user-img'); + if (userImg) { + userImg.src = settings.TWITCH.USER_LOGO_URL; + } - if (postTime) { - postTime.innerText = getPostTime(); - } + const postTime = article.querySelector('.post-time'); - article.appendChild(postTime); + if (postTime) { + postTime.innerText = getPostTime(); + } - const msg = article.querySelector('.msg-box'); - if (msg) { - msg.innerText = userText; - } + article.appendChild(postTime); - // Appends the message to the main chat box (shows the message) - showChatMessage(article, true); + const msg = article.querySelector('.msg-box'); + if (msg) { + console.log(0); + await replaceChatMessageWithCustomEmojis(userText).then(data => { + // console.log(data); + msg.innerHTML = data; - twitch.sendMessage(userText); + // Appends the message to the main chat box (shows the message) + showChatMessage(article); - // Empty input box after sending message - document.body.querySelector('#textInput').value = ''; + twitch.sendMessage(userText); + + // Empty input box after sending message + document.body.querySelector('#textInput').value = ''; + }); + } } +const replaceChatMessageWithCustomEmojis = message => + new Promise(resolve => { + const words = message.split(' '); + words.forEach(async word => { + if (word !== '') { + await emojiPicker.database.getEmojiByUnicodeOrName(word).then(data => { + if (data && data.name === word) { + const url = ``; + message = message.replace(word, url); + } + }); + resolve(message); + } + }); + }); + // Function that will execute when you press 'enter' in the message box -document.body.querySelector('#textInput').addEventListener('keydown', (e) => { - if (e.which === 13) { - getResponse(); - } +document.body.querySelector('#textInput').addEventListener('keydown', e => { + if (e.which === 13) { + getResponse(); + } }); // Function that will execute when you click the 'send' button document.body.querySelector('#SendButton').addEventListener('click', () => { - getResponse(); + getResponse(); }); // #endregion @@ -57,21 +79,21 @@ document.body.querySelector('#SendButton').addEventListener('click', () => { // Left panel document.body.querySelector('.circle-left').addEventListener('click', () => { - const menu = document.body.querySelector('.sidepanel-left'); + const menu = document.body.querySelector('.sidepanel-left'); - if (menu.classList.contains('collapse-menu-left')) { - menu.classList.remove('collapse-menu-left'); - } else { - menu.classList.add('collapse-menu-left'); - } + if (menu.classList.contains('collapse-menu-left')) { + menu.classList.remove('collapse-menu-left'); + } else { + menu.classList.add('collapse-menu-left'); + } - const leftCircle = document.body.querySelector('.circle-left'); + const leftCircle = document.body.querySelector('.circle-left'); - if (leftCircle.classList.contains('collapse-circle-left')) { - leftCircle.classList.remove('collapse-circle-left'); - } else { - leftCircle.classList.add('collapse-circle-left'); - } + if (leftCircle.classList.contains('collapse-circle-left')) { + leftCircle.classList.remove('collapse-circle-left'); + } else { + leftCircle.classList.add('collapse-circle-left'); + } }); // #region Show panels @@ -80,27 +102,26 @@ document.body.querySelector('.circle-left').addEventListener('click', () => { // TODO : optimize show panels // Function that shows and hides the option panels. (TTS, Configuration, Commands) const displayPanel = (panelSelectorClass, panelSelectorID, btnSelectorID) => { - const btn = document.querySelector(btnSelectorID); - const panel = document.querySelector(panelSelectorID); - const panels = document.querySelectorAll(panelSelectorClass); + const btn = document.querySelector(btnSelectorID); + const panel = document.querySelector(panelSelectorID); + const panels = document.querySelectorAll(panelSelectorClass); - btn.addEventListener( - 'click', - (event) => { - event.stopPropagation(); - panels.forEach((el) => { - if (el === panel) return; - el.classList.remove('show'); - }); - if (panel.classList.contains('show')) { - } else { - panel.classList.add('show'); - } - }, - { - capture: true, - }, - ); + btn.addEventListener( + 'click', + event => { + event.stopPropagation(); + panels.forEach(el => { + if (el === panel) return; + el.classList.remove('show'); + }); + if (!panel.classList.contains('show')) { + panel.classList.add('show'); + } + }, + { + capture: true + } + ); }; displayPanel('.OptionPanel', '#Configuration', '#btnConfiguration'); @@ -113,27 +134,26 @@ displayPanel('.OptionPanel', '#ChatCreator', '#btnChatCreator'); // #endregion const displayPanelX = (panelSelectorClass, panelSelectorID, btnSelectorID) => { - const btn = document.querySelector(btnSelectorID); - const panel = document.querySelector(panelSelectorID); - const panels = document.querySelectorAll(panelSelectorClass); + const btn = document.querySelector(btnSelectorID); + const panel = document.querySelector(panelSelectorID); + const panels = document.querySelectorAll(panelSelectorClass); - btn.addEventListener( - 'click', - (event) => { - event.stopPropagation(); - panels.forEach((el) => { - if (el === panel) return; - el.classList.remove('item-active'); - }); - if (panel.classList.contains('item-active')) { - } else { - panel.classList.add('item-active'); - } - }, - { - capture: true, - }, - ); + btn.addEventListener( + 'click', + event => { + event.stopPropagation(); + panels.forEach(el => { + if (el === panel) return; + el.classList.remove('item-active'); + }); + if (!panel.classList.contains('item-active')) { + panel.classList.add('item-active'); + } + }, + { + capture: true + } + ); }; displayPanelX('.item', '#btnChat', '#btnChat'); diff --git a/src/js/customEmojis.js b/src/js/customEmojis.js new file mode 100644 index 0000000..a1a951a --- /dev/null +++ b/src/js/customEmojis.js @@ -0,0 +1,9 @@ +const customEmojis = [ + { + name: 'sakuraestaKleefeliz', + shortcodes: ['sakuraestaKleefeliz'], + url: 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_0cb536ddb6e143ab87ffeccb160a4d45/default/dark/1.0' + } +]; + +module.exports = { customEmojis }; diff --git a/src/js/google.js b/src/js/google.js index 9edfa68..81774e6 100644 --- a/src/js/google.js +++ b/src/js/google.js @@ -1,31 +1,33 @@ +/* global settings, addVoiceService, googleVoices */ + function getGoogleVoices() { - if (!settings.GOOGLE.USE_GOOGLE) { - return; - } + if (!settings.GOOGLE.USE_GOOGLE) { + return; + } - addVoiceService('Google'); + addVoiceService('Google'); - let primaryVoice = document.querySelector('#primaryGoogleVoice'); - let secondaryVoice = document.querySelector('#secondaryGoogleVoice'); + const primaryVoice = document.querySelector('#primaryGoogleVoice'); + const secondaryVoice = document.querySelector('#secondaryGoogleVoice'); - function setVoicesinSelect(voiceSelect) { - const voices = Object.values(googleVoices); - voices.forEach((voice) => { - const option = document.createElement('option'); - option.classList.add('option'); + function setVoicesinSelect(voiceSelect) { + const voices = Object.values(googleVoices); + voices.forEach(voice => { + const option = document.createElement('option'); + option.classList.add('option'); - option.value = voice; - option.innerHTML = voice; + option.value = voice; + option.innerHTML = voice; - voiceSelect.appendChild(option); - }); - } - setVoicesinSelect(primaryVoice); - primaryVoice.value = settings.GOOGLE.PRIMARY_VOICE; - setVoicesinSelect(secondaryVoice); - secondaryVoice.value = settings.GOOGLE.SECONDARY_VOICE; + voiceSelect.appendChild(option); + }); + } + setVoicesinSelect(primaryVoice); + primaryVoice.value = settings.GOOGLE.PRIMARY_VOICE; + setVoicesinSelect(secondaryVoice); + secondaryVoice.value = settings.GOOGLE.SECONDARY_VOICE; } if (settings.GOOGLE.USE_GOOGLE) { - getGoogleVoices(); + getGoogleVoices(); } diff --git a/src/js/languages.js b/src/js/languages.js index 3f7e0fc..91a16d9 100644 --- a/src/js/languages.js +++ b/src/js/languages.js @@ -1,331 +1,332 @@ // TODO: Enable STT: -// Output STT to TTS? *TTS service selection* (for now, later add the option to choose a specific voice with mega dropdowns) +// Output STT to TTS? *TTS service selection* (for now, later add the option to choose a specific voice with mega dropdowns) // *automatic translation: make an translation.js and add ALL the texts and have it translated if user chooses a language in top bar // *info page with credits, version and more info const languages = { - acehnese: { IETF: 'ace-ID', 'ISO-639': 'ace' }, - afrikaans: { IETF: 'af-ZA', 'ISO-639': 'af' }, - akan: { IETF: 'ak-GH', 'ISO-639': 'ak' }, - albanian: { IETF: 'sq-AL', 'ISO-639': 'sq' }, - amharic: { IETF: 'am-ET', 'ISO-639': 'am' }, - 'antigua and barbuda creole english': { IETF: 'aig-AG', 'ISO-639': 'aig' }, - arabic: { IETF: 'ar-SA', 'ISO-639': 'ar' }, - 'arabic egyptian': { IETF: 'ar-EG', 'ISO-639': 'ar' }, - aragonese: { IETF: 'an-ES', 'ISO-639': 'an' }, - armenian: { IETF: 'hy-AM', 'ISO-639': 'hy' }, - assamese: { IETF: 'as-IN', 'ISO-639': 'as' }, - asturian: { IETF: 'ast-ES', 'ISO-639': 'ast' }, - 'austrian german': { IETF: 'de-AT', 'ISO-639': 'de' }, - awadhi: { IETF: 'awa-IN', 'ISO-639': 'awa' }, - 'ayacucho quechua': { IETF: 'quy-PE', 'ISO-639': 'quy' }, - azerbaijani: { IETF: 'az-AZ', 'ISO-639': 'az' }, - 'bahamas creole english': { IETF: 'bah-BS', 'ISO-639': 'bah' }, - bajan: { IETF: 'bjs-BB', 'ISO-639': 'bjs' }, - balinese: { IETF: 'ban-ID', 'ISO-639': 'ban' }, - 'balkan gipsy': { IETF: 'rm-RO', 'ISO-639': 'rm' }, - bambara: { IETF: 'bm-ML', 'ISO-639': 'bm' }, - banjar: { IETF: 'bjn-ID', 'ISO-639': 'bjn' }, - bashkir: { IETF: 'ba-RU', 'ISO-639': 'ba' }, - basque: { IETF: 'eu-ES', 'ISO-639': 'eu' }, - belarusian: { IETF: 'be-BY', 'ISO-639': 'be' }, - 'belgian french': { IETF: 'fr-BE', 'ISO-639': 'fr' }, - bemba: { IETF: 'bem-ZM', 'ISO-639': 'bem' }, - bengali: { IETF: 'bn-IN', 'ISO-639': 'bn' }, - bhojpuri: { IETF: 'bho-IN', 'ISO-639': 'bho' }, - bihari: { IETF: 'bh-IN', 'ISO-639': 'bh' }, - bislama: { IETF: 'bi-VU', 'ISO-639': 'bi' }, - borana: { IETF: 'gax-KE', 'ISO-639': 'gax' }, - bosnian: { IETF: 'bs-BA', 'ISO-639': 'bs' }, - 'bosnian (cyrillic)': { IETF: 'bs-Cyrl-BA', 'ISO-639': 'bs' }, - breton: { IETF: 'br-FR', 'ISO-639': 'br' }, - buginese: { IETF: 'bug-ID', 'ISO-639': 'bug' }, - bulgarian: { IETF: 'bg-BG', 'ISO-639': 'bg' }, - burmese: { IETF: 'my-MM', 'ISO-639': 'my' }, - catalan: { IETF: 'ca-ES', 'ISO-639': 'ca' }, - 'catalan valencian': { IETF: 'cav-ES', 'ISO-639': 'cav' }, - cebuano: { IETF: 'ceb-PH', 'ISO-639': 'ceb' }, - 'central atlas tamazight': { IETF: 'tzm-MA', 'ISO-639': 'tzm' }, - 'central aymara': { IETF: 'ayr-BO', 'ISO-639': 'ayr' }, - 'central kanuri (latin script)': { IETF: 'knc-NG', 'ISO-639': 'knc' }, - 'chadian arabic': { IETF: 'shu-TD', 'ISO-639': 'shu' }, - chamorro: { IETF: 'ch-GU', 'ISO-639': 'ch' }, - cherokee: { IETF: 'chr-US', 'ISO-639': 'chr' }, - chhattisgarhi: { IETF: 'hne-IN', 'ISO-639': 'hne' }, - 'chinese simplified': { IETF: 'zh-CN', 'ISO-639': 'zh' }, - 'chinese trad. (hong kong)': { IETF: 'zh-HK', 'ISO-639': 'zh' }, - 'chinese traditional': { IETF: 'zh-TW', 'ISO-639': 'zh' }, - 'chinese traditional macau': { IETF: 'zh-MO', 'ISO-639': 'zh' }, - chittagonian: { IETF: 'ctg-BD', 'ISO-639': 'ctg' }, - chokwe: { IETF: 'cjk-AO', 'ISO-639': 'cjk' }, - 'classical greek': { IETF: 'grc-GR', 'ISO-639': 'grc' }, - 'comorian ngazidja': { IETF: 'zdj-KM', 'ISO-639': 'zdj' }, - coptic: { IETF: 'cop-EG', 'ISO-639': 'cop' }, - 'crimean tatar': { IETF: 'crh-RU', 'ISO-639': 'crh' }, - 'crioulo upper guinea': { IETF: 'pov-GW', 'ISO-639': 'pov' }, - croatian: { IETF: 'hr-HR', 'ISO-639': 'hr' }, - czech: { IETF: 'cs-CZ', 'ISO-639': 'cs' }, - danish: { IETF: 'da-DK', 'ISO-639': 'da' }, - dari: { IETF: 'prs-AF', 'ISO-639': 'prs' }, - dimli: { IETF: 'diq-TR', 'ISO-639': 'diq' }, - dutch: { IETF: 'nl-NL', 'ISO-639': 'nl' }, - dyula: { IETF: 'dyu-CI', 'ISO-639': 'dyu' }, - dzongkha: { IETF: 'dz-BT', 'ISO-639': 'dz' }, - 'eastern yiddish': { IETF: 'ydd-US', 'ISO-639': 'ydd' }, - emakhuwa: { IETF: 'vmw-MZ', 'ISO-639': 'vmw' }, - english: { IETF: 'en-GB', 'ISO-639': 'en' }, - 'english australia': { IETF: 'en-AU', 'ISO-639': 'en' }, - 'english canada': { IETF: 'en-CA', 'ISO-639': 'en' }, - 'english india': { IETF: 'en-IN', 'ISO-639': 'en' }, - 'english ireland': { IETF: 'en-IE', 'ISO-639': 'en' }, - 'english new zealand': { IETF: 'en-NZ', 'ISO-639': 'en' }, - 'english singapore': { IETF: 'en-SG', 'ISO-639': 'en' }, - 'english south africa': { IETF: 'en-ZA', 'ISO-639': 'en' }, - 'english us': { IETF: 'en-US', 'ISO-639': 'en' }, - esperanto: { IETF: 'eo-EU', 'ISO-639': 'eo' }, - estonian: { IETF: 'et-EE', 'ISO-639': 'et' }, - ewe: { IETF: 'ee-GH', 'ISO-639': 'ee' }, - fanagalo: { IETF: 'fn-FNG', 'ISO-639': 'fn' }, - faroese: { IETF: 'fo-FO', 'ISO-639': 'fo' }, - fijian: { IETF: 'fj-FJ', 'ISO-639': 'fj' }, - filipino: { IETF: 'fil-PH', 'ISO-639': 'fil' }, - finnish: { IETF: 'fi-FI', 'ISO-639': 'fi' }, - flemish: { IETF: 'nl-BE', 'ISO-639': 'nl' }, - fon: { IETF: 'fon-BJ', 'ISO-639': 'fon' }, - french: { IETF: 'fr-FR', 'ISO-639': 'fr' }, - 'french canada': { IETF: 'fr-CA', 'ISO-639': 'fr' }, - 'french swiss': { IETF: 'fr-CH', 'ISO-639': 'fr' }, - friulian: { IETF: 'fur-IT', 'ISO-639': 'fur' }, - fula: { IETF: 'ff-FUL', 'ISO-639': 'ff' }, - galician: { IETF: 'gl-ES', 'ISO-639': 'gl' }, - gamargu: { IETF: 'mfi-NG', 'ISO-639': 'mfi' }, - garo: { IETF: 'grt-IN', 'ISO-639': 'grt' }, - georgian: { IETF: 'ka-GE', 'ISO-639': 'ka' }, - german: { IETF: 'de-DE', 'ISO-639': 'de' }, - gilbertese: { IETF: 'gil-KI', 'ISO-639': 'gil' }, - glavda: { IETF: 'glw-NG', 'ISO-639': 'glw' }, - greek: { IETF: 'el-GR', 'ISO-639': 'el' }, - 'grenadian creole english': { IETF: 'gcl-GD', 'ISO-639': 'gcl' }, - guarani: { IETF: 'gn-PY', 'ISO-639': 'gn' }, - gujarati: { IETF: 'gu-IN', 'ISO-639': 'gu' }, - 'guyanese creole english': { IETF: 'gyn-GY', 'ISO-639': 'gyn' }, - 'haitian creole french': { IETF: 'ht-HT', 'ISO-639': 'ht' }, - 'halh mongolian': { IETF: 'khk-MN', 'ISO-639': 'khk' }, - hausa: { IETF: 'ha-NE', 'ISO-639': 'ha' }, - hawaiian: { IETF: 'haw-US', 'ISO-639': 'haw' }, - hebrew: { IETF: 'he-IL', 'ISO-639': 'he' }, - higi: { IETF: 'hig-NG', 'ISO-639': 'hig' }, - hiligaynon: { IETF: 'hil-PH', 'ISO-639': 'hil' }, - 'hill mari': { IETF: 'mrj-RU', 'ISO-639': 'mrj' }, - hindi: { IETF: 'hi-IN', 'ISO-639': 'hi' }, - hmong: { IETF: 'hmn-CN', 'ISO-639': 'hmn' }, - hungarian: { IETF: 'hu-HU', 'ISO-639': 'hu' }, - icelandic: { IETF: 'is-IS', 'ISO-639': 'is' }, - 'igbo ibo': { IETF: 'ibo-NG', 'ISO-639': 'ibo' }, - 'igbo ig': { IETF: 'ig-NG', 'ISO-639': 'ig' }, - ilocano: { IETF: 'ilo-PH', 'ISO-639': 'ilo' }, - indonesian: { IETF: 'id-ID', 'ISO-639': 'id' }, - 'inuktitut greenlandic': { IETF: 'kl-GL', 'ISO-639': 'kl' }, - 'irish gaelic': { IETF: 'ga-IE', 'ISO-639': 'ga' }, - italian: { IETF: 'it-IT', 'ISO-639': 'it' }, - 'italian swiss': { IETF: 'it-CH', 'ISO-639': 'it' }, - 'jamaican creole english': { IETF: 'jam-JM', 'ISO-639': 'jam' }, - japanese: { IETF: 'ja-JP', 'ISO-639': 'ja' }, - javanese: { IETF: 'jv-ID', 'ISO-639': 'jv' }, - jingpho: { IETF: 'kac-MM', 'ISO-639': 'kac' }, - "k'iche'": { IETF: 'quc-GT', 'ISO-639': 'quc' }, - 'kabiy�': { IETF: 'kbp-TG', 'ISO-639': 'kbp' }, - kabuverdianu: { IETF: 'kea-CV', 'ISO-639': 'kea' }, - kabylian: { IETF: 'kab-DZ', 'ISO-639': 'kab' }, - kalenjin: { IETF: 'kln-KE', 'ISO-639': 'kln' }, - kamba: { IETF: 'kam-KE', 'ISO-639': 'kam' }, - kannada: { IETF: 'kn-IN', 'ISO-639': 'kn' }, - kanuri: { IETF: 'kr-KAU', 'ISO-639': 'kr' }, - karen: { IETF: 'kar-MM', 'ISO-639': 'kar' }, - 'kashmiri (devanagari script)': { IETF: 'ks-IN', 'ISO-639': 'ks' }, - 'kashmiri (arabic script)': { IETF: 'kas-IN', 'ISO-639': 'kas' }, - kazakh: { IETF: 'kk-KZ', 'ISO-639': 'kk' }, - khasi: { IETF: 'kha-IN', 'ISO-639': 'kha' }, - khmer: { IETF: 'km-KH', 'ISO-639': 'km' }, - 'kikuyu kik': { IETF: 'kik-KE', 'ISO-639': 'kik' }, - 'kikuyu ki': { IETF: 'ki-KE', 'ISO-639': 'ki' }, - kimbundu: { IETF: 'kmb-AO', 'ISO-639': 'kmb' }, - kinyarwanda: { IETF: 'rw-RW', 'ISO-639': 'rw' }, - kirundi: { IETF: 'rn-BI', 'ISO-639': 'rn' }, - kisii: { IETF: 'guz-KE', 'ISO-639': 'guz' }, - kongo: { IETF: 'kg-CG', 'ISO-639': 'kg' }, - konkani: { IETF: 'kok-IN', 'ISO-639': 'kok' }, - korean: { IETF: 'ko-KR', 'ISO-639': 'ko' }, - 'northern kurdish': { IETF: 'kmr-TR', 'ISO-639': 'kmr' }, - 'kurdish sorani': { IETF: 'ckb-IQ', 'ISO-639': 'ckb' }, - kyrgyz: { IETF: 'ky-KG', 'ISO-639': 'ky' }, - lao: { IETF: 'lo-LA', 'ISO-639': 'lo' }, - latgalian: { IETF: 'ltg-LV', 'ISO-639': 'ltg' }, - latin: { IETF: 'la-XN', 'ISO-639': 'la' }, - latvian: { IETF: 'lv-LV', 'ISO-639': 'lv' }, - ligurian: { IETF: 'lij-IT', 'ISO-639': 'lij' }, - limburgish: { IETF: 'li-NL', 'ISO-639': 'li' }, - lingala: { IETF: 'ln-LIN', 'ISO-639': 'ln' }, - lithuanian: { IETF: 'lt-LT', 'ISO-639': 'lt' }, - lombard: { IETF: 'lmo-IT', 'ISO-639': 'lmo' }, - 'luba-kasai': { IETF: 'lua-CD', 'ISO-639': 'lua' }, - luganda: { IETF: 'lg-UG', 'ISO-639': 'lg' }, - luhya: { IETF: 'luy-KE', 'ISO-639': 'luy' }, - luo: { IETF: 'luo-KE', 'ISO-639': 'luo' }, - luxembourgish: { IETF: 'lb-LU', 'ISO-639': 'lb' }, - maa: { IETF: 'mas-KE', 'ISO-639': 'mas' }, - macedonian: { IETF: 'mk-MK', 'ISO-639': 'mk' }, - magahi: { IETF: 'mag-IN', 'ISO-639': 'mag' }, - maithili: { IETF: 'mai-IN', 'ISO-639': 'mai' }, - malagasy: { IETF: 'mg-MG', 'ISO-639': 'mg' }, - malay: { IETF: 'ms-MY', 'ISO-639': 'ms' }, - malayalam: { IETF: 'ml-IN', 'ISO-639': 'ml' }, - maldivian: { IETF: 'dv-MV', 'ISO-639': 'dv' }, - maltese: { IETF: 'mt-MT', 'ISO-639': 'mt' }, - mandara: { IETF: 'mfi-CM', 'ISO-639': 'mfi' }, - manipuri: { IETF: 'mni-IN', 'ISO-639': 'mni' }, - 'manx gaelic': { IETF: 'gv-IM', 'ISO-639': 'gv' }, - maori: { IETF: 'mi-NZ', 'ISO-639': 'mi' }, - marathi: { IETF: 'mr-IN', 'ISO-639': 'mr' }, - margi: { IETF: 'mrt-NG', 'ISO-639': 'mrt' }, - mari: { IETF: 'mhr-RU', 'ISO-639': 'mhr' }, - marshallese: { IETF: 'mh-MH', 'ISO-639': 'mh' }, - mende: { IETF: 'men-SL', 'ISO-639': 'men' }, - meru: { IETF: 'mer-KE', 'ISO-639': 'mer' }, - mijikenda: { IETF: 'nyf-KE', 'ISO-639': 'nyf' }, - minangkabau: { IETF: 'min-ID', 'ISO-639': 'min' }, - mizo: { IETF: 'lus-IN', 'ISO-639': 'lus' }, - mongolian: { IETF: 'mn-MN', 'ISO-639': 'mn' }, - montenegrin: { IETF: 'sr-ME', 'ISO-639': 'sr' }, - morisyen: { IETF: 'mfe-MU', 'ISO-639': 'mfe' }, - 'moroccan arabic': { IETF: 'ar-MA', 'ISO-639': 'ar' }, - mossi: { IETF: 'mos-BF', 'ISO-639': 'mos' }, - ndau: { IETF: 'ndc-MZ', 'ISO-639': 'ndc' }, - ndebele: { IETF: 'nr-ZA', 'ISO-639': 'nr' }, - nepali: { IETF: 'ne-NP', 'ISO-639': 'ne' }, - 'nigerian fulfulde': { IETF: 'fuv-NG', 'ISO-639': 'fuv' }, - niuean: { IETF: 'niu-NU', 'ISO-639': 'niu' }, - 'north azerbaijani': { IETF: 'azj-AZ', 'ISO-639': 'azj' }, - sesotho: { IETF: 'nso-ZA', 'ISO-639': 'nso' }, - 'northern uzbek': { IETF: 'uzn-UZ', 'ISO-639': 'uzn' }, - 'norwegian bokm�l': { IETF: 'nb-NO', 'ISO-639': 'nb' }, - 'norwegian nynorsk': { IETF: 'nn-NO', 'ISO-639': 'nn' }, - nuer: { IETF: 'nus-SS', 'ISO-639': 'nus' }, - nyanja: { IETF: 'ny-MW', 'ISO-639': 'ny' }, - occitan: { IETF: 'oc-FR', 'ISO-639': 'oc' }, - 'occitan aran': { IETF: 'oc-ES', 'ISO-639': 'oc' }, - odia: { IETF: 'or-IN', 'ISO-639': 'or' }, - oriya: { IETF: 'ory-IN', 'ISO-639': 'ory' }, - urdu: { IETF: 'ur-PK', 'ISO-639': 'ur' }, - palauan: { IETF: 'pau-PW', 'ISO-639': 'pau' }, - pali: { IETF: 'pi-IN', 'ISO-639': 'pi' }, - pangasinan: { IETF: 'pag-PH', 'ISO-639': 'pag' }, - papiamentu: { IETF: 'pap-CW', 'ISO-639': 'pap' }, - pashto: { IETF: 'ps-PK', 'ISO-639': 'ps' }, - persian: { IETF: 'fa-IR', 'ISO-639': 'fa' }, - pijin: { IETF: 'pis-SB', 'ISO-639': 'pis' }, - 'plateau malagasy': { IETF: 'plt-MG', 'ISO-639': 'plt' }, - polish: { IETF: 'pl-PL', 'ISO-639': 'pl' }, - portuguese: { IETF: 'pt-PT', 'ISO-639': 'pt' }, - 'portuguese brazil': { IETF: 'pt-BR', 'ISO-639': 'pt' }, - potawatomi: { IETF: 'pot-US', 'ISO-639': 'pot' }, - punjabi: { IETF: 'pa-IN', 'ISO-639': 'pa' }, - 'punjabi (pakistan)': { IETF: 'pnb-PK', 'ISO-639': 'pnb' }, - quechua: { IETF: 'qu-PE', 'ISO-639': 'qu' }, - rohingya: { IETF: 'rhg-MM', 'ISO-639': 'rhg' }, - rohingyalish: { IETF: 'rhl-MM', 'ISO-639': 'rhl' }, - romanian: { IETF: 'ro-RO', 'ISO-639': 'ro' }, - romansh: { IETF: 'roh-CH', 'ISO-639': 'roh' }, - rundi: { IETF: 'run-BI', 'ISO-639': 'run' }, - russian: { IETF: 'ru-RU', 'ISO-639': 'ru' }, - 'saint lucian creole french': { IETF: 'acf-LC', 'ISO-639': 'acf' }, - samoan: { IETF: 'sm-WS', 'ISO-639': 'sm' }, - sango: { IETF: 'sg-CF', 'ISO-639': 'sg' }, - sanskrit: { IETF: 'sa-IN', 'ISO-639': 'sa' }, - santali: { IETF: 'sat-IN', 'ISO-639': 'sat' }, - sardinian: { IETF: 'sc-IT', 'ISO-639': 'sc' }, - 'scots gaelic': { IETF: 'gd-GB', 'ISO-639': 'gd' }, - sena: { IETF: 'seh-ZW', 'ISO-639': 'seh' }, - 'serbian cyrillic': { IETF: 'sr-Cyrl-RS', 'ISO-639': 'sr' }, - 'serbian latin': { IETF: 'sr-Latn-RS', 'ISO-639': 'sr' }, - 'seselwa creole french': { IETF: 'crs-SC', 'ISO-639': 'crs' }, - 'setswana (south africa)': { IETF: 'tn-ZA', 'ISO-639': 'tn' }, - shan: { IETF: 'shn-MM', 'ISO-639': 'shn' }, - shona: { IETF: 'sn-ZW', 'ISO-639': 'sn' }, - sicilian: { IETF: 'scn-IT', 'ISO-639': 'scn' }, - silesian: { IETF: 'szl-PL', 'ISO-639': 'szl' }, - 'sindhi snd': { IETF: 'snd-PK', 'ISO-639': 'snd' }, - 'sindhi sd': { IETF: 'sd-PK', 'ISO-639': 'sd' }, - sinhala: { IETF: 'si-LK', 'ISO-639': 'si' }, - slovak: { IETF: 'sk-SK', 'ISO-639': 'sk' }, - slovenian: { IETF: 'sl-SI', 'ISO-639': 'sl' }, - somali: { IETF: 'so-SO', 'ISO-639': 'so' }, - 'sotho southern': { IETF: 'st-LS', 'ISO-639': 'st' }, - 'south azerbaijani': { IETF: 'azb-AZ', 'ISO-639': 'azb' }, - 'southern pashto': { IETF: 'pbt-PK', 'ISO-639': 'pbt' }, - 'southwestern dinka': { IETF: 'dik-SS', 'ISO-639': 'dik' }, - spanish: { IETF: 'es-ES', 'ISO-639': 'es' }, - 'spanish argentina': { IETF: 'es-AR', 'ISO-639': 'es' }, - 'spanish colombia': { IETF: 'es-CO', 'ISO-639': 'es' }, - 'spanish latin america': { IETF: 'es-419', 'ISO-639': 'es' }, - 'spanish mexico': { IETF: 'es-MX', 'ISO-639': 'es' }, - 'spanish united states': { IETF: 'es-US', 'ISO-639': 'es' }, - 'sranan tongo': { IETF: 'srn-SR', 'ISO-639': 'srn' }, - 'standard latvian': { IETF: 'lvs-LV', 'ISO-639': 'lvs' }, - 'standard malay': { IETF: 'zsm-MY', 'ISO-639': 'zsm' }, - sundanese: { IETF: 'su-ID', 'ISO-639': 'su' }, - swahili: { IETF: 'sw-KE', 'ISO-639': 'sw' }, - swati: { IETF: 'ss-SZ', 'ISO-639': 'ss' }, - swedish: { IETF: 'sv-SE', 'ISO-639': 'sv' }, - 'swiss german': { IETF: 'de-CH', 'ISO-639': 'de' }, - 'syriac (aramaic)': { IETF: 'syc-TR', 'ISO-639': 'syc' }, - tagalog: { IETF: 'tl-PH', 'ISO-639': 'tl' }, - tahitian: { IETF: 'ty-PF', 'ISO-639': 'ty' }, - tajik: { IETF: 'tg-TJ', 'ISO-639': 'tg' }, - 'tamashek (tuareg)': { IETF: 'tmh-DZ', 'ISO-639': 'tmh' }, - tamasheq: { IETF: 'taq-ML', 'ISO-639': 'taq' }, - 'tamil india': { IETF: 'ta-IN', 'ISO-639': 'ta' }, - 'tamil sri lanka': { IETF: 'ta-LK', 'ISO-639': 'ta' }, - taroko: { IETF: 'trv-TW', 'ISO-639': 'trv' }, - tatar: { IETF: 'tt-RU', 'ISO-639': 'tt' }, - telugu: { IETF: 'te-IN', 'ISO-639': 'te' }, - tetum: { IETF: 'tet-TL', 'ISO-639': 'tet' }, - thai: { IETF: 'th-TH', 'ISO-639': 'th' }, - tibetan: { IETF: 'bo-CN', 'ISO-639': 'bo' }, - tigrinya: { IETF: 'ti-ET', 'ISO-639': 'ti' }, - 'tok pisin': { IETF: 'tpi-PG', 'ISO-639': 'tpi' }, - tokelauan: { IETF: 'tkl-TK', 'ISO-639': 'tkl' }, - tongan: { IETF: 'to-TO', 'ISO-639': 'to' }, - 'tosk albanian': { IETF: 'als-AL', 'ISO-639': 'als' }, - tsonga: { IETF: 'ts-ZA', 'ISO-639': 'ts' }, - tswa: { IETF: 'tsc-MZ', 'ISO-639': 'tsc' }, - tswana: { IETF: 'tn-BW', 'ISO-639': 'tn' }, - tumbuka: { IETF: 'tum-MW', 'ISO-639': 'tum' }, - turkish: { IETF: 'tr-TR', 'ISO-639': 'tr' }, - turkmen: { IETF: 'tk-TM', 'ISO-639': 'tk' }, - tuvaluan: { IETF: 'tvl-TV', 'ISO-639': 'tvl' }, - twi: { IETF: 'tw-GH', 'ISO-639': 'tw' }, - udmurt: { IETF: 'udm-RU', 'ISO-639': 'udm' }, - ukrainian: { IETF: 'uk-UA', 'ISO-639': 'uk' }, - uma: { IETF: 'ppk-ID', 'ISO-639': 'ppk' }, - umbundu: { IETF: 'umb-AO', 'ISO-639': 'umb' }, - 'uyghur uig': { IETF: 'uig-CN', 'ISO-639': 'uig' }, - 'uyghur ug': { IETF: 'ug-CN', 'ISO-639': 'ug' }, - uzbek: { IETF: 'uz-UZ', 'ISO-639': 'uz' }, - venetian: { IETF: 'vec-IT', 'ISO-639': 'vec' }, - vietnamese: { IETF: 'vi-VN', 'ISO-639': 'vi' }, - 'vincentian creole english': { IETF: 'svc-VC', 'ISO-639': 'svc' }, - 'virgin islands creole english': { IETF: 'vic-US', 'ISO-639': 'vic' }, - wallisian: { IETF: 'wls-WF', 'ISO-639': 'wls' }, - 'waray (philippines)': { IETF: 'war-PH', 'ISO-639': 'war' }, - welsh: { IETF: 'cy-GB', 'ISO-639': 'cy' }, - 'west central oromo': { IETF: 'gaz-ET', 'ISO-639': 'gaz' }, - 'western persian': { IETF: 'pes-IR', 'ISO-639': 'pes' }, - wolof: { IETF: 'wo-SN', 'ISO-639': 'wo' }, - xhosa: { IETF: 'xh-ZA', 'ISO-639': 'xh' }, - yiddish: { IETF: 'yi-YD', 'ISO-639': 'yi' }, - yoruba: { IETF: 'yo-NG', 'ISO-639': 'yo' }, - zulu: { IETF: 'zu-ZA', 'ISO-639': 'zu' }, + none: { IETF: 'none', 'ISO-639': 'none' }, + acehnese: { IETF: 'ace-ID', 'ISO-639': 'ace' }, + afrikaans: { IETF: 'af-ZA', 'ISO-639': 'af' }, + akan: { IETF: 'ak-GH', 'ISO-639': 'ak' }, + albanian: { IETF: 'sq-AL', 'ISO-639': 'sq' }, + amharic: { IETF: 'am-ET', 'ISO-639': 'am' }, + 'antigua and barbuda creole english': { IETF: 'aig-AG', 'ISO-639': 'aig' }, + arabic: { IETF: 'ar-SA', 'ISO-639': 'ar' }, + 'arabic egyptian': { IETF: 'ar-EG', 'ISO-639': 'ar' }, + aragonese: { IETF: 'an-ES', 'ISO-639': 'an' }, + armenian: { IETF: 'hy-AM', 'ISO-639': 'hy' }, + assamese: { IETF: 'as-IN', 'ISO-639': 'as' }, + asturian: { IETF: 'ast-ES', 'ISO-639': 'ast' }, + 'austrian german': { IETF: 'de-AT', 'ISO-639': 'de' }, + awadhi: { IETF: 'awa-IN', 'ISO-639': 'awa' }, + 'ayacucho quechua': { IETF: 'quy-PE', 'ISO-639': 'quy' }, + azerbaijani: { IETF: 'az-AZ', 'ISO-639': 'az' }, + 'bahamas creole english': { IETF: 'bah-BS', 'ISO-639': 'bah' }, + bajan: { IETF: 'bjs-BB', 'ISO-639': 'bjs' }, + balinese: { IETF: 'ban-ID', 'ISO-639': 'ban' }, + 'balkan gipsy': { IETF: 'rm-RO', 'ISO-639': 'rm' }, + bambara: { IETF: 'bm-ML', 'ISO-639': 'bm' }, + banjar: { IETF: 'bjn-ID', 'ISO-639': 'bjn' }, + bashkir: { IETF: 'ba-RU', 'ISO-639': 'ba' }, + basque: { IETF: 'eu-ES', 'ISO-639': 'eu' }, + belarusian: { IETF: 'be-BY', 'ISO-639': 'be' }, + 'belgian french': { IETF: 'fr-BE', 'ISO-639': 'fr' }, + bemba: { IETF: 'bem-ZM', 'ISO-639': 'bem' }, + bengali: { IETF: 'bn-IN', 'ISO-639': 'bn' }, + bhojpuri: { IETF: 'bho-IN', 'ISO-639': 'bho' }, + bihari: { IETF: 'bh-IN', 'ISO-639': 'bh' }, + bislama: { IETF: 'bi-VU', 'ISO-639': 'bi' }, + borana: { IETF: 'gax-KE', 'ISO-639': 'gax' }, + bosnian: { IETF: 'bs-BA', 'ISO-639': 'bs' }, + 'bosnian (cyrillic)': { IETF: 'bs-Cyrl-BA', 'ISO-639': 'bs' }, + breton: { IETF: 'br-FR', 'ISO-639': 'br' }, + buginese: { IETF: 'bug-ID', 'ISO-639': 'bug' }, + bulgarian: { IETF: 'bg-BG', 'ISO-639': 'bg' }, + burmese: { IETF: 'my-MM', 'ISO-639': 'my' }, + catalan: { IETF: 'ca-ES', 'ISO-639': 'ca' }, + 'catalan valencian': { IETF: 'cav-ES', 'ISO-639': 'cav' }, + cebuano: { IETF: 'ceb-PH', 'ISO-639': 'ceb' }, + 'central atlas tamazight': { IETF: 'tzm-MA', 'ISO-639': 'tzm' }, + 'central aymara': { IETF: 'ayr-BO', 'ISO-639': 'ayr' }, + 'central kanuri (latin script)': { IETF: 'knc-NG', 'ISO-639': 'knc' }, + 'chadian arabic': { IETF: 'shu-TD', 'ISO-639': 'shu' }, + chamorro: { IETF: 'ch-GU', 'ISO-639': 'ch' }, + cherokee: { IETF: 'chr-US', 'ISO-639': 'chr' }, + chhattisgarhi: { IETF: 'hne-IN', 'ISO-639': 'hne' }, + 'chinese simplified': { IETF: 'zh-CN', 'ISO-639': 'zh' }, + 'chinese trad. (hong kong)': { IETF: 'zh-HK', 'ISO-639': 'zh' }, + 'chinese traditional': { IETF: 'zh-TW', 'ISO-639': 'zh' }, + 'chinese traditional macau': { IETF: 'zh-MO', 'ISO-639': 'zh' }, + chittagonian: { IETF: 'ctg-BD', 'ISO-639': 'ctg' }, + chokwe: { IETF: 'cjk-AO', 'ISO-639': 'cjk' }, + 'classical greek': { IETF: 'grc-GR', 'ISO-639': 'grc' }, + 'comorian ngazidja': { IETF: 'zdj-KM', 'ISO-639': 'zdj' }, + coptic: { IETF: 'cop-EG', 'ISO-639': 'cop' }, + 'crimean tatar': { IETF: 'crh-RU', 'ISO-639': 'crh' }, + 'crioulo upper guinea': { IETF: 'pov-GW', 'ISO-639': 'pov' }, + croatian: { IETF: 'hr-HR', 'ISO-639': 'hr' }, + czech: { IETF: 'cs-CZ', 'ISO-639': 'cs' }, + danish: { IETF: 'da-DK', 'ISO-639': 'da' }, + dari: { IETF: 'prs-AF', 'ISO-639': 'prs' }, + dimli: { IETF: 'diq-TR', 'ISO-639': 'diq' }, + dutch: { IETF: 'nl-NL', 'ISO-639': 'nl' }, + dyula: { IETF: 'dyu-CI', 'ISO-639': 'dyu' }, + dzongkha: { IETF: 'dz-BT', 'ISO-639': 'dz' }, + 'eastern yiddish': { IETF: 'ydd-US', 'ISO-639': 'ydd' }, + emakhuwa: { IETF: 'vmw-MZ', 'ISO-639': 'vmw' }, + english: { IETF: 'en-GB', 'ISO-639': 'en' }, + 'english australia': { IETF: 'en-AU', 'ISO-639': 'en' }, + 'english canada': { IETF: 'en-CA', 'ISO-639': 'en' }, + 'english india': { IETF: 'en-IN', 'ISO-639': 'en' }, + 'english ireland': { IETF: 'en-IE', 'ISO-639': 'en' }, + 'english new zealand': { IETF: 'en-NZ', 'ISO-639': 'en' }, + 'english singapore': { IETF: 'en-SG', 'ISO-639': 'en' }, + 'english south africa': { IETF: 'en-ZA', 'ISO-639': 'en' }, + 'english us': { IETF: 'en-US', 'ISO-639': 'en' }, + esperanto: { IETF: 'eo-EU', 'ISO-639': 'eo' }, + estonian: { IETF: 'et-EE', 'ISO-639': 'et' }, + ewe: { IETF: 'ee-GH', 'ISO-639': 'ee' }, + fanagalo: { IETF: 'fn-FNG', 'ISO-639': 'fn' }, + faroese: { IETF: 'fo-FO', 'ISO-639': 'fo' }, + fijian: { IETF: 'fj-FJ', 'ISO-639': 'fj' }, + filipino: { IETF: 'fil-PH', 'ISO-639': 'fil' }, + finnish: { IETF: 'fi-FI', 'ISO-639': 'fi' }, + flemish: { IETF: 'nl-BE', 'ISO-639': 'nl' }, + fon: { IETF: 'fon-BJ', 'ISO-639': 'fon' }, + french: { IETF: 'fr-FR', 'ISO-639': 'fr' }, + 'french canada': { IETF: 'fr-CA', 'ISO-639': 'fr' }, + 'french swiss': { IETF: 'fr-CH', 'ISO-639': 'fr' }, + friulian: { IETF: 'fur-IT', 'ISO-639': 'fur' }, + fula: { IETF: 'ff-FUL', 'ISO-639': 'ff' }, + galician: { IETF: 'gl-ES', 'ISO-639': 'gl' }, + gamargu: { IETF: 'mfi-NG', 'ISO-639': 'mfi' }, + garo: { IETF: 'grt-IN', 'ISO-639': 'grt' }, + georgian: { IETF: 'ka-GE', 'ISO-639': 'ka' }, + german: { IETF: 'de-DE', 'ISO-639': 'de' }, + gilbertese: { IETF: 'gil-KI', 'ISO-639': 'gil' }, + glavda: { IETF: 'glw-NG', 'ISO-639': 'glw' }, + greek: { IETF: 'el-GR', 'ISO-639': 'el' }, + 'grenadian creole english': { IETF: 'gcl-GD', 'ISO-639': 'gcl' }, + guarani: { IETF: 'gn-PY', 'ISO-639': 'gn' }, + gujarati: { IETF: 'gu-IN', 'ISO-639': 'gu' }, + 'guyanese creole english': { IETF: 'gyn-GY', 'ISO-639': 'gyn' }, + 'haitian creole french': { IETF: 'ht-HT', 'ISO-639': 'ht' }, + 'halh mongolian': { IETF: 'khk-MN', 'ISO-639': 'khk' }, + hausa: { IETF: 'ha-NE', 'ISO-639': 'ha' }, + hawaiian: { IETF: 'haw-US', 'ISO-639': 'haw' }, + hebrew: { IETF: 'he-IL', 'ISO-639': 'he' }, + higi: { IETF: 'hig-NG', 'ISO-639': 'hig' }, + hiligaynon: { IETF: 'hil-PH', 'ISO-639': 'hil' }, + 'hill mari': { IETF: 'mrj-RU', 'ISO-639': 'mrj' }, + hindi: { IETF: 'hi-IN', 'ISO-639': 'hi' }, + hmong: { IETF: 'hmn-CN', 'ISO-639': 'hmn' }, + hungarian: { IETF: 'hu-HU', 'ISO-639': 'hu' }, + icelandic: { IETF: 'is-IS', 'ISO-639': 'is' }, + 'igbo ibo': { IETF: 'ibo-NG', 'ISO-639': 'ibo' }, + 'igbo ig': { IETF: 'ig-NG', 'ISO-639': 'ig' }, + ilocano: { IETF: 'ilo-PH', 'ISO-639': 'ilo' }, + indonesian: { IETF: 'id-ID', 'ISO-639': 'id' }, + 'inuktitut greenlandic': { IETF: 'kl-GL', 'ISO-639': 'kl' }, + 'irish gaelic': { IETF: 'ga-IE', 'ISO-639': 'ga' }, + italian: { IETF: 'it-IT', 'ISO-639': 'it' }, + 'italian swiss': { IETF: 'it-CH', 'ISO-639': 'it' }, + 'jamaican creole english': { IETF: 'jam-JM', 'ISO-639': 'jam' }, + japanese: { IETF: 'ja-JP', 'ISO-639': 'ja' }, + javanese: { IETF: 'jv-ID', 'ISO-639': 'jv' }, + jingpho: { IETF: 'kac-MM', 'ISO-639': 'kac' }, + "k'iche'": { IETF: 'quc-GT', 'ISO-639': 'quc' }, + 'kabiy�': { IETF: 'kbp-TG', 'ISO-639': 'kbp' }, + kabuverdianu: { IETF: 'kea-CV', 'ISO-639': 'kea' }, + kabylian: { IETF: 'kab-DZ', 'ISO-639': 'kab' }, + kalenjin: { IETF: 'kln-KE', 'ISO-639': 'kln' }, + kamba: { IETF: 'kam-KE', 'ISO-639': 'kam' }, + kannada: { IETF: 'kn-IN', 'ISO-639': 'kn' }, + kanuri: { IETF: 'kr-KAU', 'ISO-639': 'kr' }, + karen: { IETF: 'kar-MM', 'ISO-639': 'kar' }, + 'kashmiri (devanagari script)': { IETF: 'ks-IN', 'ISO-639': 'ks' }, + 'kashmiri (arabic script)': { IETF: 'kas-IN', 'ISO-639': 'kas' }, + kazakh: { IETF: 'kk-KZ', 'ISO-639': 'kk' }, + khasi: { IETF: 'kha-IN', 'ISO-639': 'kha' }, + khmer: { IETF: 'km-KH', 'ISO-639': 'km' }, + 'kikuyu kik': { IETF: 'kik-KE', 'ISO-639': 'kik' }, + 'kikuyu ki': { IETF: 'ki-KE', 'ISO-639': 'ki' }, + kimbundu: { IETF: 'kmb-AO', 'ISO-639': 'kmb' }, + kinyarwanda: { IETF: 'rw-RW', 'ISO-639': 'rw' }, + kirundi: { IETF: 'rn-BI', 'ISO-639': 'rn' }, + kisii: { IETF: 'guz-KE', 'ISO-639': 'guz' }, + kongo: { IETF: 'kg-CG', 'ISO-639': 'kg' }, + konkani: { IETF: 'kok-IN', 'ISO-639': 'kok' }, + korean: { IETF: 'ko-KR', 'ISO-639': 'ko' }, + 'northern kurdish': { IETF: 'kmr-TR', 'ISO-639': 'kmr' }, + 'kurdish sorani': { IETF: 'ckb-IQ', 'ISO-639': 'ckb' }, + kyrgyz: { IETF: 'ky-KG', 'ISO-639': 'ky' }, + lao: { IETF: 'lo-LA', 'ISO-639': 'lo' }, + latgalian: { IETF: 'ltg-LV', 'ISO-639': 'ltg' }, + latin: { IETF: 'la-XN', 'ISO-639': 'la' }, + latvian: { IETF: 'lv-LV', 'ISO-639': 'lv' }, + ligurian: { IETF: 'lij-IT', 'ISO-639': 'lij' }, + limburgish: { IETF: 'li-NL', 'ISO-639': 'li' }, + lingala: { IETF: 'ln-LIN', 'ISO-639': 'ln' }, + lithuanian: { IETF: 'lt-LT', 'ISO-639': 'lt' }, + lombard: { IETF: 'lmo-IT', 'ISO-639': 'lmo' }, + 'luba-kasai': { IETF: 'lua-CD', 'ISO-639': 'lua' }, + luganda: { IETF: 'lg-UG', 'ISO-639': 'lg' }, + luhya: { IETF: 'luy-KE', 'ISO-639': 'luy' }, + luo: { IETF: 'luo-KE', 'ISO-639': 'luo' }, + luxembourgish: { IETF: 'lb-LU', 'ISO-639': 'lb' }, + maa: { IETF: 'mas-KE', 'ISO-639': 'mas' }, + macedonian: { IETF: 'mk-MK', 'ISO-639': 'mk' }, + magahi: { IETF: 'mag-IN', 'ISO-639': 'mag' }, + maithili: { IETF: 'mai-IN', 'ISO-639': 'mai' }, + malagasy: { IETF: 'mg-MG', 'ISO-639': 'mg' }, + malay: { IETF: 'ms-MY', 'ISO-639': 'ms' }, + malayalam: { IETF: 'ml-IN', 'ISO-639': 'ml' }, + maldivian: { IETF: 'dv-MV', 'ISO-639': 'dv' }, + maltese: { IETF: 'mt-MT', 'ISO-639': 'mt' }, + mandara: { IETF: 'mfi-CM', 'ISO-639': 'mfi' }, + manipuri: { IETF: 'mni-IN', 'ISO-639': 'mni' }, + 'manx gaelic': { IETF: 'gv-IM', 'ISO-639': 'gv' }, + maori: { IETF: 'mi-NZ', 'ISO-639': 'mi' }, + marathi: { IETF: 'mr-IN', 'ISO-639': 'mr' }, + margi: { IETF: 'mrt-NG', 'ISO-639': 'mrt' }, + mari: { IETF: 'mhr-RU', 'ISO-639': 'mhr' }, + marshallese: { IETF: 'mh-MH', 'ISO-639': 'mh' }, + mende: { IETF: 'men-SL', 'ISO-639': 'men' }, + meru: { IETF: 'mer-KE', 'ISO-639': 'mer' }, + mijikenda: { IETF: 'nyf-KE', 'ISO-639': 'nyf' }, + minangkabau: { IETF: 'min-ID', 'ISO-639': 'min' }, + mizo: { IETF: 'lus-IN', 'ISO-639': 'lus' }, + mongolian: { IETF: 'mn-MN', 'ISO-639': 'mn' }, + montenegrin: { IETF: 'sr-ME', 'ISO-639': 'sr' }, + morisyen: { IETF: 'mfe-MU', 'ISO-639': 'mfe' }, + 'moroccan arabic': { IETF: 'ar-MA', 'ISO-639': 'ar' }, + mossi: { IETF: 'mos-BF', 'ISO-639': 'mos' }, + ndau: { IETF: 'ndc-MZ', 'ISO-639': 'ndc' }, + ndebele: { IETF: 'nr-ZA', 'ISO-639': 'nr' }, + nepali: { IETF: 'ne-NP', 'ISO-639': 'ne' }, + 'nigerian fulfulde': { IETF: 'fuv-NG', 'ISO-639': 'fuv' }, + niuean: { IETF: 'niu-NU', 'ISO-639': 'niu' }, + 'north azerbaijani': { IETF: 'azj-AZ', 'ISO-639': 'azj' }, + sesotho: { IETF: 'nso-ZA', 'ISO-639': 'nso' }, + 'northern uzbek': { IETF: 'uzn-UZ', 'ISO-639': 'uzn' }, + 'norwegian bokm�l': { IETF: 'nb-NO', 'ISO-639': 'nb' }, + 'norwegian nynorsk': { IETF: 'nn-NO', 'ISO-639': 'nn' }, + nuer: { IETF: 'nus-SS', 'ISO-639': 'nus' }, + nyanja: { IETF: 'ny-MW', 'ISO-639': 'ny' }, + occitan: { IETF: 'oc-FR', 'ISO-639': 'oc' }, + 'occitan aran': { IETF: 'oc-ES', 'ISO-639': 'oc' }, + odia: { IETF: 'or-IN', 'ISO-639': 'or' }, + oriya: { IETF: 'ory-IN', 'ISO-639': 'ory' }, + urdu: { IETF: 'ur-PK', 'ISO-639': 'ur' }, + palauan: { IETF: 'pau-PW', 'ISO-639': 'pau' }, + pali: { IETF: 'pi-IN', 'ISO-639': 'pi' }, + pangasinan: { IETF: 'pag-PH', 'ISO-639': 'pag' }, + papiamentu: { IETF: 'pap-CW', 'ISO-639': 'pap' }, + pashto: { IETF: 'ps-PK', 'ISO-639': 'ps' }, + persian: { IETF: 'fa-IR', 'ISO-639': 'fa' }, + pijin: { IETF: 'pis-SB', 'ISO-639': 'pis' }, + 'plateau malagasy': { IETF: 'plt-MG', 'ISO-639': 'plt' }, + polish: { IETF: 'pl-PL', 'ISO-639': 'pl' }, + portuguese: { IETF: 'pt-PT', 'ISO-639': 'pt' }, + 'portuguese brazil': { IETF: 'pt-BR', 'ISO-639': 'pt' }, + potawatomi: { IETF: 'pot-US', 'ISO-639': 'pot' }, + punjabi: { IETF: 'pa-IN', 'ISO-639': 'pa' }, + 'punjabi (pakistan)': { IETF: 'pnb-PK', 'ISO-639': 'pnb' }, + quechua: { IETF: 'qu-PE', 'ISO-639': 'qu' }, + rohingya: { IETF: 'rhg-MM', 'ISO-639': 'rhg' }, + rohingyalish: { IETF: 'rhl-MM', 'ISO-639': 'rhl' }, + romanian: { IETF: 'ro-RO', 'ISO-639': 'ro' }, + romansh: { IETF: 'roh-CH', 'ISO-639': 'roh' }, + rundi: { IETF: 'run-BI', 'ISO-639': 'run' }, + russian: { IETF: 'ru-RU', 'ISO-639': 'ru' }, + 'saint lucian creole french': { IETF: 'acf-LC', 'ISO-639': 'acf' }, + samoan: { IETF: 'sm-WS', 'ISO-639': 'sm' }, + sango: { IETF: 'sg-CF', 'ISO-639': 'sg' }, + sanskrit: { IETF: 'sa-IN', 'ISO-639': 'sa' }, + santali: { IETF: 'sat-IN', 'ISO-639': 'sat' }, + sardinian: { IETF: 'sc-IT', 'ISO-639': 'sc' }, + 'scots gaelic': { IETF: 'gd-GB', 'ISO-639': 'gd' }, + sena: { IETF: 'seh-ZW', 'ISO-639': 'seh' }, + 'serbian cyrillic': { IETF: 'sr-Cyrl-RS', 'ISO-639': 'sr' }, + 'serbian latin': { IETF: 'sr-Latn-RS', 'ISO-639': 'sr' }, + 'seselwa creole french': { IETF: 'crs-SC', 'ISO-639': 'crs' }, + 'setswana (south africa)': { IETF: 'tn-ZA', 'ISO-639': 'tn' }, + shan: { IETF: 'shn-MM', 'ISO-639': 'shn' }, + shona: { IETF: 'sn-ZW', 'ISO-639': 'sn' }, + sicilian: { IETF: 'scn-IT', 'ISO-639': 'scn' }, + silesian: { IETF: 'szl-PL', 'ISO-639': 'szl' }, + 'sindhi snd': { IETF: 'snd-PK', 'ISO-639': 'snd' }, + 'sindhi sd': { IETF: 'sd-PK', 'ISO-639': 'sd' }, + sinhala: { IETF: 'si-LK', 'ISO-639': 'si' }, + slovak: { IETF: 'sk-SK', 'ISO-639': 'sk' }, + slovenian: { IETF: 'sl-SI', 'ISO-639': 'sl' }, + somali: { IETF: 'so-SO', 'ISO-639': 'so' }, + 'sotho southern': { IETF: 'st-LS', 'ISO-639': 'st' }, + 'south azerbaijani': { IETF: 'azb-AZ', 'ISO-639': 'azb' }, + 'southern pashto': { IETF: 'pbt-PK', 'ISO-639': 'pbt' }, + 'southwestern dinka': { IETF: 'dik-SS', 'ISO-639': 'dik' }, + spanish: { IETF: 'es-ES', 'ISO-639': 'es' }, + 'spanish argentina': { IETF: 'es-AR', 'ISO-639': 'es' }, + 'spanish colombia': { IETF: 'es-CO', 'ISO-639': 'es' }, + 'spanish latin america': { IETF: 'es-419', 'ISO-639': 'es' }, + 'spanish mexico': { IETF: 'es-MX', 'ISO-639': 'es' }, + 'spanish united states': { IETF: 'es-US', 'ISO-639': 'es' }, + 'sranan tongo': { IETF: 'srn-SR', 'ISO-639': 'srn' }, + 'standard latvian': { IETF: 'lvs-LV', 'ISO-639': 'lvs' }, + 'standard malay': { IETF: 'zsm-MY', 'ISO-639': 'zsm' }, + sundanese: { IETF: 'su-ID', 'ISO-639': 'su' }, + swahili: { IETF: 'sw-KE', 'ISO-639': 'sw' }, + swati: { IETF: 'ss-SZ', 'ISO-639': 'ss' }, + swedish: { IETF: 'sv-SE', 'ISO-639': 'sv' }, + 'swiss german': { IETF: 'de-CH', 'ISO-639': 'de' }, + 'syriac (aramaic)': { IETF: 'syc-TR', 'ISO-639': 'syc' }, + tagalog: { IETF: 'tl-PH', 'ISO-639': 'tl' }, + tahitian: { IETF: 'ty-PF', 'ISO-639': 'ty' }, + tajik: { IETF: 'tg-TJ', 'ISO-639': 'tg' }, + 'tamashek (tuareg)': { IETF: 'tmh-DZ', 'ISO-639': 'tmh' }, + tamasheq: { IETF: 'taq-ML', 'ISO-639': 'taq' }, + 'tamil india': { IETF: 'ta-IN', 'ISO-639': 'ta' }, + 'tamil sri lanka': { IETF: 'ta-LK', 'ISO-639': 'ta' }, + taroko: { IETF: 'trv-TW', 'ISO-639': 'trv' }, + tatar: { IETF: 'tt-RU', 'ISO-639': 'tt' }, + telugu: { IETF: 'te-IN', 'ISO-639': 'te' }, + tetum: { IETF: 'tet-TL', 'ISO-639': 'tet' }, + thai: { IETF: 'th-TH', 'ISO-639': 'th' }, + tibetan: { IETF: 'bo-CN', 'ISO-639': 'bo' }, + tigrinya: { IETF: 'ti-ET', 'ISO-639': 'ti' }, + 'tok pisin': { IETF: 'tpi-PG', 'ISO-639': 'tpi' }, + tokelauan: { IETF: 'tkl-TK', 'ISO-639': 'tkl' }, + tongan: { IETF: 'to-TO', 'ISO-639': 'to' }, + 'tosk albanian': { IETF: 'als-AL', 'ISO-639': 'als' }, + tsonga: { IETF: 'ts-ZA', 'ISO-639': 'ts' }, + tswa: { IETF: 'tsc-MZ', 'ISO-639': 'tsc' }, + tswana: { IETF: 'tn-BW', 'ISO-639': 'tn' }, + tumbuka: { IETF: 'tum-MW', 'ISO-639': 'tum' }, + turkish: { IETF: 'tr-TR', 'ISO-639': 'tr' }, + turkmen: { IETF: 'tk-TM', 'ISO-639': 'tk' }, + tuvaluan: { IETF: 'tvl-TV', 'ISO-639': 'tvl' }, + twi: { IETF: 'tw-GH', 'ISO-639': 'tw' }, + udmurt: { IETF: 'udm-RU', 'ISO-639': 'udm' }, + ukrainian: { IETF: 'uk-UA', 'ISO-639': 'uk' }, + uma: { IETF: 'ppk-ID', 'ISO-639': 'ppk' }, + umbundu: { IETF: 'umb-AO', 'ISO-639': 'umb' }, + 'uyghur uig': { IETF: 'uig-CN', 'ISO-639': 'uig' }, + 'uyghur ug': { IETF: 'ug-CN', 'ISO-639': 'ug' }, + uzbek: { IETF: 'uz-UZ', 'ISO-639': 'uz' }, + venetian: { IETF: 'vec-IT', 'ISO-639': 'vec' }, + vietnamese: { IETF: 'vi-VN', 'ISO-639': 'vi' }, + 'vincentian creole english': { IETF: 'svc-VC', 'ISO-639': 'svc' }, + 'virgin islands creole english': { IETF: 'vic-US', 'ISO-639': 'vic' }, + wallisian: { IETF: 'wls-WF', 'ISO-639': 'wls' }, + 'waray (philippines)': { IETF: 'war-PH', 'ISO-639': 'war' }, + welsh: { IETF: 'cy-GB', 'ISO-639': 'cy' }, + 'west central oromo': { IETF: 'gaz-ET', 'ISO-639': 'gaz' }, + 'western persian': { IETF: 'pes-IR', 'ISO-639': 'pes' }, + wolof: { IETF: 'wo-SN', 'ISO-639': 'wo' }, + xhosa: { IETF: 'xh-ZA', 'ISO-639': 'xh' }, + yiddish: { IETF: 'yi-YD', 'ISO-639': 'yi' }, + yoruba: { IETF: 'yo-NG', 'ISO-639': 'yo' }, + zulu: { IETF: 'zu-ZA', 'ISO-639': 'zu' } }; module.exports = { languages }; diff --git a/src/js/logger.js b/src/js/logger.js index d7ea220..60bc0de 100644 --- a/src/js/logger.js +++ b/src/js/logger.js @@ -6,73 +6,75 @@ const path = require('path'); const consoleloggerLevel = process.env.WINSTON_LOGGER_LEVEL || 'info'; const consoleFormat = format.combine( - format.colorize(), - format.timestamp(), - format.align(), - format.printf((info) => `${info.timestamp} - ${info.level}: ${info.message} ${JSON.stringify(info.metadata)}`), + format.colorize(), + format.timestamp(), + format.align(), + format.printf(info => `${info.timestamp} - ${info.level}: ${info.message} ${JSON.stringify(info.metadata)}`) ); const fileFormat = format.combine( - format.timestamp(), - format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }), - format.json(), + format.timestamp(), + format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }), + format.json() ); const logger = createLogger({ - level: 'info', - format: fileFormat, - transports: [ - new transports.File({ - filename: path.join(__dirname, '../logs/error.log'), - level: 'error', - }), - new transports.File({ - filename: path.join(__dirname, '../logs/activity.log'), - maxsize: 5242880, - maxFiles: 5, - }), - ], + level: 'info', + format: fileFormat, + transports: [ + new transports.File({ + filename: path.join(__dirname, '../logs/error.log'), + level: 'error' + }), + new transports.File({ + filename: path.join(__dirname, '../logs/activity.log'), + maxsize: 5242880, + maxFiles: 5 + }) + ] }); if (process.env.NODE_ENV !== 'production') { - logger.add( - new transports.Console({ - level: consoleloggerLevel, - format: consoleFormat, - }), - ); + logger.add( + new transports.Console({ + level: consoleloggerLevel, + format: consoleFormat + }) + ); } fetch(path.join(__dirname, '../logs/activity.log')) - .then((response) => response.text()) - .then((logData) => { - const logLines = logData.trim().split('\n'); - const tableBody = document.getElementById('logContent'); + .then(response => response.text()) + .then(logData => { + const logLines = logData.trim().split('\n'); + const tableBody = document.getElementById('logContent'); - logLines.forEach((logLine) => { - const logObject = JSON.parse(logLine); - const row = document.createElement('tr'); + logLines.forEach(logLine => { + const logObject = JSON.parse(logLine); + const row = document.createElement('tr'); - const levelCell = document.createElement('td'); - levelCell.textContent = logObject.level; - levelCell.classList.add(logObject.level); // Add class for styling - row.appendChild(levelCell); + const levelCell = document.createElement('td'); + levelCell.textContent = logObject.level; + levelCell.classList.add(logObject.level); // Add class for styling + row.appendChild(levelCell); - const messageCell = document.createElement('td'); - messageCell.textContent = logObject.message; - row.appendChild(messageCell); + const messageCell = document.createElement('td'); + messageCell.textContent = logObject.message; + row.appendChild(messageCell); - const metadataCell = document.createElement('td'); - metadataCell.textContent = JSON.stringify(logObject.metadata, null, 2); - row.appendChild(metadataCell); + const metadataCell = document.createElement('td'); + metadataCell.textContent = JSON.stringify(logObject.metadata, null, 2); + row.appendChild(metadataCell); - const timestampCell = document.createElement('td'); - timestampCell.textContent = logObject.timestamp; - row.appendChild(timestampCell); + const timestampCell = document.createElement('td'); + timestampCell.textContent = logObject.timestamp; + row.appendChild(timestampCell); - tableBody.appendChild(row); - }); - }) - .catch((error) => {}); + tableBody.appendChild(row); + }); + }) + .catch(error => { + console.error(error); + }); module.exports = logger; diff --git a/src/js/mediaDevices.js b/src/js/mediaDevices.js index ee21c35..d2a1ef8 100644 --- a/src/js/mediaDevices.js +++ b/src/js/mediaDevices.js @@ -1,49 +1,51 @@ -let micSelect = document.querySelector('#microphone'); +/* global settings, */ + +const micSelect = document.querySelector('#microphone'); let selectedMic; function getAvailableMediaDevices(type) { - return new Promise((resolve, reject) => { - navigator.mediaDevices - .enumerateDevices() - .then((devices) => { - const microphones = devices.filter((device) => device.kind === type); - resolve(microphones); - }) - .catch((error) => { - reject(error); - }); - }); + return new Promise((resolve, reject) => { + navigator.mediaDevices + .enumerateDevices() + .then(devices => { + const microphones = devices.filter(device => device.kind === type); + resolve(microphones); + }) + .catch(error => { + reject(error); + }); + }); } // Microphones getAvailableMediaDevices('audioinput') - .then((microphones) => { - let i = 0; - let tempname = ''; - for (let mic of microphones) { - if (mic.deviceId === 'default') { - tempname = mic.label.slice(10); // remove "default -" from the label to get the default device name. - } + .then(microphones => { + let i = 0; + let tempname = ''; + for (const mic of microphones) { + if (mic.deviceId === 'default') { + tempname = mic.label.slice(10); // remove "default -" from the label to get the default device name. + } - if (mic.deviceId === 'communications' || mic.label === tempname) { - continue; - } + if (mic.deviceId === 'communications' || mic.label === tempname) { + continue; + } - const option = document.createElement('option'); + const option = document.createElement('option'); - // Set the options value and text. - option.value = i; - option.innerHTML = `${mic.label}`; + // Set the options value and text. + option.value = i; + option.innerHTML = `${mic.label}`; - // Add the option to the voice selector. - micSelect.appendChild(option); + // Add the option to the voice selector. + micSelect.appendChild(option); - if (i === microphones.length - 1) { - document.getElementById('microphone').value = settings.STT.SELECTED_MICROPHONE; - } - i++; - } - }) - .catch((error) => { - console.error('Error retrieving microphones:', error); - }); + if (i === microphones.length - 1) { + document.getElementById('microphone').value = settings.STT.SELECTED_MICROPHONE; + } + i++; + } + }) + .catch(error => { + console.error('Error retrieving microphones:', error); + }); diff --git a/src/js/messageTemplates.js b/src/js/messageTemplates.js index 34e6cc4..c8a626a 100644 --- a/src/js/messageTemplates.js +++ b/src/js/messageTemplates.js @@ -1,26 +1,26 @@ const twitchTemplate = ` - - - - -
          + + + + +
          `.trim(); const userTemplate = ` - - - - You -
          + + + + You +
          `.trim(); const messageTemplate = `
          - - - 12:00 PM - You -
          Hello there
          + + + 12:00 PM + You +
          Hello there
          `.trim(); diff --git a/src/js/renderer.js b/src/js/renderer.js index 0128a5d..16ba76b 100644 --- a/src/js/renderer.js +++ b/src/js/renderer.js @@ -3,7 +3,7 @@ const ini = require('ini'); const path = require('path'); // get directory path const axios = require('axios'); -const { ipcRenderer, shell } = require('electron'); // necessary electron libraries to send data to the app +const { webFrame, ipcRenderer, shell } = require('electron'); // necessary electron libraries to send data to the app const io = require('socket.io-client'); const util = require('util'); @@ -17,8 +17,8 @@ const { Socket } = require('socket.io-client'); const main = ipcRenderer.sendSync('environment'); const resourcesPath = main.resourcesPath; -let settingsPath = main.settingsPath.toString(); -let pythonPath = main.pythonPath.toString(); +const settingsPath = main.settingsPath.toString(); +const pythonPath = main.pythonPath.toString(); const settings = main.settings; // TODO: remove gooogle voices txt and use api instead @@ -35,6 +35,8 @@ const devicesDropdown = document.querySelector('#devicesDropdown'); const notificationSound = document.querySelector('#notification'); // obtain the html reference of the sound comboBox const sttModel = document.querySelector('#sttModel'); // obtain the html reference of the sound comboBox const ttsAudioDevices = document.querySelector('#ttsAudioDevice'); // obtain the html reference of the installedTTS comboBox +const notificationSoundAudioDevices = document.querySelector('#notificationSoundAudioDevice'); // obtain the html reference of the installedTTS comboBox +const emojiPicker = document.body.querySelector('emoji-picker'); // laod local javascript files const chat = require(path.join(__dirname, './js/chat')); @@ -47,18 +49,18 @@ const config = require(path.join(__dirname, './js/settings')); const mediaDevices = require(path.join(__dirname, './js/mediaDevices')); -let notificationSounds = path.join(__dirname, './sounds/notifications'); -let sttModels = path.join(__dirname, '../speech_to_text_models'); +const notificationSounds = path.join(__dirname, './sounds/notifications'); +const sttModels = path.join(__dirname, '../speech_to_text_models'); function reset() { - ipcRenderer.send('restart'); + ipcRenderer.send('restart'); } -let server = require(path.join(__dirname, './js/server')); +const server = require(path.join(__dirname, './js/server')); const backend = require(path.join(__dirname, './js/backend')); -let socket = io(`http://localhost:${settings.GENERAL.PORT}`); // Connect to your Socket.IO server +const socket = io(`http://localhost:${settings.GENERAL.PORT}`); // Connect to your Socket.IO server -let twitch = settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './js/twitch')) : ''; +const twitch = settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './js/twitch')) : ''; const Polly = settings.AMAZON.USE_AMAZON ? require(path.join(__dirname, './js/amazon')) : ''; const google = settings.GOOGLE.USE_GOOGLE ? require(path.join(__dirname, './js/google')) : ''; @@ -66,6 +68,9 @@ const theme = require(path.join(__dirname, './js/theme')); const auth = require(path.join(__dirname, './js/auth')); let ttsRequestCount = 0; +ttsRequestCount = 0; +let customEmojis = []; +customEmojis = []; // initialize values config.getGeneralSettings(); @@ -77,83 +82,93 @@ const StartDateAndTime = Date.now(); const speakButton = document.querySelector('#speakBtn'); const amazonCredentials = { - accessKeyId: settings.AMAZON.ACCESS_KEY, - secretAccessKey: settings.AMAZON.ACCESS_SECRET, + accessKeyId: settings.AMAZON.ACCESS_KEY, + secretAccessKey: settings.AMAZON.ACCESS_SECRET }; // Check for installed sounds fs.readdir(notificationSounds, (err, files) => { - files.forEach((file, i) => { - // Create a new option element. - const option = document.createElement('option'); + if (err) { + console.error(err); + } - // Set the options value and text. - option.value = i; - option.innerHTML = file; + files.forEach((file, i) => { + // Create a new option element. + const option = document.createElement('option'); - // Add the option to the sound selector. - notificationSound.appendChild(option); - }); + // Set the options value and text. + option.value = i; + option.innerHTML = file; - // set the saved notification sound - notificationSound.selectedIndex = settings.AUDIO.NOTIFICATION_SOUND; + // Add the option to the sound selector. + notificationSound.appendChild(option); + }); + + // set the saved notification sound + notificationSound.selectedIndex = settings.AUDIO.NOTIFICATION_SOUND; }); // Check for installed stt models fs.readdir(sttModels, (err, files) => { - for (let file of files) { - if (file.includes('.txt')) { - continue; - } - // Create a new option element. - const option = document.createElement('option'); + if (err) { + console.error(err); + } - // Set the options value and text. - option.value = file; - option.innerHTML = file; - - // Add the option to the sound selector. - sttModel.appendChild(option); + for (const file of files) { + if (file.includes('.txt')) { + continue; } + // Create a new option element. + const option = document.createElement('option'); - // set the saved notification sound - sttModel.value = settings.STT.LANGUAGE; + // Set the options value and text. + option.value = file; + option.innerHTML = file; + + // Add the option to the sound selector. + sttModel.appendChild(option); + } + + // set the saved notification sound + sttModel.value = settings.STT.LANGUAGE; }); async function getAudioDevices() { - if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { - return; - } + if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { + return; + } - const devices = await navigator.mediaDevices.enumerateDevices(); - const audioOutputDevices = devices.filter((device) => device.kind === 'audiooutput'); + const devices = await navigator.mediaDevices.enumerateDevices(); + const audioOutputDevices = devices.filter(device => device.kind === 'audiooutput'); - audioOutputDevices.forEach((device) => { - const option = document.createElement('option'); - option.text = device.label || `Output ${device.deviceId}`; - option.value = device.deviceId; - ttsAudioDevices.appendChild(option); - }); + audioOutputDevices.forEach(device => { + const option = document.createElement('option'); + option.text = device.label || `Output ${device.deviceId}`; + option.value = device.deviceId; + ttsAudioDevices.appendChild(option); + notificationSoundAudioDevices.appendChild(option); + }); - ttsAudioDevices.selectedIndex = settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE; + ttsAudioDevices.selectedIndex = settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE; + notificationSoundAudioDevices.selectedIndex = settings.AUDIO.SELECTED_NOTIFICATION_AUDIO_DEVICE; } getAudioDevices(); function setLanguagesinSelect(languageSelector, setting) { - let languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox + const languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox - for (const language in languageObject.languages) { - if (languageObject.languages.hasOwnProperty(language)) { - const iso639 = languageObject.languages[language]['ISO-639']; - const option = document.createElement('option'); - option.value = iso639; - option.innerHTML = `${iso639} - ${language}`; - languageSelect.appendChild(option); - } + for (const language in languageObject.languages) { + if (Object.prototype.hasOwnProperty.call(languageObject.languages, language)) { + const iso639 = languageObject.languages[language]['ISO-639']; + const option = document.createElement('option'); + option.value = iso639; + option.innerHTML = `${iso639} - ${language}`; + languageSelect.appendChild(option); } + } - languageSelect.selectedIndex = setting; + languageSelect.selectedIndex = setting; } setLanguagesinSelect('#language', settings.GENERAL.LANGUAGE); @@ -161,95 +176,122 @@ setLanguagesinSelect('#defaultLanguage', settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX setLanguagesinSelect('#secondaryLanguage', settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX); function addVoiceService(name) { - function addToselect(select) { - let ttsService = document.querySelector(select); - const option = document.createElement('option'); - ttsService.appendChild(option); + function addToselect(select) { + const ttsService = document.querySelector(select); + const option = document.createElement('option'); + ttsService.appendChild(option); - option.value = name; - option.innerHTML = name; - } - addToselect('#primaryTTSService'); - addToselect('#secondaryTTSService'); + option.value = name; + option.innerHTML = name; + } + addToselect('#primaryTTSService'); + addToselect('#secondaryTTSService'); } // Small tooltip -Array.from(document.body.querySelectorAll('[tip]')).forEach((el) => { - const tip = document.createElement('div'); - const body = document.querySelector('.container'); - const element = el; - tip.classList.add('tooltip'); - tip.classList.add('tooltiptext'); - tip.innerText = el.getAttribute('tip'); - tip.style.transform = `translate(${el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '15px'}, ${ - el.hasAttribute('tip-top') ? '-100%' : '15px' - })`; - body.appendChild(tip); - element.onmousemove = (e) => { - tip.style.left = `${e.x}px`; - tip.style.top = `${e.y}px`; - tip.style.zIndex = 1; - tip.style.visibility = 'visible'; - }; - element.onmouseleave = (e) => { - tip.style.visibility = 'hidden'; - }; +Array.from(document.body.querySelectorAll('[tip]')).forEach(el => { + const tip = document.createElement('div'); + const body = document.querySelector('.container'); + const element = el; + tip.classList.add('tooltip'); + tip.classList.add('tooltiptext'); + tip.innerText = el.getAttribute('tip'); + tip.style.transform = `translate(${el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '15px'}, ${ + el.hasAttribute('tip-top') ? '-100%' : '15px' + })`; + body.appendChild(tip); + element.onmousemove = e => { + tip.style.left = `${e.x}px`; + tip.style.top = `${e.y}px`; + tip.style.zIndex = 1; + tip.style.visibility = 'visible'; + }; + element.onmouseleave = e => { + tip.style.visibility = 'hidden'; + }; }); -function showChatMessage(article, isUser) { - document.querySelector('#chatBox').appendChild(article); - let usernameHtml; - let msg; - let messages = Array.from(document.body.querySelectorAll('.msg-container')); +function showChatMessage(article) { + document.querySelector('#chatBox').appendChild(article); - if (isUser) { - usernameHtml = article.querySelector('.username-user'); - msg = article.querySelector('.msg-box-user'); - } else { - usernameHtml = article.querySelector('.username'); - msg = article.querySelector('.msg-box'); - } + const messages = Array.from(document.body.querySelectorAll('.msg-container')); - // var style = getComputedStyle(usernameHtml); - // var style2 = getComputedStyle(usernameHtml); - - const lastMessage = messages[messages.length - 1]; - lastMessage.scrollIntoView({ behavior: 'smooth' }); + const lastMessage = messages[messages.length - 1]; + lastMessage.scrollIntoView({ behavior: 'smooth' }); } function getPostTime() { - const date = new Date(); - document.body.querySelectorAll('.container').innerHTML = date.getHours(); - const hours = date.getHours(); - var ampm = hours >= 12 ? 'PM' : 'AM'; - const minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); - const time = `${hours}:${minutes} ${ampm}`; + const date = new Date(); + document.body.querySelectorAll('.container').innerHTML = date.getHours(); + const hours = date.getHours(); + const ampm = hours >= 12 ? 'PM' : 'AM'; + const minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); + const time = `${hours}:${minutes} ${ampm}`; - return time; + return time; } function showPreviewChatMessage() { - const message = messageTemplates.messageTemplate; - document.querySelector('#mini-mid').innerHTML += message; - const messages = Array.from(document.body.querySelectorAll('#mini-mid')); - const lastMessage = messages[messages.length - 1]; - lastMessage.scrollIntoView({ behavior: 'smooth' }); + const message = messageTemplates.messageTemplate; + document.querySelector('#mini-mid').innerHTML += message; + const messages = Array.from(document.body.querySelectorAll('#mini-mid')); + const lastMessage = messages[messages.length - 1]; + lastMessage.scrollIntoView({ behavior: 'smooth' }); } showPreviewChatMessage(); function hideText(button, field) { - document.body.querySelector(button).addEventListener('click', () => { - const passwordInput = document.querySelector(field); - if (passwordInput.type === 'password') { - passwordInput.type = 'lol'; - } else { - passwordInput.type = 'password'; - } - }); + document.body.querySelector(button).addEventListener('click', () => { + const passwordInput = document.querySelector(field); + if (passwordInput.type === 'password') { + passwordInput.type = 'lol'; + } else { + passwordInput.type = 'password'; + } + }); } hideText('.password-toggle-btn1', '#TWITCH_OAUTH_TOKEN'); hideText('.password-toggle-btn4', '#AMAZON_ACCESS_KEY'); hideText('.password-toggle-btn5', '#AMAZON_ACCESS_SECRET'); hideText('.password-toggle-btn6', '#GOOGLE_API_KEY'); + +function setZoomLevel(currentZoom, zoomIn) { + let newZoom = currentZoom.toFixed(2); + + if (zoomIn === true && currentZoom < 4.95) { + newZoom = (currentZoom + 0.05).toFixed(2); + } + if (zoomIn === false && currentZoom > 0.25) { + newZoom = (currentZoom - 0.05).toFixed(2); + } + + webFrame.setZoomFactor(parseFloat(newZoom)); + settings.GENERAL.ZOOMLEVEL = newZoom; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + document.body.querySelector('#ZOOMLEVEL').value = (settings.GENERAL.ZOOMLEVEL * 100).toFixed(0); +} + +// const customEmojix = [ +// { +// name: 'sakuraestaKleefeliz', +// shortcodes: ['sakuraestaKleefeliz'], +// url: 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_0cb536ddb6e143ab87ffeccb160a4d45/default/dark/1.0', +// category: 'Sakura' +// } +// ]; + +// const customEmojiy = [ +// { +// name: 'sakuraestaKleefeliz', +// shortcodes: ['sakuraestaKleefeliz'], +// url: 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_0cb536ddb6e143ab87ffeccb160a4d45/default/dark/1.0', +// category: 'Sakurax' +// } +// ]; + +// emojiPicker.customEmoji = customEmojix; +// emojiPicker.customEmoji = customEmojiy; + +// console.log(emojiPicker.database.getEmojiBySearchQuery('Kappa')); diff --git a/src/js/responses.js b/src/js/responses.js index 4c7c082..49bd1a2 100644 --- a/src/js/responses.js +++ b/src/js/responses.js @@ -1,18 +1,21 @@ function getBotResponse(input) { - // rock paper scissors - if (input === 'rock') { - return 'paper'; - } if (input === 'paper') { - return 'scissors'; - } if (input === 'scissors') { - return 'rock'; - } + // rock paper scissors + if (input === 'rock') { + return 'paper'; + } + if (input === 'paper') { + return 'scissors'; + } + if (input === 'scissors') { + return 'rock'; + } - // Simple responses - if (input === 'hello') { - return 'Hello there!'; - } if (input === 'goodbye') { - return 'Talk to you later!'; - } - return 'Try asking something else!'; + // Simple responses + if (input === 'hello') { + return 'Hello there!'; + } + if (input === 'goodbye') { + return 'Talk to you later!'; + } + return 'Try asking something else!'; } diff --git a/src/js/server.js b/src/js/server.js index 97d9ff8..772a946 100644 --- a/src/js/server.js +++ b/src/js/server.js @@ -1,3 +1,5 @@ +/* global settings */ + const express = require('express'); const app = express(); const path = require('path'); @@ -5,42 +7,42 @@ const http = require('http'); const localServer = http.createServer(app); const io = require('socket.io')(localServer); -let requestCount = 0; +const requestCount = 0; function startVtuberModule() { - if (!settings.MODULES.USE_VTUBER) { - return; - } + if (!settings.MODULES.USE_VTUBER) { + return; + } - app.use('/vtuber', express.static(path.join(__dirname, '../modules/vtuber/'))); + app.use('/vtuber', express.static(path.join(__dirname, '../modules/vtuber/'))); - let vtuber = document.body.querySelector('#BrowsersourceVtuber'); - let vtuberframe = document.createElement('iframe'); - vtuberframe.class = 'frame'; - vtuberframe.src = `http://localhost:${settings.GENERAL.PORT}/vtuber`; - vtuberframe.style.width = '100%'; - vtuberframe.style.height = '100%'; - vtuberframe.frameBorder = 0; - vtuber.appendChild(vtuberframe); + const vtuber = document.body.querySelector('#BrowsersourceVtuber'); + const vtuberframe = document.createElement('iframe'); + vtuberframe.class = 'frame'; + vtuberframe.src = `http://localhost:${settings.GENERAL.PORT}/vtuber`; + vtuberframe.style.width = '100%'; + vtuberframe.style.height = '100%'; + vtuberframe.frameBorder = 0; + vtuber.appendChild(vtuberframe); } startVtuberModule(); function startChatBubbleModule() { - if (!settings.MODULES.USE_CHATBUBBLE) { - return; - } + if (!settings.MODULES.USE_CHATBUBBLE) { + return; + } - app.use('/chat', express.static(path.join(__dirname, '../modules/chat'))); + app.use('/chat', express.static(path.join(__dirname, '../modules/chat'))); - let chat = document.body.querySelector('#BrowsersourceChat'); - let chatframe = document.createElement('iframe'); - chatframe.class = 'frame'; - chatframe.src = `http://localhost:${settings.GENERAL.PORT}/chat`; - chatframe.style.width = '100%'; - chatframe.style.height = '100%'; - chatframe.frameBorder = 0; - chat.appendChild(chatframe); + const chat = document.body.querySelector('#BrowsersourceChat'); + const chatframe = document.createElement('iframe'); + chatframe.class = 'frame'; + chatframe.src = `http://localhost:${settings.GENERAL.PORT}/chat`; + chatframe.style.width = '100%'; + chatframe.style.height = '100%'; + chatframe.frameBorder = 0; + chat.appendChild(chatframe); } startChatBubbleModule(); @@ -49,34 +51,31 @@ function startSTT() {} // Middleware to conditionally serve routes app.use((req, res, next) => { - if (!settings.MODULES.USE_VTUBER && req.path === '/vtuber') { - res.sendStatus(404); // Return a 404 status for /vtuber when it's disabled - } else if (!settings.MODULES.USE_CHATBUBBLE && req.path === '/chat') { - res.sendStatus(404); // Return a 404 status for /chat when it's disabled - } else { - next(); // Proceed to the next middleware or route handler - } + if (!settings.MODULES.USE_VTUBER && req.path === '/vtuber') { + res.sendStatus(404); // Return a 404 status for /vtuber when it's disabled + } else if (!settings.MODULES.USE_CHATBUBBLE && req.path === '/chat') { + res.sendStatus(404); // Return a 404 status for /chat when it's disabled + } else { + next(); // Proceed to the next middleware or route handler + } }); localServer.listen(settings.GENERAL.PORT, () => { - startVtuberModule(); - startChatBubbleModule(); - - if (settings.TTS.USE_TTS) { - } + startVtuberModule(); + startChatBubbleModule(); }); // Handle socket connections -io.on('connection', (socket) => { - // Receive data from the client - socket.on('message', (data) => {}); +io.on('connection', socket => { + // Receive data from the client + socket.on('message', data => {}); - // Receive data from the client - socket.on('xxx', (logoUrl, username, message) => { - socket.broadcast.emit('message', logoUrl, username, message); - }); + // Receive data from the client + socket.on('xxx', (logoUrl, username, message) => { + socket.broadcast.emit('message', logoUrl, username, message); + }); - socket.on('disconnect', () => {}); + socket.on('disconnect', () => {}); }); module.exports = { startVtuberModule, startChatBubbleModule }; diff --git a/src/js/settings.js b/src/js/settings.js index 3e57ed7..ee3ddd0 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -1,600 +1,692 @@ +/* global settings, setZoomLevel, webFrame, theme, fs, settingsPath, ini, startVoiceRecognition,notificationSoundAudioDevices, ttsAudioDevices, notificationSound, path, resourcesPath, ipcRenderer, auth, shell, sound, twitch, server, backend */ + function getGeneralSettings() { - // General - document.body.querySelector('#PORT').value = settings.GENERAL.PORT; + // General + document.body.querySelector('#PORT').value = settings.GENERAL.PORT; + document.body.querySelector('#ZOOMLEVEL').value = settings.GENERAL.ZOOMLEVEL * 100; + webFrame.setZoomFactor(parseFloat(settings.GENERAL.ZOOMLEVEL)); + // Theme + document.querySelector('#USE_CUSTOM_THEME').value = settings.THEME.USE_CUSTOM_THEME; + document.body.querySelector('#USE_CUSTOM_THEME').checked = settings.THEME.USE_CUSTOM_THEME === true ? 1 : 0; + theme.setTheme(); - // Theme - document.querySelector('#USE_CUSTOM_THEME').value = settings.THEME.USE_CUSTOM_THEME; - document.body.querySelector('#USE_CUSTOM_THEME').checked = settings.THEME.USE_CUSTOM_THEME === true ? 1 : 0; - theme.setTheme(); + // STT + document.body.querySelector('#USE_STT').checked = settings.STT.USE_STT; - // STT - document.body.querySelector('#USE_STT').checked = settings.STT.USE_STT; + // Language detection + document.body.querySelector('#USE_DETECTION').checked = settings.LANGUAGE.USE_DETECTION; - // Language detection - document.body.querySelector('#USE_DETECTION').checked = settings.LANGUAGE.USE_DETECTION; + // TTS + document.body.querySelector('#USE_TTS').checked = settings.TTS.USE_TTS; - // TTS - document.body.querySelector('#USE_TTS').checked = settings.TTS.USE_TTS; + // Notification sounds + document.body.querySelector('#USE_NOTIFICATION_SOUNDS').checked = settings.AUDIO.USE_NOTIFICATION_SOUNDS; - // Notification sounds - document.body.querySelector('#USE_NOTIFICATION_SOUNDS').checked = settings.AUDIO.USE_NOTIFICATION_SOUNDS; + // Twitch + document.body.querySelector('#USE_TWITCH').checked = settings.TWITCH.USE_TWITCH; + document.body.querySelector('#TWITCH_CHANNEL_NAME').value = settings.TWITCH.CHANNEL_NAME; + document.body.querySelector('#TWITCH_OAUTH_TOKEN').value = settings.TWITCH.OAUTH_TOKEN; - // Twitch - document.body.querySelector('#USE_TWITCH').checked = settings.TWITCH.USE_TWITCH; - document.body.querySelector('#TWITCH_CHANNEL_NAME').value = settings.TWITCH.CHANNEL_NAME; - document.body.querySelector('#TWITCH_OAUTH_TOKEN').value = settings.TWITCH.OAUTH_TOKEN; + // Modules + document.body.querySelector('#USE_MODULES').checked = settings.MODULES.USE_MODULES; + document.body.querySelector('#USE_VTUBER').checked = settings.MODULES.USE_VTUBER; + document.body.querySelector('#VTUBER_URL').value = `http://localhost:${settings.GENERAL.PORT}/vtuber/`; + showMenuButton('#btnBrowsersourceVtuber', settings.MODULES.USE_VTUBER); + document.body.querySelector('#USE_CHATBUBBLE').checked = settings.MODULES.USE_CHATBUBBLE; + document.body.querySelector('#CHATBUBBLE_URL').value = `http://localhost:${settings.GENERAL.PORT}/chat/`; + showMenuButton('#btnBrowsersourceChat', settings.GENERAL.USE_CHATBUBBLE); - // Modules - document.body.querySelector('#USE_MODULES').checked = settings.MODULES.USE_MODULES; - document.body.querySelector('#USE_VTUBER').checked = settings.MODULES.USE_VTUBER; - document.body.querySelector('#VTUBER_URL').value = `http://localhost:${settings.GENERAL.PORT}/vtuber/`; - showMenuButton('#btnBrowsersourceVtuber', settings.MODULES.USE_VTUBER); - document.body.querySelector('#USE_CHATBUBBLE').checked = settings.MODULES.USE_CHATBUBBLE; - document.body.querySelector('#CHATBUBBLE_URL').value = `http://localhost:${settings.GENERAL.PORT}/chat/`; - showMenuButton('#btnBrowsersourceChat', settings.GENERAL.USE_CHATBUBBLE); + // Amazon + document.body.querySelector('#USE_AMAZON').checked = settings.AMAZON.USE_AMAZON; + document.body.querySelector('#AMAZON_ACCESS_KEY').value = settings.AMAZON.ACCESS_KEY; + document.body.querySelector('#AMAZON_ACCESS_SECRET').value = settings.AMAZON.ACCESS_SECRET; - // Amazon - document.body.querySelector('#USE_AMAZON').checked = settings.AMAZON.USE_AMAZON; - document.body.querySelector('#AMAZON_ACCESS_KEY').value = settings.AMAZON.ACCESS_KEY; - document.body.querySelector('#AMAZON_ACCESS_SECRET').value = settings.AMAZON.ACCESS_SECRET; - - // Google - document.body.querySelector('#USE_GOOGLE').checked = settings.GOOGLE.USE_GOOGLE; - document.body.querySelector('#GOOGLE_API_KEY').value = settings.GOOGLE.API_KEY; + // Google + document.body.querySelector('#USE_GOOGLE').checked = settings.GOOGLE.USE_GOOGLE; + document.body.querySelector('#GOOGLE_API_KEY').value = settings.GOOGLE.API_KEY; } document.body.querySelector('#primaryAmazonVoice').addEventListener('change', () => { - var select = document.querySelector('#primaryAmazonVoice'); - settings.AMAZON.PRIMARY_VOICE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Amazon primary voice!', 'success'); + const select = document.querySelector('#primaryAmazonVoice'); + settings.AMAZON.PRIMARY_VOICE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Amazon primary voice!', 'success'); }); document.body.querySelector('#secondaryAmazonVoice').addEventListener('change', () => { - var select = document.querySelector('#secondaryAmazonVoice'); - settings.AMAZON.SECONDARY_VOICE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Amazon secondary voice!', 'success'); + const select = document.querySelector('#secondaryAmazonVoice'); + settings.AMAZON.SECONDARY_VOICE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Amazon secondary voice!', 'success'); }); document.body.querySelector('#primaryGoogleVoice').addEventListener('change', () => { - var select = document.querySelector('#primaryGoogleVoice'); - settings.GOOGLE.PRIMARY_VOICE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Google primary voice!', 'success'); + const select = document.querySelector('#primaryGoogleVoice'); + settings.GOOGLE.PRIMARY_VOICE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Google primary voice!', 'success'); }); document.body.querySelector('#secondaryGoogleVoice').addEventListener('change', () => { - var select = document.querySelector('#secondaryGoogleVoice'); - settings.GOOGLE.SECONDARY_VOICE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Google secondary voice!', 'success'); + const select = document.querySelector('#secondaryGoogleVoice'); + settings.GOOGLE.SECONDARY_VOICE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Google secondary voice!', 'success'); }); document.body.querySelector('#primaryVoice').addEventListener('change', () => { - var select = document.querySelector('#primaryVoice'); - settings.TTS.PRIMARY_VOICE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved primary voice!', 'success'); + const select = document.querySelector('#primaryVoice'); + settings.TTS.PRIMARY_VOICE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved primary voice!', 'success'); }); document.body.querySelector('#microphone').addEventListener('change', () => { - var select = document.querySelector('#microphone'); - settings.STT.MICROPHONE = select.value; - settings.STT.MICROPHONE_ID = select.options[select.selectedIndex].text; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved microphone!', 'success'); - startVoiceRecognition(); + const select = document.querySelector('#microphone'); + settings.STT.MICROPHONE = select.value; + settings.STT.MICROPHONE_ID = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved microphone!', 'success'); + startVoiceRecognition(); }); document.body.querySelector('#sttModel').addEventListener('change', () => { - var select = document.querySelector('#sttModel'); - settings.STT.LANGUAGE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved voice detection language!', 'success'); + const select = document.querySelector('#sttModel'); + settings.STT.LANGUAGE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved voice detection language!', 'success'); }); document.body.querySelector('#defaultLanguage').addEventListener('change', () => { - var select = document.querySelector('#defaultLanguage'); - settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX = select.selectedIndex; - settings.TTS.PRIMARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved default language!', 'success'); + const select = document.querySelector('#defaultLanguage'); + settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX = select.selectedIndex; + settings.TTS.PRIMARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved default language!', 'success'); }); document.body.querySelector('#secondaryVoice').addEventListener('change', () => { - var select = document.querySelector('#secondaryVoice'); - settings.TTS.SECONDARY_VOICE = select.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved secondary voice!', 'success'); + const select = document.querySelector('#secondaryVoice'); + settings.TTS.SECONDARY_VOICE = select.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved secondary voice!', 'success'); }); document.body.querySelector('#secondaryLanguage').addEventListener('change', () => { - var select = document.querySelector('#secondaryLanguage'); - settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX = select.selectedIndex; - settings.TTS.SECONDARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved secondary language!', 'success'); + const select = document.querySelector('#secondaryLanguage'); + settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX = select.selectedIndex; + settings.TTS.SECONDARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved secondary language!', 'success'); }); document.body.querySelector('#ttsAudioDevice').addEventListener('change', () => { - settings.AUDIO.TTS_AUDIO_DEVICE = ttsAudioDevices.value; - settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE = ttsAudioDevices.selectedIndex; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved audio device!', 'success'); + settings.AUDIO.TTS_AUDIO_DEVICE = ttsAudioDevices.value; + settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE = ttsAudioDevices.selectedIndex; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved audio device!', 'success'); +}); + +document.body.querySelector('#notificationSoundAudioDevice').addEventListener('change', () => { + settings.AUDIO.SELECTED_NOTIFICATION_AUDIO_DEVICE = notificationSoundAudioDevices.value; + settings.AUDIO.NOTIFICATION_AUDIO_DEVICE = notificationSoundAudioDevices.selectedIndex; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved audio device!', 'success'); }); document.body.querySelector('#TWITCH_CHANNEL_NAME').addEventListener('change', () => { - settings.TWITCH.CHANNEL_NAME = document.body.querySelector('#TWITCH_CHANNEL_NAME').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); + settings.TWITCH.CHANNEL_NAME = document.body.querySelector('#TWITCH_CHANNEL_NAME').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); - let button = document.body.querySelector('#TestTwitchCredentials'); - button.className = 'AdvancedMenuButton'; - createNotification('Saved Channel name, please restart the application to reset twitch service', 'warning'); + const button = document.body.querySelector('#TestTwitchCredentials'); + button.className = 'AdvancedMenuButton'; + createNotification('Saved Channel name, please restart the application to reset twitch service', 'warning'); }); document.body.querySelector('#TWITCH_OAUTH_TOKEN').addEventListener('change', () => { - settings.TWITCH.OAUTH_TOKEN = document.body.querySelector('#TWITCH_OAUTH_TOKEN').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved OAuth token!', 'success'); + settings.TWITCH.OAUTH_TOKEN = document.body.querySelector('#TWITCH_OAUTH_TOKEN').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved OAuth token!', 'success'); - let button = document.body.querySelector('#TestTwitchCredentials'); - button.className = 'AdvancedMenuButton'; - createNotification('Saved OAuth token, please restart the application to reset twitch service', 'warning'); + const button = document.body.querySelector('#TestTwitchCredentials'); + button.className = 'AdvancedMenuButton'; + createNotification('Saved OAuth token, please restart the application to reset twitch service', 'warning'); }); +setInputFilter( + document.body.querySelector('#PORT'), + function (value) { + return /^\d*\.?\d*$/.test(value); // Allow digits and '.' only, using a RegExp. + }, + "Only digits and '.' are allowed" +); + document.body.querySelector('#PORT').addEventListener('change', () => { - settings.GENERAL.PORT = document.body.querySelector('#PORT').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved port, please restart the application to reset the port', 'warning'); + settings.GENERAL.PORT = document.body.querySelector('#PORT').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved port, please restart the application to reset the port', 'warning'); }); document.body.querySelector('#AMAZON_ACCESS_KEY').addEventListener('change', () => { - settings.AMAZON.ACCESS_KEY = document.body.querySelector('#AMAZON_ACCESS_KEY').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Amazon access key!', 'success'); + settings.AMAZON.ACCESS_KEY = document.body.querySelector('#AMAZON_ACCESS_KEY').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Amazon access key!', 'success'); }); document.body.querySelector('#AMAZON_ACCESS_SECRET').addEventListener('change', () => { - settings.AMAZON.ACCESS_SECRET = document.body.querySelector('#AMAZON_ACCESS_SECRET').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Amazon access secret!', 'success'); + settings.AMAZON.ACCESS_SECRET = document.body.querySelector('#AMAZON_ACCESS_SECRET').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Amazon access secret!', 'success'); }); document.body.querySelector('#GOOGLE_API_KEY').addEventListener('change', () => { - settings.GOOGLE.API_KEY = document.body.querySelector('#GOOGLE_API_KEY').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved Google api key!', 'success'); + settings.GOOGLE.API_KEY = document.body.querySelector('#GOOGLE_API_KEY').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Google api key!', 'success'); }); document.body.querySelector('#notification').addEventListener('change', () => { - settings.AUDIO.NOTIFICATION_SOUND = notificationSound.selectedIndex; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - createNotification('Saved notification sound!', 'success'); + settings.AUDIO.NOTIFICATION_SOUND = notificationSound.selectedIndex; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved notification sound!', 'success'); }); function showMenuButton(menuButton, toggle) { - let option = document.body.querySelector(menuButton); - if (!toggle) { - option.style.display = 'none'; - } else { - option.style.display = ''; - } + const option = document.body.querySelector(menuButton); + if (!toggle) { + option.style.display = 'none'; + } else { + option.style.display = ''; + } } const notificationToasts = document.querySelector('#toasts'); // toast messages function createNotification(message = null, type = null) { - const notification = document.createElement('div'); - notification.classList.add('toast'); - notification.classList.add(type); - notification.innerText = message; - notificationToasts.appendChild(notification); + const notification = document.createElement('div'); + notification.classList.add('toast'); + notification.classList.add(type); + notification.innerText = message; + notificationToasts.appendChild(notification); - let alertSound = 'info.mp3'; - if (type === 'error') { - alertSound = 'error.mp3'; - } + let alertSound = 'info.mp3'; + if (type === 'error') { + alertSound = 'error.mp3'; + } - let notfication = new Audio(path.join(resourcesPath, `./sounds/notifications/${alertSound}`)); - notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100; - notfication.play(); - setTimeout(() => notification.remove(), 10000); + const notfication = new Audio(path.join(resourcesPath, `./sounds/notifications/${alertSound}`)); + notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100; + notfication.play(); + setTimeout(() => notification.remove(), 10000); } // Check for configs if (!settings.TWITCH.USE_TWITCH) { - const text = 'Please setup a service to connect to in Configuration > Show Advanced'; - createNotification(text, 'warning'); + const text = 'Please setup a service to connect to in Configuration > Show Advanced'; + createNotification(text, 'warning'); } if (settings.TWITCH.USE_TWITCH && !settings.TWITCH.CHANNEL_NAME) { - const text = 'No channel name inserted in the Twitch service'; - createNotification(text, 'warning'); + const text = 'No channel name inserted in the Twitch service'; + createNotification(text, 'warning'); } if (settings.TWITCH.USE_TWITCH && !settings.TWITCH.USERNAME) { - const text = 'No username inserted in the Twitch service'; - createNotification(text, 'warning'); + const text = 'No username inserted in the Twitch service'; + createNotification(text, 'warning'); } function toggleRadio(toggle, inputs) { - const element = inputs; - if (toggle === true) { - for (let i = 0; i < inputs.length; i += 1) { - element[i].style.display = ''; - } - } else { - for (let i = 0; i < inputs.length; i += 1) { - element[i].style.display = 'none'; - } + const element = inputs; + if (toggle === true) { + for (let i = 0; i < inputs.length; i += 1) { + element[i].style.display = ''; } + } else { + for (let i = 0; i < inputs.length; i += 1) { + element[i].style.display = 'none'; + } + } } // #region Use Custom theme toggle logic document.body.querySelector('#USE_CUSTOM_THEME').addEventListener('click', () => { - const toggle = document.getElementById('USE_CUSTOM_THEME').checked; - const inputs = document.getElementsByClassName('inputTheme'); - toggleRadio(toggle, inputs); + const toggle = document.getElementById('USE_CUSTOM_THEME').checked; + const inputs = document.getElementsByClassName('inputTheme'); + toggleRadio(toggle, inputs); - settings.THEME.USE_CUSTOM_THEME = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - theme.setTheme(); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} custom theme!`, 'success'); + settings.THEME.USE_CUSTOM_THEME = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + theme.setTheme(); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} custom theme!`, 'success'); }); // #region Top bar buttons document.body.querySelector('#min-button').addEventListener('click', () => { - ipcRenderer.send('minimize-window'); + ipcRenderer.send('minimize-window'); }); // #region Top bar buttons document.body.querySelector('#Info_USERNAME').addEventListener('click', async () => { - let element = document.body.querySelector('#TWITCH_OAUTH_TOKEN'); - element.value = await auth.getTwitchOauthToken(); + const element = document.body.querySelector('#TWITCH_OAUTH_TOKEN'); + element.value = await auth.getTwitchOauthToken(); - createNotification('Saved OAuth token!', 'success'); + createNotification('Saved OAuth token!', 'success'); }); -let hideInputToggleButton = document.body.querySelectorAll('.password-toggle-btn .password-toggle-icon .fa-eye-slash'); -hideInputToggleButton.forEach((item) => { - item.addEventListener('click', () => { - if (item.classList.contains('fa-eye')) { - item.classList.remove('fa-eye'); - item.classList.add('fa-eye-slash'); - } else { - item.classList.remove('fa-eye-slash'); - item.classList.add('fa-eye'); - } - }); +const hideInputToggleButton = document.body.querySelectorAll('.password-toggle-btn .password-toggle-icon .fa-eye-slash'); +hideInputToggleButton.forEach(item => { + item.addEventListener('click', () => { + if (item.classList.contains('fa-eye')) { + item.classList.remove('fa-eye'); + item.classList.add('fa-eye-slash'); + } else { + item.classList.remove('fa-eye-slash'); + item.classList.add('fa-eye'); + } + }); }); function hideOrShowViewerPanel() { - const menu = document.body.querySelector('.sidepanel-right'); - const leftCircle = document.body.querySelector('.circle-right'); + const menu = document.body.querySelector('.sidepanel-right'); + const leftCircle = document.body.querySelector('.circle-right'); - if (!settings.GENERAL.VIEWERS_PANEL) { - menu.classList.add('collapse-menu-right'); - leftCircle.classList.add('collapse-circle-right'); - } else { - menu.classList.remove('collapse-menu-right'); - leftCircle.classList.remove('collapse-circle-right'); - } - fs.writeFileSync(settingsPath, ini.stringify(settings)); + if (!settings.GENERAL.VIEWERS_PANEL) { + menu.classList.add('collapse-menu-right'); + leftCircle.classList.add('collapse-circle-right'); + } else { + menu.classList.remove('collapse-menu-right'); + leftCircle.classList.remove('collapse-circle-right'); + } + fs.writeFileSync(settingsPath, ini.stringify(settings)); } hideOrShowViewerPanel(); document.body.querySelector('#VIEWERS_PANEL').addEventListener('click', () => { - if (settings.GENERAL.VIEWERS_PANEL) { - settings.GENERAL.VIEWERS_PANEL = false; - } else { - settings.GENERAL.VIEWERS_PANEL = true; - } - hideOrShowViewerPanel(); + if (settings.GENERAL.VIEWERS_PANEL) { + settings.GENERAL.VIEWERS_PANEL = false; + } else { + settings.GENERAL.VIEWERS_PANEL = true; + } + hideOrShowViewerPanel(); }); document.body.querySelector('#Info_VTUBER').addEventListener('click', () => { - shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/vtuber/`); + shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/vtuber/`); }); document.body.querySelector('#Info_CHATBUBBLE').addEventListener('click', () => { - shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/chat/`); + shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/chat/`); }); document.body.querySelector('#max-button').addEventListener('click', () => { - ipcRenderer.send('maximize-window'); + ipcRenderer.send('maximize-window'); }); document.body.querySelector('#close-button').addEventListener('click', () => { - ipcRenderer.send('close-window'); + ipcRenderer.send('close-window'); }); // #endregion // #region Notification sound test document.body.querySelector('#SoundTestButton').addEventListener('click', () => { - sound.playNotificationSound(); + sound.playNotificationSound(); }); document.body.querySelector('#TestTwitchCredentials').addEventListener('click', () => { - twitch.ping('#TestTwitchCredentials'); - // resetTwitch(; + twitch.ping('#TestTwitchCredentials'); + // resetTwitch(; }); function toggleTwitch() { - const toggle = settings.TWITCH.USE_TWITCH; - const inputs = document.getElementsByClassName('inputTwitch'); - toggleRadio(toggle, inputs); + const toggle = settings.TWITCH.USE_TWITCH; + const inputs = document.getElementsByClassName('inputTwitch'); + toggleRadio(toggle, inputs); } toggleTwitch(); document.body.querySelector('#USE_TWITCH').addEventListener('click', () => { - const toggle = document.getElementById('USE_TWITCH').checked; - settings.TWITCH.USE_TWITCH = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputTwitch'); - toggleRadio(toggle, inputs); - twitch = settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './twitch')) : null; - createNotification(`${toggle ? 'Enabled' : 'Disabled'} Twitch settings!`, 'success'); + const toggle = document.getElementById('USE_TWITCH').checked; + settings.TWITCH.USE_TWITCH = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputTwitch'); + toggleRadio(toggle, inputs); + twitch = settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './twitch')) : null; + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Twitch settings!`, 'success'); }); function toggleGoogle() { - const toggle = settings.GOOGLE.USE_GOOGLE; - const inputs = document.getElementsByClassName('inputGoogle'); - toggleRadio(toggle, inputs); + const toggle = settings.GOOGLE.USE_GOOGLE; + const inputs = document.getElementsByClassName('inputGoogle'); + toggleRadio(toggle, inputs); } toggleGoogle(); document.body.querySelector('#USE_GOOGLE').addEventListener('click', () => { - const toggle = document.getElementById('USE_GOOGLE').checked; - settings.GOOGLE.USE_GOOGLE = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputGoogle'); - toggleRadio(toggle, inputs); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} Google settings!`, 'success'); + const toggle = document.getElementById('USE_GOOGLE').checked; + settings.GOOGLE.USE_GOOGLE = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputGoogle'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Google settings!`, 'success'); }); function toggleAmazon() { - const toggle = settings.AMAZON.USE_AMAZON; - const inputs = document.getElementsByClassName('inputAmazon'); - toggleRadio(toggle, inputs); + const toggle = settings.AMAZON.USE_AMAZON; + const inputs = document.getElementsByClassName('inputAmazon'); + toggleRadio(toggle, inputs); } toggleAmazon(); document.body.querySelector('#USE_AMAZON').addEventListener('click', () => { - const toggle = document.getElementById('USE_AMAZON').checked; - settings.AMAZON.USE_AMAZON = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputAmazon'); - toggleRadio(toggle, inputs); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} Amazon settings!`, 'success'); + const toggle = document.getElementById('USE_AMAZON').checked; + settings.AMAZON.USE_AMAZON = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputAmazon'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Amazon settings!`, 'success'); }); function toggleServer() { - const toggle = settings.MODULES.USE_MODULES; - const inputs = document.getElementsByClassName('inputServer'); - toggleRadio(toggle, inputs); + const toggle = settings.MODULES.USE_MODULES; + const inputs = document.getElementsByClassName('inputServer'); + toggleRadio(toggle, inputs); } toggleServer(); document.body.querySelector('#USE_MODULES').addEventListener('click', () => { - const toggle = document.getElementById('USE_MODULES').checked; - settings.MODULES.USE_MODULES = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputServer'); - toggleRadio(toggle, inputs); - createNotification( - `${toggle ? 'Enabled' : 'Disabled'} server settings!, the service will stop working after restarting the application + const toggle = document.getElementById('USE_MODULES').checked; + settings.MODULES.USE_MODULES = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputServer'); + toggleRadio(toggle, inputs); + createNotification( + `${toggle ? 'Enabled' : 'Disabled'} server settings!, the service will stop working after restarting the application ${toggle ? '' : ', the service will stop working after restarting the application'}`, - 'success', - ); + 'success' + ); }); document.body.querySelector('#USE_VTUBER').addEventListener('change', () => { - const toggle = document.getElementById('USE_VTUBER').checked; - settings.MODULES.USE_VTUBER = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - showMenuButton('#btnBrowsersourceVtuber', toggle); - createNotification( - `${toggle ? 'Enabled' : 'Disabled'} Vtuber setting! + const toggle = document.getElementById('USE_VTUBER').checked; + settings.MODULES.USE_VTUBER = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + showMenuButton('#btnBrowsersourceVtuber', toggle); + createNotification( + `${toggle ? 'Enabled' : 'Disabled'} Vtuber setting! ${toggle ? '' : ', the service will stop working after restarting the application'}`, - 'success', - ); - server.startVtuberModule(); + 'success' + ); + server.startVtuberModule(); }); document.body.querySelector('#USE_CHATBUBBLE').addEventListener('change', () => { - const toggle = document.getElementById('USE_CHATBUBBLE').checked; - settings.MODULES.USE_CHATBUBBLE = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - showMenuButton('#btnBrowsersourceChat', toggle); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} chatbubble setting!`, 'success'); - server.startChatBubbleModule(); + const toggle = document.getElementById('USE_CHATBUBBLE').checked; + settings.MODULES.USE_CHATBUBBLE = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + showMenuButton('#btnBrowsersourceChat', toggle); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} chatbubble setting!`, 'success'); + server.startChatBubbleModule(); }); function toggleTTS() { - const toggle = settings.TTS.USE_TTS; - const inputs = document.getElementsByClassName('inputTTS'); - toggleRadio(toggle, inputs); + const toggle = settings.TTS.USE_TTS; + const inputs = document.getElementsByClassName('inputTTS'); + toggleRadio(toggle, inputs); } toggleTTS(); document.body.querySelector('#USE_TTS').addEventListener('change', () => { - const toggle = document.getElementById('USE_TTS').checked; - settings.TTS.USE_TTS = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputTTS'); - toggleRadio(toggle, inputs); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} text to speech!`, 'success'); + const toggle = document.getElementById('USE_TTS').checked; + settings.TTS.USE_TTS = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputTTS'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} text to speech!`, 'success'); }); function toggleSTT() { - const toggle = settings.STT.USE_STT; - const inputs = document.getElementsByClassName('inputSTT'); - toggleRadio(toggle, inputs); + const toggle = settings.STT.USE_STT; + const inputs = document.getElementsByClassName('inputSTT'); + toggleRadio(toggle, inputs); } toggleSTT(); document.body.querySelector('#USE_STT').addEventListener('change', () => { - const toggle = document.getElementById('USE_STT').checked; - settings.STT.USE_STT = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputSTT'); - toggleRadio(toggle, inputs); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} speech to text!`, 'success'); + const toggle = document.getElementById('USE_STT').checked; + settings.STT.USE_STT = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputSTT'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} speech to text!`, 'success'); }); function toggleLanguageDetection() { - const toggle = settings.LANGUAGE.USE_DETECTION; - const inputs = document.getElementsByClassName('languageDetectionInput'); - toggleRadio(toggle, inputs); + const toggle = settings.LANGUAGE.USE_DETECTION; + const inputs = document.getElementsByClassName('languageDetectionInput'); + toggleRadio(toggle, inputs); } toggleLanguageDetection(); document.body.querySelector('#USE_DETECTION').addEventListener('change', () => { - const toggle = document.getElementById('USE_DETECTION').checked; - settings.LANGUAGE.USE_DETECTION = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('languageDetectionInput'); - toggleRadio(toggle, inputs); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} Language detection!`, 'success'); + const toggle = document.getElementById('USE_DETECTION').checked; + settings.LANGUAGE.USE_DETECTION = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('languageDetectionInput'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Language detection!`, 'success'); }); function toggleNotificationSounds() { - const toggle = settings.AUDIO.USE_NOTIFICATION_SOUNDS; - const inputs = document.getElementsByClassName('inputNotificationSound'); - toggleRadio(toggle, inputs); + const toggle = settings.AUDIO.USE_NOTIFICATION_SOUNDS; + const inputs = document.getElementsByClassName('inputNotificationSound'); + toggleRadio(toggle, inputs); } toggleNotificationSounds(); document.body.querySelector('#USE_NOTIFICATION_SOUNDS').addEventListener('change', () => { - const toggle = document.getElementById('USE_NOTIFICATION_SOUNDS').checked; - settings.AUDIO.USE_NOTIFICATION_SOUNDS = toggle; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputNotificationSound'); - toggleRadio(toggle, inputs); - createNotification(`${toggle ? 'Enabled' : 'Disabled'} notification sounds!`, 'success'); + const toggle = document.getElementById('USE_NOTIFICATION_SOUNDS').checked; + settings.AUDIO.USE_NOTIFICATION_SOUNDS = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputNotificationSound'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} notification sounds!`, 'success'); }); document.body.querySelector('#notificationVolume').addEventListener('change', () => { - let element = document.body.querySelector('#notificationVolume'); - settings.AUDIO.NOTIFICATION_VOLUME = element.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); + const element = document.body.querySelector('#notificationVolume'); + settings.AUDIO.NOTIFICATION_VOLUME = element.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); - const slider = document.querySelector('#notificationVolumeSlider'); - slider.value = settings.AUDIO.NOTIFICATION_VOLUME; - slider.style.setProperty('--tiempotemporal', settings.AUDIO.NOTIFICATION_VOLUME); + const slider = document.querySelector('#notificationVolumeSlider'); + slider.value = settings.AUDIO.NOTIFICATION_VOLUME; + slider.style.setProperty('--tiempotemporal', settings.AUDIO.NOTIFICATION_VOLUME); - createNotification('Saved notification volume!', 'success'); + createNotification('Saved notification volume!', 'success'); }); document.body.querySelector('#notificationVolumeSlider').addEventListener('change', () => { - const e = document.querySelector('#notificationVolumeSlider'); - e.style.setProperty('--tiempotemporal', e.value); - e.style.setProperty('--min', e.min === '' ? '0' : e.min); - e.style.setProperty('--max', e.max === '' ? '100' : e.max); - document.querySelector('#notificationVolume').value = e.value; + const e = document.querySelector('#notificationVolumeSlider'); + e.style.setProperty('--tiempotemporal', e.value); + e.style.setProperty('--min', e.min === '' ? '0' : e.min); + e.style.setProperty('--max', e.max === '' ? '100' : e.max); + document.querySelector('#notificationVolume').value = e.value; - e.addEventListener('input', () => { - e.style.setProperty('--tiempotemporal', e.value); - document.querySelector('#notificationVolume').value = e.value; - settings.AUDIO.NOTIFICATION_VOLUME = e.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - }); + e.addEventListener('input', () => { + e.style.setProperty('--tiempotemporal', e.value); + document.querySelector('#notificationVolume').value = e.value; + settings.AUDIO.NOTIFICATION_VOLUME = e.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }); }); document.body.querySelector('#notificationVolumeSlider').addEventListener('mouseup', () => { - createNotification('Saved notification volume!', 'success'); + createNotification('Saved notification volume!', 'success'); }); if (settings.AUDIO.NOTIFICATION_VOLUME) { - document.querySelector('#notificationVolumeSlider').value = settings.AUDIO.NOTIFICATION_VOLUME; - document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change')); + document.querySelector('#notificationVolumeSlider').value = settings.AUDIO.NOTIFICATION_VOLUME; + document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change')); } else { - document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); + document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); } document.body.querySelector('#ttsVolume').addEventListener('change', () => { - let element = document.body.querySelector('#ttsVolume'); - settings.AUDIO.TTS_VOLUME = element.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); + const element = document.body.querySelector('#ttsVolume'); + settings.AUDIO.TTS_VOLUME = element.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); - const slider = document.querySelector('#ttsVolumeSlider'); - slider.value = settings.AUDIO.TTS_VOLUME; - slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME); + const slider = document.querySelector('#ttsVolumeSlider'); + slider.value = settings.AUDIO.TTS_VOLUME; + slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME); - createNotification('Saved TTS volume!', 'success'); + createNotification('Saved TTS volume!', 'success'); }); document.body.querySelector('#ttsVolumeSlider').addEventListener('change', () => { - const e = document.querySelector('#ttsVolumeSlider'); - e.style.setProperty('--tiempotemporal', e.value); - e.style.setProperty('--min', e.min === '' ? '0' : e.min); - e.style.setProperty('--max', e.max === '' ? '100' : e.max); - document.querySelector('#ttsVolume').value = e.value; + const e = document.querySelector('#ttsVolumeSlider'); + e.style.setProperty('--tiempotemporal', e.value); + e.style.setProperty('--min', e.min === '' ? '0' : e.min); + e.style.setProperty('--max', e.max === '' ? '100' : e.max); + document.querySelector('#ttsVolume').value = e.value; - e.addEventListener('input', () => { - e.style.setProperty('--tiempotemporal', e.value); - document.querySelector('#ttsVolume').value = e.value; - settings.AUDIO.TTS_VOLUME = e.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - }); + e.addEventListener('input', () => { + e.style.setProperty('--tiempotemporal', e.value); + document.querySelector('#ttsVolume').value = e.value; + settings.AUDIO.TTS_VOLUME = e.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }); }); document.body.querySelector('#ttsVolumeSlider').addEventListener('mouseup', () => { - createNotification('Saved TTS volume!', 'success'); + createNotification('Saved TTS volume!', 'success'); }); if (settings.AUDIO.TTS_VOLUME) { - document.querySelector('#ttsVolumeSlider').value = settings.AUDIO.TTS_VOLUME; - document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change')); + document.querySelector('#ttsVolumeSlider').value = settings.AUDIO.TTS_VOLUME; + document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change')); } else { - document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); + document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); } document.body.querySelector('#ttsVolume').addEventListener('change', () => { - let element = document.body.querySelector('#ttsVolume'); - settings.AUDIO.TTS_VOLUME = element.value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); + const element = document.body.querySelector('#ttsVolume'); + settings.AUDIO.TTS_VOLUME = element.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); - const slider = document.querySelector('#ttsVolumeSlider'); - slider.value = settings.AUDIO.TTS_VOLUME; - slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME); + const slider = document.querySelector('#ttsVolumeSlider'); + slider.value = settings.AUDIO.TTS_VOLUME; + slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME); }); document.body.querySelector('#TestDefaultTTSButton').addEventListener('click', async () => { - const text = document.getElementById('testPrimaryTTS').value; - const requestData = { - message: `user: ${text}`, - voice: settings.TTS.PRIMARY_VOICE, - }; - let count = await backend.getInternalTTSAudio(requestData); - let textObject = { filtered: text, formatted: text }; - sound.playAudio({ service: 'Internal', message: textObject, count }); + const text = document.getElementById('testPrimaryTTS').value; + const requestData = { + message: `user: ${text}`, + voice: settings.TTS.PRIMARY_VOICE + }; + const count = await backend.getInternalTTSAudio(requestData); + const textObject = { filtered: text, formatted: text }; + sound.playAudio({ service: 'Internal', message: textObject, count }); }); document.body.querySelector('#TestSecondaryTTSButton').addEventListener('click', async () => { - const text = document.getElementById('testSecondaryTTS').value; - const requestData = { - message: `user: ${text}`, - voice: settings.TTS.SECONDARY_VOICE, - }; + const text = document.getElementById('testSecondaryTTS').value; + const requestData = { + message: `user: ${text}`, + voice: settings.TTS.SECONDARY_VOICE + }; - let count = await backend.getInternalTTSAudio(requestData); - let textObject = { filtered: text, formatted: text }; + const count = await backend.getInternalTTSAudio(requestData); + const textObject = { filtered: text, formatted: text }; - sound.playAudio({ service: 'Internal', message: textObject, count }); + sound.playAudio({ service: 'Internal', message: textObject, count }); +}); + +// Restricts input for the given textbox to the given inputFilter function. +function setInputFilter(textbox, inputFilter, errMsg) { + ['input', 'keydown', 'keyup', 'mousedown', 'mouseup', 'select', 'contextmenu', 'drop', 'focusout'].forEach(function (event) { + textbox.addEventListener(event, function (e) { + if (inputFilter(this.value)) { + // Accepted value. + if (['keydown', 'mousedown', 'focusout'].indexOf(e.type) >= 0) { + this.classList.remove('input-error'); + this.setCustomValidity(''); + } + + this.oldValue = this.value; + this.oldSelectionStart = this.selectionStart; + this.oldSelectionEnd = this.selectionEnd; + } else if (Object.prototype.hasOwnProperty.call(this, 'oldValue')) { + // Rejected value: restore the previous one. + this.classList.add('input-error'); + this.setCustomValidity(errMsg); + this.reportValidity(); + this.value = this.oldValue; + this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd); + } else { + // Rejected value: nothing to restore. + this.value = ''; + } + }); + }); +} + +webFrame.setVisualZoomLevelLimits(1, 5); + +document.body.addEventListener('wheel', e => { + if (e.ctrlKey) { + const currentZoom = webFrame.getZoomFactor(); + const zoomIn = Boolean(e.deltaY < 0); + setZoomLevel(currentZoom, zoomIn); + } +}); + +setInputFilter( + document.body.querySelector('#ZOOMLEVEL'), + function (value) { + return /^\d*\.?\d*$/.test(value); // Allow digits and '.' only, using a RegExp. + }, + "Only digits and '.' are allowed" +); + +document.body.querySelector('#ZOOMLEVEL').addEventListener('change', () => { + const newZoom = parseInt(document.body.querySelector('#ZOOMLEVEL').value) / 100; + settings.GENERAL.ZOOMLEVEL = newZoom; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + setZoomLevel(newZoom, null); + createNotification('Saved zoom new level', 'warning'); +}); + +document.body.querySelector('emoji-picker').addEventListener('emoji-click', e => { + console.log(e.detail); + const div = document.getElementById('textInput'); + if (e.detail.unicode === undefined) { + div.value += e.detail.name + ' '; + } else { + div.value += e.detail.unicode + ' '; + } + + div.focus(); +}); + +// #region Use Custom theme toggle logic +document.body.querySelector('#emojis').addEventListener('click', () => { + const emojiPicker = document.body.querySelector('#emoji-picker'); + // console.log(emojiPicker); + emojiPicker.style.visibility === 'visible' ? (emojiPicker.style.visibility = 'hidden') : (emojiPicker.style.visibility = 'visible'); }); module.exports = { - getGeneralSettings, + getGeneralSettings }; diff --git a/src/js/sound.js b/src/js/sound.js index 679b2a3..1040ded 100644 --- a/src/js/sound.js +++ b/src/js/sound.js @@ -1,120 +1,139 @@ +/* global ttsAudioFile, path, resourcesPath, settings, fs, notificationSound, backend, socket, requestData */ + let trueMessage = ''; let currentLogoUrl = ''; let currentUsername = ''; -let voiceSoundArray = []; +const voiceSoundArray = []; let status = 0; -let counter = 0; +const counter = 0; -const playTTS = (data) => - new Promise((resolve) => { - ttsAudioFile = path.join(resourcesPath, `./sounds/tts/${data.service}_${data.count}.mp3`); - const tts = new Audio(ttsAudioFile); - console.log(settings.AUDIO.TTS_AUDIO_DEVICE); - tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE); +const playTTS = data => + new Promise(resolve => { + ttsAudioFile = path.join(resourcesPath, `./sounds/tts/${data.service}_${data.count}.mp3`); + const tts = new Audio(ttsAudioFile); + // console.log(settings.AUDIO.TTS_AUDIO_DEVICE); + tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE); - tts.addEventListener('ended', () => { - console.log('ended'); - fs.unlink(ttsAudioFile, (err) => { - if (err) { - console.error('TEST'); - - resolve('finished'); - return; - } - resolve('finished'); - }); - }); - - tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE) - .then(() => { - console.log('playing'); - tts.volume = settings.AUDIO.TTS_VOLUME / 100; - tts.play().catch((error) => { - resolve('finished'); - }); - }) - .catch((error) => { - console.error('Failed to set audio output device:', error); - resolve('finished'); - }); + tts.addEventListener('ended', () => { + // console.log('ended'); + fs.unlink(ttsAudioFile, err => { + if (err) { + console.error(err); + resolve('finished'); + return; + } + resolve('finished'); + }); }); + tts + .setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE) + .then(() => { + // console.log('playing'); + tts.volume = settings.AUDIO.TTS_VOLUME / 100; + tts.play().catch(error => { + if (error) { + console.error(error); + } + resolve('finished'); + }); + }) + .catch(error => { + console.error('Failed to set audio output device:', error); + resolve('finished'); + }); + }); + async function shiftVoice() { - status = 1; - while (voiceSoundArray.length > 0) { - await playTTS(voiceSoundArray.shift()); - } - status = 0; + status = 1; + while (voiceSoundArray.length > 0) { + await playTTS(voiceSoundArray.shift()); + } + status = 0; } function add(data) { - voiceSoundArray.push(data); - if (status === 0) { - shiftVoice(); - } + voiceSoundArray.push(data); + if (status === 0) { + shiftVoice(); + } } function playNotificationSound() { - if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) { - let notfication = new Audio( - path.join(resourcesPath, `./sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`), - ); + if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) { + const notfication = new Audio( + path.join(resourcesPath, `./sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`) + ); + + notfication + .setSinkId(settings.AUDIO.SELECTED_NOTIFICATION_AUDIO_DEVICE) + .then(() => { + // console.log('playing'); notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100; - notfication.play(); - } + notfication.play().catch(error => { + if (error) { + console.error(error); + } + }); + }) + .catch(error => { + console.error('Failed to set audio output device:', error); + }); + } } // Play sound function function playAudio(data) { - if (data.service !== '') { - add(data); - } + if (data.service !== '') { + add(data); + } } async function playVoice(filteredMessage, logoUrl, username, message) { - trueMessage = filteredMessage; - currentLogoUrl = logoUrl; - currentUsername = username; - let textObject = { filtered: filteredMessage, formatted: message }; - let voice; - textObject.filtered = `${username}: ${filteredMessage}`; + trueMessage = filteredMessage; + currentLogoUrl = logoUrl; + currentUsername = username; + const textObject = { filtered: filteredMessage, formatted: message }; + let voice; + textObject.filtered = `${username}: ${filteredMessage}`; - // if ( - // settings.TTS.PRIMARY_TTS_LANGUAGE.toLowerCase() !== settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase() && - // language[0].lang === settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase() - // ) { - // voice = settings.TTS.SECONDARY_TTS_NAME; - // textObject.filtered = `${username}: ${filteredMessage}`; - // } else { - // voice = settings.TTS.PRIMARY_TTS_NAME; - // textObject.filtered = `${username}: ${filteredMessage}`; - // } + // if ( + // settings.TTS.PRIMARY_TTS_LANGUAGE.toLowerCase() !== settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase() && + // language[0].lang === settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase() + // ) { + // voice = settings.TTS.SECONDARY_TTS_NAME; + // textObject.filtered = `${username}: ${filteredMessage}`; + // } else { + // voice = settings.TTS.PRIMARY_TTS_NAME; + // textObject.filtered = `${username}: ${filteredMessage}`; + // } - const service = document.getElementById('primaryTTSService').value; + const service = document.getElementById('primaryTTSService').value; - switch (service) { - case 'Internal': - const requestData = { - message: textObject.filtered, - voice: settings.TTS.PRIMARY_VOICE, - }; + switch (service) { + case 'Internal': { + const requestData = { + message: textObject.filtered, + voice: settings.TTS.PRIMARY_VOICE + }; - let count = await backend.getInternalTTSAudio(requestData); - playAudio({ service, message: textObject, count }); - break; - case 'Amazon': - // playAudio({ service: 'Amazon', message: textObject, count }); - break; - case 'Google': - // playAudio({ service: 'Google', message: textObject, count }); - break; + const count = await backend.getInternalTTSAudio(requestData); + playAudio({ service, message: textObject, count }); + break; } + case 'Amazon': + // playAudio({ service: 'Amazon', message: textObject, count }); + break; + case 'Google': + // playAudio({ service: 'Google', message: textObject, count }); + break; + } - if (settings.MODULES.USE_CHATBUBBLE) { - socket.emit('xxx', currentLogoUrl, currentUsername, textObject); - } + if (settings.MODULES.USE_CHATBUBBLE) { + socket.emit('xxx', currentLogoUrl, currentUsername, textObject); + } - playNotificationSound(); + playNotificationSound(); } module.exports = { playAudio, playVoice, playNotificationSound }; diff --git a/src/js/theme.js b/src/js/theme.js index d324b87..8fb2653 100644 --- a/src/js/theme.js +++ b/src/js/theme.js @@ -1,145 +1,143 @@ +/* global settings, root, fs, settingsPath, ini */ + function changeColor(section, setting, tempSection) { - document.querySelector(section).value = setting; - const value = document.querySelector(section).value; - root.style.setProperty(tempSection, value); + document.querySelector(section).value = setting; + const value = document.querySelector(section).value; + root.style.setProperty(tempSection, value); } function setCurrentTheme(adjustTemp = false) { - changeColor('#MAIN_COLOR_1', settings.THEME.MAIN_COLOR_1, adjustTemp ? '--main-color1-temp' : '--main-color1'); - changeColor('#MAIN_COLOR_2', settings.THEME.MAIN_COLOR_2, adjustTemp ? '--main-color2-temp' : '--main-color2'); - changeColor('#MAIN_COLOR_3', settings.THEME.MAIN_COLOR_3, adjustTemp ? '--main-color3-temp' : '--main-color3'); - changeColor('#MAIN_COLOR_4', settings.THEME.MAIN_COLOR_4, adjustTemp ? '--main-color4-temp' : '--main-color4'); - changeColor('#TOP_BAR', settings.THEME.TOP_BAR, adjustTemp ? '--top-bar-temp' : '--top-bar'); - changeColor('#MID_SECTION', settings.THEME.MID_SECTION, adjustTemp ? '--mid-section-temp' : '--mid-section'); - changeColor('#CHAT_BUBBLE_BG', settings.THEME.CHAT_BUBBLE_BG, adjustTemp ? '--chat-bubble-temp' : '--chat-bubble'); - changeColor( - '#CHAT_BUBBLE_HEADER', - settings.THEME.CHAT_BUBBLE_HEADER, - adjustTemp ? '--chat-bubble-header-temp' : '--chat-bubble-header', - ); - changeColor( - '#CHAT_BUBBLE_MESSAGE', - settings.THEME.CHAT_BUBBLE_MESSAGE, - adjustTemp ? '--chat-bubble-message-temp' : '--chat-bubble-message', - ); + changeColor('#MAIN_COLOR_1', settings.THEME.MAIN_COLOR_1, adjustTemp ? '--main-color1-temp' : '--main-color1'); + changeColor('#MAIN_COLOR_2', settings.THEME.MAIN_COLOR_2, adjustTemp ? '--main-color2-temp' : '--main-color2'); + changeColor('#MAIN_COLOR_3', settings.THEME.MAIN_COLOR_3, adjustTemp ? '--main-color3-temp' : '--main-color3'); + changeColor('#MAIN_COLOR_4', settings.THEME.MAIN_COLOR_4, adjustTemp ? '--main-color4-temp' : '--main-color4'); + changeColor('#TOP_BAR', settings.THEME.TOP_BAR, adjustTemp ? '--top-bar-temp' : '--top-bar'); + changeColor('#MID_SECTION', settings.THEME.MID_SECTION, adjustTemp ? '--mid-section-temp' : '--mid-section'); + changeColor('#CHAT_BUBBLE_BG', settings.THEME.CHAT_BUBBLE_BG, adjustTemp ? '--chat-bubble-temp' : '--chat-bubble'); + changeColor('#CHAT_BUBBLE_HEADER', settings.THEME.CHAT_BUBBLE_HEADER, adjustTemp ? '--chat-bubble-header-temp' : '--chat-bubble-header'); + changeColor( + '#CHAT_BUBBLE_MESSAGE', + settings.THEME.CHAT_BUBBLE_MESSAGE, + adjustTemp ? '--chat-bubble-message-temp' : '--chat-bubble-message' + ); } setCurrentTheme(true); function setTheme() { - if (settings.THEME.USE_CUSTOM_THEME) { - setCurrentTheme(); - } else { - root.style.setProperty('--main-color1', '#6e2c8c'); - root.style.setProperty('--main-color2', 'white'); - root.style.setProperty('--main-color3', '#211E1E'); - root.style.setProperty('--main-color4', '#2f2c34'); - root.style.setProperty('--top-bar', '#100B12'); - root.style.setProperty('--mid-section', '#352d3d'); - root.style.setProperty('--chat-bubble', ' #7A6D7F'); - root.style.setProperty('--chat-bubble-header', '#141414'); - root.style.setProperty('--chat-bubble-message', 'white'); - } + if (settings.THEME.USE_CUSTOM_THEME) { + setCurrentTheme(); + } else { + root.style.setProperty('--main-color1', '#6e2c8c'); + root.style.setProperty('--main-color2', 'white'); + root.style.setProperty('--main-color3', '#211E1E'); + root.style.setProperty('--main-color4', '#2f2c34'); + root.style.setProperty('--top-bar', '#100B12'); + root.style.setProperty('--mid-section', '#352d3d'); + root.style.setProperty('--chat-bubble', ' #7A6D7F'); + root.style.setProperty('--chat-bubble-header', '#141414'); + root.style.setProperty('--chat-bubble-message', 'white'); + } } document.body.querySelector('#MAIN_COLOR_1').addEventListener('input', () => { - const x = document.getElementById('MAIN_COLOR_1').value; - root.style.setProperty('--main-color1-temp', x); - console.log(x); + const x = document.getElementById('MAIN_COLOR_1').value; + root.style.setProperty('--main-color1-temp', x); + console.log(x); }); document.body.querySelector('#MAIN_COLOR_1').addEventListener('change', () => { - settings.THEME.MAIN_COLOR_1 = document.getElementById('MAIN_COLOR_1').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#MAIN_COLOR_1', settings.THEME.MAIN_COLOR_1, '--main-color1'); + settings.THEME.MAIN_COLOR_1 = document.getElementById('MAIN_COLOR_1').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#MAIN_COLOR_1', settings.THEME.MAIN_COLOR_1, '--main-color1'); }); document.body.querySelector('#MAIN_COLOR_2').addEventListener('input', () => { - const x = document.getElementById('MAIN_COLOR_2').value; - root.style.setProperty('--main-color2-temp', x); + const x = document.getElementById('MAIN_COLOR_2').value; + root.style.setProperty('--main-color2-temp', x); }); document.body.querySelector('#MAIN_COLOR_2').addEventListener('change', () => { - settings.THEME.MAIN_COLOR_2 = document.getElementById('MAIN_COLOR_2').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#MAIN_COLOR_2', settings.THEME.MAIN_COLOR_2, '--main-color2'); + settings.THEME.MAIN_COLOR_2 = document.getElementById('MAIN_COLOR_2').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#MAIN_COLOR_2', settings.THEME.MAIN_COLOR_2, '--main-color2'); }); document.body.querySelector('#MAIN_COLOR_3').addEventListener('input', () => { - const x = document.getElementById('MAIN_COLOR_3').value; - root.style.setProperty('--main-color3-temp', x); + const x = document.getElementById('MAIN_COLOR_3').value; + root.style.setProperty('--main-color3-temp', x); }); document.body.querySelector('#MAIN_COLOR_3').addEventListener('change', () => { - settings.THEME.MAIN_COLOR_3 = document.getElementById('MAIN_COLOR_3').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#MAIN_COLOR_3', settings.THEME.MAIN_COLOR_3, '--main-color3'); + settings.THEME.MAIN_COLOR_3 = document.getElementById('MAIN_COLOR_3').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#MAIN_COLOR_3', settings.THEME.MAIN_COLOR_3, '--main-color3'); }); document.body.querySelector('#MAIN_COLOR_4').addEventListener('input', () => { - const x = document.getElementById('MAIN_COLOR_4').value; - root.style.setProperty('--main-color4-temp', x); + const x = document.getElementById('MAIN_COLOR_4').value; + root.style.setProperty('--main-color4-temp', x); }); document.body.querySelector('#MAIN_COLOR_4').addEventListener('change', () => { - settings.THEME.MAIN_COLOR_4 = document.getElementById('MAIN_COLOR_4').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#MAIN_COLOR_4', settings.THEME.MAIN_COLOR_4, '--main-color4'); + settings.THEME.MAIN_COLOR_4 = document.getElementById('MAIN_COLOR_4').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#MAIN_COLOR_4', settings.THEME.MAIN_COLOR_4, '--main-color4'); }); document.body.querySelector('#TOP_BAR').addEventListener('input', () => { - const x = document.getElementById('TOP_BAR').value; - root.style.setProperty('--top-bar-temp', x); + const x = document.getElementById('TOP_BAR').value; + root.style.setProperty('--top-bar-temp', x); }); document.body.querySelector('#TOP_BAR').addEventListener('change', () => { - settings.THEME.TOP_BAR = document.getElementById('TOP_BAR').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#TOP_BAR', settings.THEME.TOP_BAR, '--top-bar'); + settings.THEME.TOP_BAR = document.getElementById('TOP_BAR').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#TOP_BAR', settings.THEME.TOP_BAR, '--top-bar'); }); document.body.querySelector('#MID_SECTION').addEventListener('input', () => { - const x = document.getElementById('MID_SECTION').value; - root.style.setProperty('--mid-section-temp', x); + const x = document.getElementById('MID_SECTION').value; + root.style.setProperty('--mid-section-temp', x); }); document.body.querySelector('#MID_SECTION').addEventListener('change', () => { - settings.THEME.MID_SECTION = document.getElementById('MID_SECTION').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#MID_SECTION', settings.THEME.MID_SECTION, '--mid-section'); + settings.THEME.MID_SECTION = document.getElementById('MID_SECTION').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#MID_SECTION', settings.THEME.MID_SECTION, '--mid-section'); }); document.body.querySelector('#CHAT_BUBBLE_BG').addEventListener('input', () => { - const x = document.getElementById('CHAT_BUBBLE_BG').value; - root.style.setProperty('--chat-bubble-temp', x); + const x = document.getElementById('CHAT_BUBBLE_BG').value; + root.style.setProperty('--chat-bubble-temp', x); }); document.body.querySelector('#CHAT_BUBBLE_BG').addEventListener('change', () => { - settings.THEME.CHAT_BUBBLE_BG = document.getElementById('CHAT_BUBBLE_BG').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#CHAT_BUBBLE_BG', settings.THEME.CHAT_BUBBLE_BG, '--chat-bubble'); + settings.THEME.CHAT_BUBBLE_BG = document.getElementById('CHAT_BUBBLE_BG').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#CHAT_BUBBLE_BG', settings.THEME.CHAT_BUBBLE_BG, '--chat-bubble'); }); document.body.querySelector('#CHAT_BUBBLE_HEADER').addEventListener('input', () => { - const x = document.getElementById('CHAT_BUBBLE_HEADER').value; - root.style.setProperty('--chat-bubble-header-temp', x); + const x = document.getElementById('CHAT_BUBBLE_HEADER').value; + root.style.setProperty('--chat-bubble-header-temp', x); }); document.body.querySelector('#CHAT_BUBBLE_HEADER').addEventListener('change', () => { - settings.THEME.CHAT_BUBBLE_HEADER = document.getElementById('CHAT_BUBBLE_HEADER').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#CHAT_BUBBLE_HEADER', settings.THEME.CHAT_BUBBLE_HEADER, '--chat-bubble-header'); + settings.THEME.CHAT_BUBBLE_HEADER = document.getElementById('CHAT_BUBBLE_HEADER').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#CHAT_BUBBLE_HEADER', settings.THEME.CHAT_BUBBLE_HEADER, '--chat-bubble-header'); }); document.body.querySelector('#CHAT_BUBBLE_MESSAGE').addEventListener('input', () => { - const x = document.getElementById('CHAT_BUBBLE_MESSAGE').value; - root.style.setProperty('--chat-bubble-message-temp', x); + const x = document.getElementById('CHAT_BUBBLE_MESSAGE').value; + root.style.setProperty('--chat-bubble-message-temp', x); }); document.body.querySelector('#CHAT_BUBBLE_MESSAGE').addEventListener('change', () => { - settings.THEME.CHAT_BUBBLE_MESSAGE = document.getElementById('CHAT_BUBBLE_MESSAGE').value; - fs.writeFileSync(settingsPath, ini.stringify(settings)); - changeColor('#CHAT_BUBBLE_MESSAGE', settings.THEME.CHAT_BUBBLE_MESSAGE, '--chat-bubble-message'); + settings.THEME.CHAT_BUBBLE_MESSAGE = document.getElementById('CHAT_BUBBLE_MESSAGE').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor('#CHAT_BUBBLE_MESSAGE', settings.THEME.CHAT_BUBBLE_MESSAGE, '--chat-bubble-message'); }); module.exports = { setTheme }; diff --git a/src/js/twitch.js b/src/js/twitch.js index 6f3ec65..781a85a 100644 --- a/src/js/twitch.js +++ b/src/js/twitch.js @@ -1,144 +1,186 @@ +/* global client, customEmojis, emojiPicker, settings, options, sound, showChatMessage, messageTemplates, getPostTime */ + const tmi = require('tmi.js'); const axios = require('axios'); -let client; +let client = null; +let logoUrl = null; function sendMessage(message) { - client.say(settings.TWITCH.CHANNEL_NAME, message).catch(console.error); + client.say(settings.TWITCH.CHANNEL_NAME, message).catch(console.error); } client = new tmi.Client({ - options: { - skipUpdatingEmotesets: true, - }, - identity: { - username: settings.TWITCH.USERNAME, - password: settings.TWITCH.OAUTH_TOKEN, - }, - channels: [settings.TWITCH.CHANNEL_NAME], + options: { + skipUpdatingEmotesets: true + }, + identity: { + username: settings.TWITCH.USERNAME, + password: settings.TWITCH.OAUTH_TOKEN + }, + channels: [settings.TWITCH.CHANNEL_NAME] }); client - .connect() - .then((data) => {}) - .catch(console.error); + .connect() + .then(data => {}) + .catch(console.error); function ping(element) { - let value = document.body.querySelector(element); + const value = document.body.querySelector(element); - client - .ping() - .then((data) => { - value.classList.add('success'); - value.innerText = 'Success!'; - }) - .catch((e) => { - value.classList.add('error'); - value.innerText = 'Failed!'; - }); + client + .ping() + .then(data => { + value.classList.add('success'); + value.innerText = 'Success!'; + }) + .catch(e => { + value.classList.add('error'); + value.innerText = 'Failed!'; + }); } function displayTwitchMessage(logoUrl, username, messageObject, fileteredMessage) { - const article = document.createElement('article'); - article.className = 'msg-container sender'; + const article = document.createElement('article'); + article.className = 'msg-container sender'; - article.innerHTML = messageTemplates.twitchTemplate; + article.innerHTML = messageTemplates.twitchTemplate; - const userImg = article.querySelector('.user-img'); - if (userImg) { - userImg.src = logoUrl; - } + const userImg = article.querySelector('.user-img'); + if (userImg) { + userImg.src = logoUrl; + } - const usernameHtml = article.querySelector('.username'); - if (usernameHtml) { - usernameHtml.innerText = username; - } + const usernameHtml = article.querySelector('.username'); + if (usernameHtml) { + usernameHtml.innerText = username; + } - const postTime = article.querySelector('.post-time'); + const postTime = article.querySelector('.post-time'); - if (postTime) { - postTime.innerText = getPostTime(); - } + if (postTime) { + postTime.innerText = getPostTime(); + } - article.appendChild(postTime); + article.appendChild(postTime); - const msg = article.querySelector('.msg-box'); - if (msg) { - messageObject.forEach((entry) => { - if (entry.text) { - msg.innerHTML += entry.text; - } else { - msg.innerHTML += entry.html; - } - }); - } + const msg = article.querySelector('.msg-box'); + if (msg) { + messageObject.forEach(entry => { + if (entry.text) { + msg.innerHTML += entry.text; + } else { + msg.innerHTML += entry.html; + } + }); + } - // Appends the message to the main chat box (shows the message) - showChatMessage(article, false); + // Appends the message to the main chat box (shows the message) + showChatMessage(article); - if (fileteredMessage) { - sound.playVoice(fileteredMessage, logoUrl, username, msg); - } + if (fileteredMessage) { + sound.playVoice(fileteredMessage, logoUrl, username, msg); + } - window.article = article; + window.article = article; } function getProfileImage(userid, username, message, fileteredMessage) { - // Get user Logo with access token - options = { - method: 'GET', - url: `https://api.twitch.tv/helix/users?id=${userid}`, - headers: { 'Client-ID': settings.TWITCH.CLIENT_ID, Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` }, - }; + // Get user Logo with access token + options = { + method: 'GET', + url: `https://api.twitch.tv/helix/users?id=${userid}`, + headers: { 'Client-ID': settings.TWITCH.CLIENT_ID, Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` } + }; - axios - .request(options) - .then((responseLogoUrl) => { - const logoUrl = responseLogoUrl.data.data[0].profile_image_url; - displayTwitchMessage(logoUrl, username, message, fileteredMessage); - }) - .catch((error) => { - console.error(error); - }); + axios + .request(options) + .then(responseLogoUrl => { + logoUrl = responseLogoUrl.data.data[0].profile_image_url; + displayTwitchMessage(logoUrl, username, message, fileteredMessage); + }) + .catch(error => { + console.error(error); + }); } function parseString(inputString) { - const regex = /()|([^<]+)/g; - const matches = inputString.match(regex) || []; - const result = []; + const regex = /()|([^<]+)/g; + const matches = inputString.match(regex) || []; + const result = []; - for (let i = 0; i < matches.length; i++) { - const match = matches[i].trim(); - if (match.startsWith(' { - if (self) { - return; - } - const emotes = tags.emotes || {}; - const emoteValues = Object.entries(emotes); - let fileteredMessage = message; - let emoteMessage = message; + if (self) { + return; + } + const emotes = tags.emotes || {}; + const emoteValues = Object.entries(emotes); + let filteredMessage = message; + let emoteMessage = message; - emoteValues.forEach((entry) => { - entry[1].forEach((lol) => { - const [start, end] = lol.split('-'); - let emote = ``; - emoteMessage = emoteMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), emote); - fileteredMessage = fileteredMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), ''); - }); + emoteValues.forEach(entry => { + entry[1].forEach(lol => { + const [start, end] = lol.split('-'); + const emote = ``; + emoteMessage = emoteMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), emote); + filteredMessage = filteredMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), ''); }); + }); - let messageObject = parseString(emoteMessage); - getProfileImage(tags['user-id'], tags['display-name'], messageObject, fileteredMessage); + const messageObject = parseString(emoteMessage); + getProfileImage(tags['user-id'], tags['display-name'], messageObject, filteredMessage); }); +function formatTwitchEmojis(emojis, name) { + emojis.forEach(emoji => { + const emojiToBeAdded = { + name: emoji.name, + shortcodes: [emoji.name], + url: emoji.images.url_1x, + category: name + }; + customEmojis.push(emojiToBeAdded); + }); + emojiPicker.customEmoji = customEmojis; +} + +function getTwitchGLobalEmotes() { + // Get user Logo with access token + options = { + method: 'GET', + url: 'https://api.twitch.tv/helix/chat/emotes/global', + headers: { + 'Client-ID': settings.TWITCH.CLIENT_ID, + Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` + } + }; + + axios + .request(options) + .then(responseLogoUrl => { + formatTwitchEmojis(responseLogoUrl.data.data, 'Twitch Global'); + // console.log(responseLogoUrl); + }) + .catch(error => { + console.error(error); + }); +} + +if (settings.TWITCH.OAUTH_TOKEN) { + getTwitchGLobalEmotes(); +} + module.exports = { sendMessage, ping, client }; diff --git a/src/main.js b/src/main.js index 0bd5fab..b1a134f 100644 --- a/src/main.js +++ b/src/main.js @@ -1,3 +1,5 @@ +/* global pythonPath, a */ + const { app, BrowserWindow, ipcMain } = require('electron'); const { writeIniFile } = require('write-ini-file'); const path = require('path'); @@ -14,197 +16,199 @@ let settings; let window; if (app.isPackaged) { - settingsPath = path.join(process.resourcesPath, './settings.ini'); - pythonPath = path.join(process.resourcesPath, './backend'); - resourcesPath = process.resourcesPath; + settingsPath = path.join(process.resourcesPath, './settings.ini'); + pythonPath = path.join(process.resourcesPath, './backend'); + resourcesPath = process.resourcesPath; } else { - settingsPath = path.join(resourcesPath, './config/settings.ini'); - pythonPath = path.join(resourcesPath, './backend'); + settingsPath = path.join(resourcesPath, './config/settings.ini'); + pythonPath = path.join(resourcesPath, './backend'); } // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (require('electron-squirrel-startup')) { - app.quit(); + app.quit(); } async function createWindow() { - if (!fs.existsSync(settingsPath)) { - console.log(resourcesPath); - await createIniFile(); - } else { - settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); + if (!fs.existsSync(settingsPath)) { + console.log(resourcesPath); + await createIniFile(); + } else { + settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); + } + + window = new BrowserWindow({ + icon: path.join(__dirname, '/images/icon-512.png'), + width: parseInt(settings.GENERAL.WIDTH), + height: parseInt(settings.GENERAL.HEIGHT), + x: parseInt(settings.GENERAL.POSITION_X), + y: parseInt(settings.GENERAL.POSITION_Y), + frame: false, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + enableRemoteModule: true } + }); - window = new BrowserWindow({ - icon: path.join(__dirname, '/images/icon-512.png'), - width: parseInt(settings.GENERAL.WIDTH), - height: parseInt(settings.GENERAL.HEIGHT), - x: parseInt(settings.GENERAL.POSITION_X), - y: parseInt(settings.GENERAL.POSITION_Y), - frame: false, - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - enableRemoteModule: true, - }, - }); + window.loadFile(path.join(__dirname, 'index.html')); - window.loadFile(path.join(__dirname, 'index.html')); + if (!app.isPackaged) { + window.webContents.openDevTools(); + } - if (!app.isPackaged) { - window.webContents.openDevTools(); - } + window.on('close', e => { + settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); // load newest settings in case anything changed after starting the program + const bounds = window.getBounds(); - window.on('close', (e) => { - settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); // load newest settings in case anything changed after starting the program - const bounds = window.getBounds(); + settings.GENERAL.WIDTH = bounds.width; + settings.GENERAL.HEIGHT = bounds.height; + settings.GENERAL.POSITION_X = bounds.x; + settings.GENERAL.POSITION_Y = bounds.y; - settings.GENERAL.WIDTH = bounds.width; - settings.GENERAL.HEIGHT = bounds.height; - settings.GENERAL.POSITION_X = bounds.x; - settings.GENERAL.POSITION_Y = bounds.y; - - fs.writeFileSync(settingsPath, ini.stringify(settings)); - }); + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }); } app.whenReady().then(() => { - createWindow(); + createWindow(); }); -app.on('window-all-closed', (event) => { - if (process.platform !== 'darwin') { - app.quit(); - } +app.on('window-all-closed', event => { + if (process.platform !== 'darwin') { + app.quit(); + } }); app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } }); app.on('before-quit', () => { - window.webContents.send('quit-event'); + window.webContents.send('quit-event'); }); ipcMain.on('resize-window', (event, width, height) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); - browserWindow.setSize(width, height); + const browserWindow = BrowserWindow.fromWebContents(event.sender); + browserWindow.setSize(width, height); }); -ipcMain.on('minimize-window', (event) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); - browserWindow.minimize(); +ipcMain.on('minimize-window', event => { + const browserWindow = BrowserWindow.fromWebContents(event.sender); + browserWindow.minimize(); }); -ipcMain.on('maximize-window', (event) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); +ipcMain.on('maximize-window', event => { + const browserWindow = BrowserWindow.fromWebContents(event.sender); - if (!browserWindow.isMaximized()) { - browserWindow.maximize(); - } else { - browserWindow.unmaximize(); - } + if (!browserWindow.isMaximized()) { + browserWindow.maximize(); + } else { + browserWindow.unmaximize(); + } }); -ipcMain.on('close-window', (event) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); - kill('loquendoBot_backend'); - browserWindow.close(); - app.quit(); +ipcMain.on('close-window', event => { + const browserWindow = BrowserWindow.fromWebContents(event.sender); + kill('loquendoBot_backend'); + browserWindow.close(); + app.quit(); }); -ipcMain.on('restart', (event) => { - app.relaunch(); +ipcMain.on('restart', event => { + app.relaunch(); }); -ipcMain.on('environment', (event) => { - event.returnValue = { resourcesPath, pythonPath, settingsPath, settings, isPackaged: app.isPackaged }; +ipcMain.on('environment', event => { + event.returnValue = { resourcesPath, pythonPath, settingsPath, settings, isPackaged: app.isPackaged }; }); async function createIniFile() { - await writeIniFile(settingsPath, { - GENERAL: { - VOICE_ENABLED: true, - NOTIFICATION_ENABLED: true, - POSITION_X: 0, - POSITION_Y: 0, - WIDTH: 1024, - HEIGHT: 768, - LANGUAGE: 'EN', - PORT: 9000, - VIEWERS_PANEL: false, - LOCATION: pythonPath, - }, - LANGUAGE: { - USE_DETECTION: false, - }, - TTS: { - USE_TTS: true, - PRIMARY_VOICE: '', - PRIMARY_TTS_LANGUAGE: 'EN', - SECONDARY_VOICE: '', - SECONDARY_TTS_LANGUAGE: 'EN', - }, - STT: { - USE_STT: false, - MICROPHONE_ID: 'default', - SELECTED_MICROPHONE: 'default', - MICROPHONE: 0, - LANGUAGE: 'vosk-model-small-es-0.42', - }, - AUDIO: { - USE_NOTIFICATION_SOUNDS: true, - NOTIFICATION_AUDIO_DEVICE: 0, - NOTIFICATION_SOUND: 0, - NOTIFICATION_VOLUME: 50, - SELECTED_TTS_AUDIO_DEVICE: 0, - TTS_AUDIO_DEVICE: 'default', - TTS_VOLUME: 50, - }, - THEME: { - USE_CUSTOM_THEME: false, - MAIN_COLOR_1: '#cdc1c1', - MAIN_COLOR_2: '#b12020', - MAIN_COLOR_3: '#6c4104', - MAIN_COLOR_4: '#532d2d', - TOP_BAR: '#c8ff00', - MID_SECTION: '#6b8578', - CHAT_BUBBLE_BG: '#447466', - CHAT_BUBBLE_HEADER: '#ffffff', - CHAT_BUBBLE_MESSAGE: '#b5b5b5', - }, - TWITCH: { - USE_TWITCH: false, - CHANNEL_NAME: '', - USERNAME: '', - USER_ID: '', - USER_LOGO_URL: '', - OAUTH_TOKEN: '', - CLIENT_ID: '2t206sj7rvtr1rutob3p627d13jch9', - }, - MODULES: { - USE_MODULES: false, - USE_VTUBER: false, - USE_CHATBUBBLE: false, - }, - AMAZON: { - USE_AMAZON: false, - ACCESS_KEY: '', - ACCESS_SECRET: '', - PRIMARY_VOICE: '', - SECONDARY_VOICE: '', - CHARACTERS_USED: 0, - }, - GOOGLE: { - USE_GOOGLE: false, - API_KEY: '', - PRIMARY_VOICE: '', - SECONDARY_VOICE: '', - CHARACTERS_USED: 0, - }, - }).then(() => { - settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); - }); + await writeIniFile(settingsPath, { + GENERAL: { + VOICE_ENABLED: true, + NOTIFICATION_ENABLED: true, + POSITION_X: 0, + POSITION_Y: 0, + WIDTH: 1024, + HEIGHT: 768, + LANGUAGE: 'EN', + PORT: 9000, + VIEWERS_PANEL: false, + LOCATION: pythonPath, + ZOOMLEVEL: 1 + }, + LANGUAGE: { + USE_DETECTION: false + }, + TTS: { + USE_TTS: true, + PRIMARY_VOICE: '', + PRIMARY_TTS_LANGUAGE: 'EN', + SECONDARY_VOICE: '', + SECONDARY_TTS_LANGUAGE: 'EN' + }, + STT: { + USE_STT: false, + MICROPHONE_ID: 'default', + SELECTED_MICROPHONE: 'default', + MICROPHONE: 0, + LANGUAGE: 'vosk-model-small-es-0.42' + }, + AUDIO: { + USE_NOTIFICATION_SOUNDS: true, + SELECTED_NOTIFICATION_AUDIO_DEVICE: 'default', + NOTIFICATION_AUDIO_DEVICE: 0, + NOTIFICATION_SOUND: 0, + NOTIFICATION_VOLUME: 50, + SELECTED_TTS_AUDIO_DEVICE: 0, + TTS_AUDIO_DEVICE: 'default', + TTS_VOLUME: 50 + }, + THEME: { + USE_CUSTOM_THEME: false, + MAIN_COLOR_1: '#cdc1c1', + MAIN_COLOR_2: '#b12020', + MAIN_COLOR_3: '#6c4104', + MAIN_COLOR_4: '#532d2d', + TOP_BAR: '#c8ff00', + MID_SECTION: '#6b8578', + CHAT_BUBBLE_BG: '#447466', + CHAT_BUBBLE_HEADER: '#ffffff', + CHAT_BUBBLE_MESSAGE: '#b5b5b5' + }, + TWITCH: { + USE_TWITCH: false, + CHANNEL_NAME: '', + USERNAME: '', + USER_ID: '', + USER_LOGO_URL: '', + OAUTH_TOKEN: '', + CLIENT_ID: '2t206sj7rvtr1rutob3p627d13jch9' + }, + MODULES: { + USE_MODULES: false, + USE_VTUBER: false, + USE_CHATBUBBLE: false + }, + AMAZON: { + USE_AMAZON: false, + ACCESS_KEY: '', + ACCESS_SECRET: '', + PRIMARY_VOICE: '', + SECONDARY_VOICE: '', + CHARACTERS_USED: 0 + }, + GOOGLE: { + USE_GOOGLE: false, + API_KEY: '', + PRIMARY_VOICE: '', + SECONDARY_VOICE: '', + CHARACTERS_USED: 0 + } + }).then(() => { + settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); + }); } diff --git a/src/modules/chat/index.html b/src/modules/chat/index.html index c961cd4..81150e7 100644 --- a/src/modules/chat/index.html +++ b/src/modules/chat/index.html @@ -1,23 +1,23 @@ - + - - Chat - - - - - - -
          -
          -
          -
          -
          - - - + + Chat + + + + + + +
          +
          +
          +
          +
          + + + diff --git a/src/modules/chat/main.css b/src/modules/chat/main.css index bea4e5b..ff681e4 100644 --- a/src/modules/chat/main.css +++ b/src/modules/chat/main.css @@ -1,171 +1,171 @@ body { - background-color: transparent; - font-family: 'FRAMDCN'; + background-color: transparent; + font-family: 'FRAMDCN'; } :root { - --variable: 2s; - --buttonBackground: #bf2c2c; + --variable: 2s; + --buttonBackground: #bf2c2c; } .thomas { - position: relative; - float: center; - display: inline-block; + position: relative; + float: center; + /* display: inline-block; */ } .speechbubble { - display: block; - bottom: 0; - position: absolute; - z-index: -1; + display: block; + bottom: 0; + position: absolute; + z-index: -1; } .fade-outx { - animation: fade-outx var(--variable) linear; + animation: fade-outx var(--variable) linear; } @keyframes fade-outx { - from { - opacity: 1; - } + from { + opacity: 1; + } - to { - opacity: 0; - } + to { + opacity: 0; + } } .fade-outxx { - animation: fade-outxx var(--variable) linear; + animation: fade-outxx var(--variable) linear; } @keyframes fade-outxx { - from { - opacity: 1; - } + from { + opacity: 1; + } - to { - opacity: 0; - } + to { + opacity: 0; + } } .bounce-in { - animation: bounce-in 1s ease; + animation: bounce-in 1s ease; } @keyframes bounce-in { - 0% { - opacity: 0; - transform: scale(0.3); - } + 0% { + opacity: 0; + transform: scale(0.3); + } - 50% { - opacity: 1; - transform: scale(1.05); - } + 50% { + opacity: 1; + transform: scale(1.05); + } - 70% { - transform: scale(0.9); - } + 70% { + transform: scale(0.9); + } - 100% { - transform: scale(1); - } + 100% { + transform: scale(1); + } } .bounce-inx { - animation: bounce-inx 1s ease; + animation: bounce-inx 1s ease; } @keyframes bounce-inx { - 0% { - opacity: 0; - } + 0% { + opacity: 0; + } - 50% { - opacity: 1; - } + 50% { + opacity: 1; + } } .msg-container { - position: static; - display: inline-block; - width: 100%; - padding-top: 10px; + position: static; + display: inline-block; + width: 100%; + padding-top: 10px; } .message-window { - height: calc(100% - 50px); - overflow: hidden; - overflow-y: hidden; - display: flex; - flex-direction: column; - width: 80%; - margin: auto; - background: transparent; + height: calc(100% - 50px); + overflow: hidden; + overflow-y: hidden; + display: flex; + flex-direction: column; + width: 80%; + margin: auto; + background: transparent; } .message-window::before { - content: ''; - flex: 1 0 0px; + content: ''; + flex: 1 0 0px; } .OptionPanel { - flex: 3; - display: none; - position: absolute; - top: 10px; - left: 0; - width: 100%; - height: calc(100% - 25px); - background: transparent; + flex: 3; + display: none; + position: absolute; + top: 10px; + left: 0; + width: 100%; + height: calc(100% - 25px); + background: transparent; } .OptionPanel.show { - display: block; + display: block; } .message { - text-align: left; - max-width: 100%; - height: auto; - min-width: 125px; - hyphens: auto; - bottom: 0; - right: 0; - float: right; - overflow-wrap: break-word; + text-align: left; + max-width: 100%; + height: auto; + min-width: 125px; + hyphens: auto; + bottom: 0; + right: 0; + float: right; + overflow-wrap: break-word; } .message { - position: relative; - border: 2px solid #ff80e1; - box-shadow: 0 2px 10px rgba(255, 128, 225, 0.5); - background: linear-gradient(45deg, rgb(15, 12, 41, 0.7), rgb(48, 43, 99, 0.7)); - /* background: linear-gradient(45deg, rgba(72, 0, 154, 0.7), rgba(138, 43, 226, 0.7)); */ + position: relative; + border: 2px solid #ff80e1; + box-shadow: 0 2px 10px rgba(255, 128, 225, 0.5); + background: linear-gradient(45deg, rgb(15, 12, 41, 0.7), rgb(48, 43, 99, 0.7)); + /* background: linear-gradient(45deg, rgba(72, 0, 154, 0.7), rgba(138, 43, 226, 0.7)); */ - color: white; - padding: 15px; - border-radius: 20px; + color: white; + padding: 15px; + border-radius: 20px; } - +/* .message::after { -} +} */ .arrow { - content: ''; - border: 2px solid #ff80e1; - position: absolute; - left: 50%; - top: 100%; - transform: translateX(-50%) rotate(180deg); - border-width: 10px; - border-style: solid; - border-color: transparent transparent rgb(255, 128, 225, 0.7) transparent; - color: #ff80e1; + content: ''; + border: 2px solid #ff80e1; + position: absolute; + left: 50%; + top: 100%; + transform: translateX(-50%) rotate(180deg); + border-width: 10px; + border-style: solid; + border-color: transparent transparent rgb(255, 128, 225, 0.7) transparent; + color: #ff80e1; } .sender { - color: #ff80e1; - font-size: 14pt; + color: #ff80e1; + font-size: 14pt; } diff --git a/src/modules/chat/main.js b/src/modules/chat/main.js index d4e92b9..5d01727 100644 --- a/src/modules/chat/main.js +++ b/src/modules/chat/main.js @@ -1,3 +1,5 @@ +/* global io */ + // Connect to the Socket.IO server const socket = io(); @@ -5,18 +7,18 @@ const socket = io(); socket.emit('message', 'Hello, Server!'); function getPostTime() { - const d = new Date(); - document.body.querySelectorAll('.container').innerHTML = d.getHours(); - const hours = d.getHours(); - const minutes = (d.getMinutes() < 10 ? '0' : '') + d.getMinutes(); - const time = `${hours}:${minutes}`; - return time; + const d = new Date(); + document.body.querySelectorAll('.container').innerHTML = d.getHours(); + const hours = d.getHours(); + const minutes = (d.getMinutes() < 10 ? '0' : '') + d.getMinutes(); + const time = `${hours}:${minutes}`; + return time; } function showChatMessage(article) { - const main = document.querySelector('#chatBox'); - main.appendChild(article); - main.scrollTop = main.scrollHeight; + const main = document.querySelector('#chatBox'); + main.appendChild(article); + main.scrollTop = main.scrollHeight; } let textStreamContainer; @@ -28,96 +30,96 @@ let x; let currentIndex = 0; let messageStream = ''; -let tempMessageObject = ''; -let fullMessageLength = 0; +const tempMessageObject = ''; +const fullMessageLength = 0; function getFullMessageLength(text) { - let fullMessageLength = 0; - text.forEach((element) => { - if (element.text) { - fullMessageLength += element.text.length; - } - element.html; - fullMessageLength += 1; - }); + let fullMessageLength = 0; + text.forEach(element => { + if (element.text) { + fullMessageLength += element.text.length; + } + // element.html; + fullMessageLength += 1; + }); - return fullMessageLength; + return fullMessageLength; } function streamText() { - // if (currentIndex < fullMessageLength) { + // if (currentIndex < fullMessageLength) { - // textStreamContainer.innerHTML += messageStream.filtered.charAt(currentIndex); - // currentIndex++; - // setTimeout(streamText, 50); - // } - if (currentIndex < messageStream.length) { - textStreamContainer.innerHTML += messageStream.charAt(currentIndex); - currentIndex++; - setTimeout(streamText, 50); - } else { - currentIndex = 0; - x.classList.add('fade-outx'); - } + // textStreamContainer.innerHTML += messageStream.filtered.charAt(currentIndex); + // currentIndex++; + // setTimeout(streamText, 50); + // } + if (currentIndex < messageStream.length) { + textStreamContainer.innerHTML += messageStream.charAt(currentIndex); + currentIndex++; + setTimeout(streamText, 50); + } else { + currentIndex = 0; + x.classList.add('fade-outx'); + } } function displayTwitchMessage(logoUrl, username, messageObject) { - if (!messageObject) { - return; + if (!messageObject) { + return; + } + + const root = document.querySelector(':root'); + root.style.setProperty('--variable', '5s'); + + const article = document.createElement('article'); + x = article; + + article.className = 'msg-container'; + + const placeMessage = ` +
          +
          +
          +
          +
          +
          + `.trim(); + + article.innerHTML = placeMessage; + const msg = article.querySelector('.message'); + + msg.innerHTML = `
          ${username}
          `; // \n${message}`; + + msg.style.fontSize = '12pt'; + + showChatMessage(article); + + const elements = document.getElementsByClassName('msg-container'); + if (elements.length > 1) { + elements[0].remove(); + } + + article.addEventListener('animationend', e => { + if (e.animationName === 'fade-outx') { + article.remove(); } + }); - const root = document.querySelector(':root'); - root.style.setProperty('--variable', '5s'); - - const article = document.createElement('article'); - x = article; - - article.className = 'msg-container'; - - const placeMessage = ` -
          -
          -
          -
          -
          -
          - `.trim(); - - article.innerHTML = placeMessage; - const msg = article.querySelector('.message'); - - msg.innerHTML = `
          ${username}
          `; //\n${message}`; - - msg.style.fontSize = '12pt'; - - showChatMessage(article); - - const elements = document.getElementsByClassName('msg-container'); - if (elements.length > 1) { + if (elements.length > 1) { + elements[0].classList.add('fade-outxx'); + elements[0].addEventListener('animationend', e => { + if (e.animationName === 'fade-outxx') { elements[0].remove(); - } - - article.addEventListener('animationend', (e) => { - if (e.animationName == 'fade-outx') { - article.remove(); - } + } }); - - if (elements.length > 1) { - elements[0].classList.add('fade-outxx'); - elements[0].addEventListener('animationend', (e) => { - if (e.animationName == 'fade-outxx') { - elements[0].remove(); - } - }); - } - // fullMessageLength = getFullMessageLength(messageObject); - messageStream = messageObject.filtered; - textStreamContainer = document.querySelector('.message'); - streamText(); + } + // fullMessageLength = getFullMessageLength(messageObject); + messageStream = messageObject.filtered; + textStreamContainer = document.querySelector('.message'); + streamText(); } // // Receive a message from the server socket.on('message', (logoUrl, username, message, messageDuration) => { - displayTwitchMessage(logoUrl, username, message); + displayTwitchMessage(logoUrl, username, message); }); diff --git a/src/modules/vtuber/css/about.css b/src/modules/vtuber/css/about.css index 768ed15..8db9f7a 100644 --- a/src/modules/vtuber/css/about.css +++ b/src/modules/vtuber/css/about.css @@ -20,8 +20,8 @@ body { padding-left: 40dip; padding-right: 10dip; vertical-align: top; - foreground-repeat: no-repeat; - foreground-position: 16dip 50%; + /* foreground-repeat: no-repeat; + foreground-position: 16dip 50%; */ background-repeat: no-repeat; background-position: 10dip 50%; background-size: 64dip 64dip; @@ -37,7 +37,7 @@ body { .title { font-weight: bold !important; - flow: column !important; + /* flow: column !important; */ text-align: left !important; margin: auto !important; width: min-content !important; @@ -86,12 +86,12 @@ img { } #button-bar { - flow: horizontal; + /* flow: horizontal; */ padding: 10dip; border-spacing: 10dip; margin: 0; - flow: horizontal; - horizontal-align: right; + /* flow: horizontal; */ + /* horizontal-align: right; */ } label { @@ -103,7 +103,7 @@ label { text-shadow: #fff 0px 1px; min-width: 4em; line-height: 2em; - vertical-align: middle; + /* vertical-align: middle; */ width: min-intrinsic; text-align: center; -} \ No newline at end of file +} diff --git a/src/modules/vtuber/css/main.css b/src/modules/vtuber/css/main.css index daf7def..59c2c06 100644 --- a/src/modules/vtuber/css/main.css +++ b/src/modules/vtuber/css/main.css @@ -1,386 +1,380 @@ * { - box-sizing: border-box; - image-rendering: optimize-quality; + box-sizing: border-box; + image-rendering: optimize-quality; } :disabled { - display: none; + display: none; } html { - overflow: hidden; + overflow: hidden; } body { - margin: 0; - padding: 16dip; - position: relative; - background-image: url('../png/grid.png'); - background-size: 70px; - background-repeat: repeat; + margin: 0; + padding: 16dip; + position: relative; + background-image: url('../png/grid.png'); + background-size: 70px; + background-repeat: repeat; } #controls { - height: 100%; - width: 100%; - /* flow: horizontal; */ - overflow: hidden; - display: flex; + height: 100%; + width: 100%; + /* flow: horizontal; */ + overflow: hidden; + display: flex; } #controls-left { - order: 2px solid cyan; - width: 7%; - height: 10%; - /* flow: vertical; */ - border-spacing: 1%; + order: 2px solid cyan; + width: 7%; + height: 10%; + /* flow: vertical; */ + border-spacing: 1%; } #controls-top { - height: 10%; - width: 100%; - /* flow: horizontal; */ - border-spacing: 1%; - margin-left: 10px; + height: 10%; + width: 100%; + /* flow: horizontal; */ + border-spacing: 1%; + margin-left: 10px; } #meters { - display: flex; - height: 50vh; - /* flow: horizontal; */ - /* border-spacing: *; */ - position: relative; + display: flex; + height: 50vh; + /* flow: horizontal; */ + /* border-spacing: *; */ + position: relative; } #meter-microphone { - margin-left: 10%; - margin-right: 10%; + margin-left: 10%; + margin-right: 10%; } #meter-delay { - margin-right: 20%; + margin-right: 20%; } #meter-microphone, #meter-delay { - height: 45vh; - width: 25%; - background-repeat: no-repeat; + height: 45vh; + width: 25%; + background-repeat: no-repeat; } -input[type='vslider']>button.slider { - background-size: 100% auto; - border-radius: 0; - width: 275%; - height: 5%; - background-position: 0 50%; - border-width: 0; +input[type='vslider'] > button.slider { + background-size: 100% auto; + border-radius: 0; + width: 275%; + height: 5%; + background-position: 0 50%; + border-width: 0; } button { - height: 50px; - width: 50px; - background-size: cover; - overflow: hidden; - border-style: none; - background-color: transparent; + height: 50px; + width: 50px; + background-size: cover; + overflow: hidden; + border-style: none; + background-color: transparent; } -#meter-microphone>button.slider { - background-image: url('../png/controls/meters/left.png'); +#meter-microphone > button.slider { + background-image: url('../png/controls/meters/left.png'); } -#meter-delay>button.slider { - background-image: url('../png/controls/meters/right.png'); +#meter-delay > button.slider { + background-image: url('../png/controls/meters/right.png'); } #meter-microphone { - color: #2ebe38; + color: #2ebe38; } #meter-delay { - color: #453be2; + color: #453be2; } #slider-left { - left: -25%; + left: -25%; } #slider-right { - right: -25%; + right: -25%; } #buttons-left { - width: 100%; - height: 100%; - box-shadow: none; + width: 100%; + height: 100%; + box-shadow: none; } #buttons-top { - height: 50px; - width: 100%; - display: flex; + height: 50px; + width: 100%; + display: flex; } #buttons-left button { - width: 50; - height: 50px; - display: flex; - background-size: cover; - overflow: hidden; + width: 50; + height: 50px; + display: flex; + background-size: cover; + overflow: hidden; } #buttons-top button { - background-size: auto 100%; - background-position: 50% 50%; - border-width: 0; - border-radius: 0; + background-size: auto 100%; + background-position: 50% 50%; + border-width: 0; + border-radius: 0; } #buttons-left button:active, #about:active, #close:active { - filter: brightness(-10%); + filter: brightness(-10%); } popup[role='tooltip'] { - color: white; - background: rgba(0, 0, 0, 0.666); - border-width: 0; - padding: 0.333em; - font-size: 1.25em; - font-family: Calibri; + color: white; + background: rgba(0, 0, 0, 0.666); + border-width: 0; + padding: 0.333em; + font-size: 1.25em; + font-family: Calibri; } #microphone-device { - background-image: url('../png/controls/buttons/left/mic.png'); + background-image: url('../png/controls/buttons/left/mic.png'); } #background-color { - background-image: url('../png/controls/buttons/left/bg.png'); + background-image: url('../png/controls/buttons/left/bg.png'); } #open-file { - background-image: url('../png/controls/buttons/left/open.png'); + background-image: url('../png/controls/buttons/left/open.png'); } #save-file { - background-image: url('../png/controls/buttons/left/save.png'); + background-image: url('../png/controls/buttons/left/save.png'); } /* TOP ROW BUTTONS */ button.mouth-image.border-default { - background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); - position: absolute; - width: 50px; - height: 50px; - top: 0; - bottom: 0; + background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); + position: absolute; + width: 50px; + height: 50px; + top: 0; + bottom: 0; } button.mouth-image.border-add { - background-image: url('../png/controls/buttons/top/avatar-change/border/add.png'); + background-image: url('../png/controls/buttons/top/avatar-change/border/add.png'); } button.mouth-image:active { - filter: brightness(-10%); + filter: brightness(-10%); } button.mouth-image::before { - position: absolute; - top: 5%; - right: 10%; - width: 50px; - height: 66%; - background-size: 100% 100%; - z-index: -1; + position: absolute; + top: 5%; + right: 10%; + width: 50px; + height: 66%; + background-size: 100% 100%; + z-index: -1; } button.mouth-image::after { - position: absolute; - top: 69%; - left: 37%; - width: 50px; - height: 35%; - transform: translate(-50%, -50%); - background-size: 100% 100%; + position: absolute; + top: 69%; + left: 37%; + width: 50px; + height: 35%; + transform: translate(-50%, -50%); + background-size: 100% 100%; } #closed-mouth-image.border-default::before { - background-image: url('../png/avatars/crab/closed.png'); + background-image: url('../png/avatars/crab/closed.png'); } #closed-mouth-image::after { - background-image: url('../png/controls/buttons/top/avatar-change/closed.png'); + background-image: url('../png/controls/buttons/top/avatar-change/closed.png'); } #open-mouth-image.border-default::before { - background-image: url('../png/avatars/crab/open.png'); + background-image: url('../png/avatars/crab/open.png'); } #open-mouth-image::after { - background-image: url('../png/controls/buttons/top/avatar-change/open.png'); + background-image: url('../png/controls/buttons/top/avatar-change/open.png'); } #closed-mouth-blinking-image.border-default::before { - background-image: url('../png/avatars/crab/closed-blink.png'); + background-image: url('../png/avatars/crab/closed-blink.png'); } #closed-mouth-blinking-image::after { - background-image: url('../png/controls/buttons/top/avatar-change/closed-blink.png'); + background-image: url('../png/controls/buttons/top/avatar-change/closed-blink.png'); } #open-mouth-blinking-image.border-default::before { - background-image: url('../png/avatars/crab/open-blink.png'); + background-image: url('../png/avatars/crab/open-blink.png'); } #open-mouth-blinking-image::after { - background-image: url('../png/controls/buttons/top/avatar-change/open-blink.png'); + background-image: url('../png/controls/buttons/top/avatar-change/open-blink.png'); } button.motion { - /* background-image: url('../png/controls/buttons/top/motion/template.png'); */ - position: relative; - /* var(x): 0dip; + /* background-image: url('../png/controls/buttons/top/motion/template.png'); */ + position: relative; + /* var(x): 0dip; var(y): height(33%); */ - height: 50px; - width: 50px; + height: 50px; + width: 50px; } - .closed-mouth-motion { - background-image: url('../png/controls/buttons/top/motion/closed.png'); - box-sizing: border-box; - image-rendering: optimize-quality; - height: 50px; - width: 50px; - background-color: #9bccd4; + background-image: url('../png/controls/buttons/top/motion/closed.png'); + box-sizing: border-box; + image-rendering: optimize-quality; + height: 50px; + width: 50px; + background-color: #9bccd4; } .test { - width: 50px; - height: 50px; - background-size: cover; - overflow: hidden; + width: 50px; + height: 50px; + background-size: cover; + overflow: hidden; } .avatar-change { - background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); - background-size: cover; - width: 50px; - height: 50px; - position: relative; - left: -5px; + background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); + background-size: cover; + width: 50px; + height: 50px; + position: relative; + left: -5px; } .border { - background-image: url('../png/controls/buttons/top/motion/border.png'); - background-size: cover; - width: 50px; - height: 50px; - position: relative; - top: -50px; + background-image: url('../png/controls/buttons/top/motion/border.png'); + background-size: cover; + width: 50px; + height: 50px; + position: relative; + top: -50px; } .open-mouth-motion { - background-image: url('../png/controls/buttons/top/motion/open.png'); - box-sizing: border-box; - image-rendering: optimize-quality; - height: 50px; - width: 50px; + background-image: url('../png/controls/buttons/top/motion/open.png'); + box-sizing: border-box; + image-rendering: optimize-quality; + height: 50px; + width: 50px; } .mouth-transition { - background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); - box-sizing: border-box; - image-rendering: optimize-quality; - height: 50px; - width: 50px; - background-position: 50% 50%; - background-color: yellow; + background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); + box-sizing: border-box; + image-rendering: optimize-quality; + height: 50px; + width: 50px; + background-position: 50% 50%; + background-color: yellow; } .mouth-transitionx { - background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); - box-sizing: border-box; - image-rendering: optimize-quality; - height: 50px; - width: 50px; - background-position: 50% 50%; - background-color: red; + background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); + box-sizing: border-box; + image-rendering: optimize-quality; + height: 50px; + width: 50px; + background-position: 50% 50%; + background-color: red; } - #mouth-transition::before { - background-color: red; - background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); + background-color: red; + background-image: url('../png/controls/buttons/top/avatar-change/border/default.png'); } button.motion::before { - position: absolute; - width: 50px; - height: 90%; - background-size: 105% 105%; - transform: translate(-11%, -11%); - /* background-position: -50% -50%; */ - overflow: hidden; - z-index: -1; - /* hit-margin: -999px; */ + position: absolute; + width: 50px; + height: 90%; + background-size: 105% 105%; + transform: translate(-11%, -11%); + /* background-position: -50% -50%; */ + overflow: hidden; + z-index: -1; + /* hit-margin: -999px; */ } #closed-mouth-motion::before { - background-color: #2ebe38; + background-color: #2ebe38; } #open-mouth-motion::before { - background-image: url('../png/controls/buttons/top/motion/open.png'); - height: 50px; - width: 50px; - pointer-events: none; - background-color: yellow; + background-image: url('../png/controls/buttons/top/motion/open.png'); + height: 50px; + width: 50px; + pointer-events: none; + background-color: yellow; } button.motion::after { - position: absolute; - width: 80%; - height: 80%; - background-color: red; - overflow: hidden; - z-index: -1; - transform: translate(11%, 11%); - /* hit-margin: -999px; */ + position: absolute; + width: 80%; + height: 80%; + background-color: red; + overflow: hidden; + z-index: -1; + transform: translate(11%, 11%); + /* hit-margin: -999px; */ } #set-hotkey { - background-image: url('../png/controls/buttons/top/hotkey/set/default.png'); + background-image: url('../png/controls/buttons/top/hotkey/set/default.png'); } #hotkey-mode { - background-image: url('../png/controls/buttons/top/hotkey/mode/0.png'); + background-image: url('../png/controls/buttons/top/hotkey/mode/0.png'); } #delete-state { - background-image: url('../png/controls/buttons/right/delete.png'); + background-image: url('../png/controls/buttons/right/delete.png'); } #about { - background-image: url('../png/controls/buttons/top/info.png'); + background-image: url('../png/controls/buttons/top/info.png'); } #close { - background-image: url('../png/controls/buttons/top/close.png'); + background-image: url('../png/controls/buttons/top/close.png'); } #avatar { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - width: 40%; - height: width(100%); + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 40%; + height: width(100%); } - -menu.popup { - /* box-shadow: 3px 3px 1px rgba(0, 0, 0, 0.692); */ -} \ No newline at end of file diff --git a/src/modules/vtuber/html/about.html b/src/modules/vtuber/html/about.html index 5a1d1a6..36cf9cb 100644 --- a/src/modules/vtuber/html/about.html +++ b/src/modules/vtuber/html/about.html @@ -38,4 +38,4 @@ - \ No newline at end of file + diff --git a/src/modules/vtuber/index.html b/src/modules/vtuber/index.html index 084bdbf..2568880 100644 --- a/src/modules/vtuber/index.html +++ b/src/modules/vtuber/index.html @@ -1,76 +1,76 @@ - + - - TransTube - - - - + + TransTube + + + + - - -
          -
          -
          - - -
          -
          - - - - -
          -
          -
          -
          -
          - -
          -
          - -
          -
          - -
          -
          - -
          -
          - -
          -
          -
          - -
          -
          -
          - -
          -
          - - - - -
          -
          + + +
          +
          +
          + +
          +
          + + + + +
          +
          +
          +
          +
          + +
          +
          + +
          +
          + +
          +
          + +
          +
          + +
          +
          +
          + +
          +
          +
          + +
          +
          - -
        • change image
        • -
        • remove image
        • -
          - + + + +
          +
          +
          + + +
        • change image
        • +
        • remove image
        • +
          + diff --git a/src/modules/vtuber/js/main.js b/src/modules/vtuber/js/main.js index e5626a1..78117fb 100644 --- a/src/modules/vtuber/js/main.js +++ b/src/modules/vtuber/js/main.js @@ -10,311 +10,270 @@ globalThis.MOUTH_IS_OPEN = false; globalThis.BLINKING = false; function avatarBlink() { - const state = globalThis.BLINKING ? './png/avatars/crab/closed-blink.png' : './png/avatars/crab/closed.png'; - return state; + const state = globalThis.BLINKING ? './png/avatars/crab/closed-blink.png' : './png/avatars/crab/closed.png'; + return state; } function avatarTalk() { - let state = globalThis.MOUTH_IS_OPEN ? './png/avatars/crab/open.png' : './png/avatars/crab/closed.png'; - if (globalThis.BLINK) { - state = './png/avatars/crab/open-blink.png'; - } + let state = globalThis.MOUTH_IS_OPEN ? './png/avatars/crab/open.png' : './png/avatars/crab/closed.png'; + if (globalThis.BLINK) { + state = './png/avatars/crab/open-blink.png'; + } - return state; + return state; } function adjustWindow() { - // const [width, height] = Window.this.screenBox('frame', 'dimension'); - // const w = width * 0.666; - // const h = height * 0.666; - // Window.this.move(width / 2 - w / 2, height / 2 - h / 2, w, h, true); + // const [width, height] = Window.this.screenBox('frame', 'dimension'); + // const w = width * 0.666; + // const h = height * 0.666; + // Window.this.move(width / 2 - w / 2, height / 2 - h / 2, w, h, true); } adjustWindow(); async function monitorDelay() { - setInterval(() => { }); + setInterval(() => {}); } monitorDelay(); function animate() { - let avatarCurr = $('#avatar').src; + let avatarCurr = $('#avatar').src; - const animation = globalThis.MOUTH_IS_OPEN - ? globalThis.CHOSEN_OPEN_MOUTH_ANIMATION - : globalThis.CHOSEN_CLOSED_MOUTH_ANIMATION; + const animation = globalThis.MOUTH_IS_OPEN ? globalThis.CHOSEN_OPEN_MOUTH_ANIMATION : globalThis.CHOSEN_CLOSED_MOUTH_ANIMATION; - globalThis.ANIMATION = animation; + globalThis.ANIMATION = animation; - clearInterval(globalThis.ANIMATION_INTERVAL); + clearInterval(globalThis.ANIMATION_INTERVAL); - globalThis.ANIMATION_INTERVAL = setInterval(() => { - // console.log(globalThis.ANIMATION_INTERVAL); - const t = Date.now() / 1000; - const { x, y } = MOTION[animation](t); - const left = -50 - x * 5; - const top = -50 - y * 5; - document.body.querySelector('#avatar').style.transform = `translate(${left}%, ${top}%)`; + globalThis.ANIMATION_INTERVAL = setInterval(() => { + // console.log(globalThis.ANIMATION_INTERVAL); + const t = Date.now() / 1000; + const { x, y } = MOTION[animation](t); + const left = -50 - x * 5; + const top = -50 - y * 5; + document.body.querySelector('#avatar').style.transform = `translate(${left}%, ${top}%)`; - avatarCurr = $('#avatar').src; + avatarCurr = $('#avatar').src; - if (globalThis.MOUTH_IS_OPEN === false) { - // const avatarNew = avatarCurr.replace('open', 'closed'); + if (globalThis.MOUTH_IS_OPEN === false) { + // const avatarNew = avatarCurr.replace('open', 'closed'); - const avatarNew = avatarTalk(); + const avatarNew = avatarTalk(); - if (avatarNew !== avatarCurr) { - $('#avatar').src = avatarNew; - avatarCurr = avatarNew; - } - } else { - // const avatarNew = avatarCurr.replace('closed', 'open'); + if (avatarNew !== avatarCurr) { + $('#avatar').src = avatarNew; + avatarCurr = avatarNew; + } + } else { + // const avatarNew = avatarCurr.replace('closed', 'open'); - const avatarNew = avatarBlink(); + const avatarNew = avatarBlink(); - if (avatarNew !== avatarCurr) { - $('#avatar').src = avatarNew; - avatarCurr = avatarNew; - } - } - }); + if (avatarNew !== avatarCurr) { + $('#avatar').src = avatarNew; + avatarCurr = avatarNew; + } + } + }); } animate(); function updateMeter() { - setInterval(() => { - // let volume = 50//Window.this.xcall('get_volume'); - const volume = 100; - document.body.querySelector('#meter-microphone').value = volume; + setInterval(() => { + // let volume = 50//Window.this.xcall('get_volume'); + const volume = 100; + document.body.querySelector('#meter-microphone').value = volume; - const delayVolume = document.body.querySelector('#meter-delay').value; - const delaySlider = document.body.querySelector('#meter-delay').value; + const delayVolume = document.body.querySelector('#meter-delay').value; + const delaySlider = document.body.querySelector('#meter-delay').value; - const microphoneVolume = document.body.querySelector('#meter-microphone').value; - const microphoneSlider = document.body.querySelector('#meter-microphone').value; + const microphoneVolume = document.body.querySelector('#meter-microphone').value; + const microphoneSlider = document.body.querySelector('#meter-microphone').value; - if (microphoneVolume > microphoneSlider) { - document.body.querySelector('#meter-delay').value = 100; - } else { - document.body.querySelector('#meter-delay').value = Math.max(0, delayVolume - 1); - } + if (microphoneVolume > microphoneSlider) { + document.body.querySelector('#meter-delay').value = 100; + } else { + document.body.querySelector('#meter-delay').value = Math.max(0, delayVolume - 1); + } - if (delayVolume > delaySlider) { - if (globalThis.MOUTH_IS_OPEN === false) { - globalThis.MOUTH_IS_OPEN = true; - // console.log('monitor delay => delayVolume > delaySlider'); - $('#avatar').src = avatarTalk(); + if (delayVolume > delaySlider) { + if (globalThis.MOUTH_IS_OPEN === false) { + globalThis.MOUTH_IS_OPEN = true; + // console.log('monitor delay => delayVolume > delaySlider'); + $('#avatar').src = avatarTalk(); - animate(); - } - } else if (globalThis.MOUTH_IS_OPEN === true) { - globalThis.MOUTH_IS_OPEN = false; - // console.log('monitor delay => else'); - $('#avatar').src = avatarTalk(); - animate(); - } - }); + animate(); + } + } else if (globalThis.MOUTH_IS_OPEN === true) { + globalThis.MOUTH_IS_OPEN = false; + // console.log('monitor delay => else'); + $('#avatar').src = avatarTalk(); + animate(); + } + }); } updateMeter(); function animateButton(button, animation = 'motionless') { - clearInterval(button.BUTTON_INTERVAL); - const animatedButton = document.body.querySelector(button); - animatedButton.BUTTON_INTERVAL = setInterval(() => { - const t = Date.now() / 1000; - const { x, y } = MOTION[animation](t); - const left = 50 + x * 50; - const top = 50 - y * 50; + clearInterval(button.BUTTON_INTERVAL); + const animatedButton = document.body.querySelector(button); + animatedButton.BUTTON_INTERVAL = setInterval(() => { + const t = Date.now() / 1000; + const { x, y } = MOTION[animation](t); + const left = 50 + x * 50; + const top = 50 - y * 50; - // animatedButton + // animatedButton - // animatedButton.style.x = left; - // animatedButton.style.y = (top + 500) * -1; - // animatedButton.style.transform = `translate(${left}%, -${top + 500}%)`; - }); + // animatedButton.style.x = left; + // animatedButton.style.y = (top + 500) * -1; + // animatedButton.style.transform = `translate(${left}%, -${top + 500}%)`; + }); } -animateButton( - '#closed-mouth-motion', - globalThis.CHOSEN_CLOSED_MOUTH_ANIMATION, -); +animateButton('#closed-mouth-motion', globalThis.CHOSEN_CLOSED_MOUTH_ANIMATION); animateButton('#open-mouth-motion', globalThis.CHOSEN_OPEN_MOUTH_ANIMATION); function blink() { - let avatarCurr = $('#avatar').src; - setInterval(() => { - avatarCurr = $('#avatar').src; - const n = Date.now() % 3200; - if (n > 3000) { - globalThis.BLINKING = true; - const avatarNew = avatarBlink(); - if (avatarCurr !== avatarNew) { - document.body.querySelector('#avatar').src = avatarNew; - avatarCurr = avatarNew; - } - } else { - globalThis.BLINKING = false; - // const avatarNew = avatarCurr.replace('-blink', ''); - const avatarNew = avatarBlink(); - if (avatarCurr !== avatarNew) { - document.body.querySelector('#avatar').src = avatarNew; - avatarCurr = avatarNew; - } - } - }); + let avatarCurr = $('#avatar').src; + setInterval(() => { + avatarCurr = $('#avatar').src; + const n = Date.now() % 3200; + if (n > 3000) { + globalThis.BLINKING = true; + const avatarNew = avatarBlink(); + if (avatarCurr !== avatarNew) { + document.body.querySelector('#avatar').src = avatarNew; + avatarCurr = avatarNew; + } + } else { + globalThis.BLINKING = false; + // const avatarNew = avatarCurr.replace('-blink', ''); + const avatarNew = avatarBlink(); + if (avatarCurr !== avatarNew) { + document.body.querySelector('#avatar').src = avatarNew; + avatarCurr = avatarNew; + } + } + }); } blink(); async function _cycleAnimations() { - const animations = Object.keys(MOTION); - let i = 0; - while (true) { - const key = animations[i % animations.length]; - animate(key); - Window.this.caption = key; - i++; - await new Promise((r) => setTimeout(r, 2000)); - } + const animations = Object.keys(MOTION); + let i = 0; + while (true) { + const key = animations[i % animations.length]; + animate(key); + Window.this.caption = key; + i++; + await new Promise(resolve => setTimeout(resolve, 2000)); + } } -$(document).on( - '~mousedown', - '#closed-mouth-motion, #open-mouth-motion', - motionButtonEvent, -); +$(document).on('~mousedown', '#closed-mouth-motion, #open-mouth-motion', motionButtonEvent); -$(document).on( - '~doubleclick', - '#closed-mouth-motion, #open-mouth-motion', - motionButtonEvent, -); +$(document).on('~doubleclick', '#closed-mouth-motion, #open-mouth-motion', motionButtonEvent); function motionButtonEvent(evt) { - const { target: button } = evt; - button.attributes.counter = button.attributes.counter || 0; + const { target: button } = evt; + button.attributes.counter = button.attributes.counter || 0; - if (evt.button === 1) { - button.attributes.counter++; - } else if (evt.button === 2) { - button.attributes.counter--; - } + if (evt.button === 1) { + button.attributes.counter++; + } else if (evt.button === 2) { + button.attributes.counter--; + } - const color = [ - 'white', - '#9BCCD4', - '#8087D6', - '#AB65CF', - '#E7FD5B', - '#EC9F45', - '#E24555', - ][mod(button.attributes.counter, 7)]; - button.style.variable('color', color); + const color = ['white', '#9BCCD4', '#8087D6', '#AB65CF', '#E7FD5B', '#EC9F45', '#E24555'][mod(button.attributes.counter, 7)]; + button.style.variable('color', color); - const animation = [ - 'motionless', - 'vibing', - 'shaking', - 'shakingMore', - 'bouncy', - 'excited', - 'nervous', - ][mod(button.attributes.counter, 7)]; + const animation = ['motionless', 'vibing', 'shaking', 'shakingMore', 'bouncy', 'excited', 'nervous'][mod(button.attributes.counter, 7)]; - animateButton(button, animation); + animateButton(button, animation); - if (button.id === 'closed-mouth-motion') { - globalThis.CHOSEN_CLOSED_MOUTH_ANIMATION = animation; - animate(); - } else if (button.id === 'open-mouth-motion') { - globalThis.CHOSEN_OPEN_MOUTH_ANIMATION = animation; - animate(); - } + if (button.id === 'closed-mouth-motion') { + globalThis.CHOSEN_CLOSED_MOUTH_ANIMATION = animation; + animate(); + } else if (button.id === 'open-mouth-motion') { + globalThis.CHOSEN_OPEN_MOUTH_ANIMATION = animation; + animate(); + } } function animateMouthButton() { - setInterval(() => { - const n = Date.now() % 1200; - document.body.querySelector('.mouth-transition').style.backgroundImage = `url('../vtuber/png/controls/buttons/top/motion/${n > 600 ? 'open' : 'closed' - }.png')`; - }); + setInterval(() => { + const n = Date.now() % 1200; + document.body.querySelector('.mouth-transition').style.backgroundImage = `url('../vtuber/png/controls/buttons/top/motion/${ + n > 600 ? 'open' : 'closed' + }.png')`; + }); } animateMouthButton(); function mod(n, m) { - return ((n % m) + m) % m; + return ((n % m) + m) % m; } globalThis.CURRENT_BUTTON = null; -$(document).on( - 'click', - '.mouth-image.border-default:not(:first-of-type)', - (evt, el) => { - globalThis.CURRENT_BUTTON = el; - el.popup($('menu')); - }, -); +$(document).on('click', '.mouth-image.border-default:not(:first-of-type)', (evt, el) => { + globalThis.CURRENT_BUTTON = el; + el.popup($('menu')); +}); function loadImage() { - const filename = Window.this.selectFile({ - mode: 'open', - filter: - 'image files (*.bmp,*.dib,*.gif,*.png,*.apng,*.jpg,*.jpeg,*.jiff)|*.bmp;*.dib;*.gif;*.png;*.apng;*.jpg;*.jpeg;*.jiff', - caption: 'select image for closed mouth...', - }); - return filename; + const filename = Window.this.selectFile({ + mode: 'open', + filter: 'image files (*.bmp,*.dib,*.gif,*.png,*.apng,*.jpg,*.jpeg,*.jiff)|*.bmp;*.dib;*.gif;*.png;*.apng;*.jpg;*.jpeg;*.jiff', + caption: 'select image for closed mouth...' + }); + return filename; } function changeImage(evt, el) { - // setTimeout to avoid context menu popping up - setTimeout(() => { - if (el.matches('.mouth-image:first-of-type, .mouth-image.border-add')) { - globalThis.CURRENT_BUTTON = el; - } + // setTimeout to avoid context menu popping up + setTimeout(() => { + if (el.matches('.mouth-image:first-of-type, .mouth-image.border-add')) { + globalThis.CURRENT_BUTTON = el; + } - const filename = loadImage(); - if (!filename) return; - const which = globalThis.CURRENT_BUTTON.id - .match(/closed|open|blink/g) - .join('-'); - document.style.variable(which, `url('${filename}')`); + const filename = loadImage(); + if (!filename) return; + const which = globalThis.CURRENT_BUTTON.id.match(/closed|open|blink/g).join('-'); + document.style.variable(which, `url('${filename}')`); - globalThis.CURRENT_BUTTON.classList.add('border-default'); - globalThis.CURRENT_BUTTON.classList.remove('border-add'); - }); + globalThis.CURRENT_BUTTON.classList.add('border-default'); + globalThis.CURRENT_BUTTON.classList.remove('border-add'); + }); } -$(document).on( - 'click', - '.mouth-image:first-of-type, .mouth-image.border-add', - changeImage, -); +$(document).on('click', '.mouth-image:first-of-type, .mouth-image.border-add', changeImage); $(document).on('click', '#change-image', changeImage); $(document).on('click', '#remove-image', (evt, el) => { - globalThis.CURRENT_BUTTON.classList.remove('border-default'); - globalThis.CURRENT_BUTTON.classList.add('border-add'); + globalThis.CURRENT_BUTTON.classList.remove('border-default'); + globalThis.CURRENT_BUTTON.classList.add('border-add'); - const which = globalThis.CURRENT_BUTTON.id - .match(/closed|open|blink/g) - .join('-'); - document.style.variable(which, null); + const which = globalThis.CURRENT_BUTTON.id.match(/closed|open|blink/g).join('-'); + document.style.variable(which, null); }); movableView('body'); // Window.this.on('activate', (evt) => { -// if (evt.reason === 0) { -// document.classList.add('transparent'); -// } else { -// document.classList.remove('transparent'); -// } +// if (evt.reason === 0) { +// document.classList.add('transparent'); +// } else { +// document.classList.remove('transparent'); +// } // }); // setInterval(() => (Window.this.isTopmost = true)); diff --git a/src/modules/vtuber/js/motion.js b/src/modules/vtuber/js/motion.js index 35f9893..feb770a 100644 --- a/src/modules/vtuber/js/motion.js +++ b/src/modules/vtuber/js/motion.js @@ -1,65 +1,65 @@ import { pnoise1 } from './perlin_noise.js'; export default { - motionless, - vibing, - shaking, - shakingMore, - bouncy, - excited, - nervous, + motionless, + vibing, + shaking, + shakingMore, + bouncy, + excited, + nervous }; function motionless(t) { - return { x: 0, y: 0 }; + return { x: 0, y: 0 }; } function clamp01(number) { - return Math.max(0, Math.min(number, 1)); + return Math.max(0, Math.min(number, 1)); } function _shake(t, amount, velocity) { - let num = clamp01(pnoise1(t * velocity, 0)); - let num2 = clamp01(pnoise1(t * velocity, 50)); - num = num * 2 - 1; - num2 = num2 * 2 - 1; - return { - x: amount * (num * Math.sqrt(1 - (num2 * num2) / 2)), - y: amount * (num2 * Math.sqrt(1 - (num * num) / 2)), - }; + let num = clamp01(pnoise1(t * velocity, 0)); + let num2 = clamp01(pnoise1(t * velocity, 50)); + num = num * 2 - 1; + num2 = num2 * 2 - 1; + return { + x: amount * (num * Math.sqrt(1 - (num2 * num2) / 2)), + y: amount * (num2 * Math.sqrt(1 - (num * num) / 2)) + }; } function _jumpy(t, amountX, amountY, velocity) { - t *= velocity; - const num = t % 1; - const num2 = -8 * num * (num - 1) - 1; - let num3 = t % 2; - if (num3 > 1) { - num3 = 2 - num3; - } - return { x: (num3 * 2 - 1) * amountX, y: num2 * amountY }; + t *= velocity; + const num = t % 1; + const num2 = -8 * num * (num - 1) - 1; + let num3 = t % 2; + if (num3 > 1) { + num3 = 2 - num3; + } + return { x: (num3 * 2 - 1) * amountX, y: num2 * amountY }; } function vibing(t) { - return _shake(t, 0.7, 0.5); + return _shake(t, 0.7, 0.5); } function shaking(t) { - return _shake(t, 0.3, 10); + return _shake(t, 0.3, 10); } function shakingMore(t) { - return _shake(t, 1, 8); + return _shake(t, 1, 8); } function bouncy(t) { - return _jumpy(t, 0, 0.5, 1); + return _jumpy(t, 0, 0.5, 1); } function excited(t) { - return _jumpy(t, 0.5, 0.5, 2); + return _jumpy(t, 0.5, 0.5, 2); } function nervous(t) { - return _jumpy(t, 1, 1, 4); -} \ No newline at end of file + return _jumpy(t, 1, 1, 4); +} diff --git a/src/modules/vtuber/js/movable_view.js b/src/modules/vtuber/js/movable_view.js index 0b799ea..42968d4 100644 --- a/src/modules/vtuber/js/movable_view.js +++ b/src/modules/vtuber/js/movable_view.js @@ -1,64 +1,65 @@ if (!Number.prototype.limit) { - Number.prototype.limit = function (min, max) { - if (this < min) return min; - if (this > max) return max; - return this; - }; + // eslint-disable-next-line no-extend-native + Number.prototype.limit = function (min, max) { + if (this < min) return min; + if (this > max) return max; + return this; + }; } function movableView(s, screenBound = false) { - let xoff; let yoff; let minXY; let maxX; let - maxY; - let dragging = false; + let xoff; + let yoff; + let minXY; + let maxX; + let maxY; + let dragging = false; - function screenBounds() { - if (screenBound) { - [maxX, maxY] = Window.this.screenBox('workarea', 'dimension'); - const [w, h] = Window.this.box('dimension', 'border'); - maxX -= w; - maxY -= h; - minXY = 0; - } else { - maxX = Number.MAX_SAFE_INTEGER; - maxY = Number.MAX_SAFE_INTEGER; - minXY = Number.MIN_SAFE_INTEGER; - } - } + function screenBounds() { + if (screenBound) { + [maxX, maxY] = Window.this.screenBox('workarea', 'dimension'); + const [w, h] = Window.this.box('dimension', 'border'); + maxX -= w; + maxY -= h; + minXY = 0; + } else { + maxX = Number.MAX_SAFE_INTEGER; + maxY = Number.MAX_SAFE_INTEGER; + minXY = Number.MIN_SAFE_INTEGER; + } + } - function onMouseDown(e) { - screenBounds(); - e.target.state.capture(true); + function onMouseDown(e) { + screenBounds(); + e.target.state.capture(true); - const [x, y] = Window.this.box('position', 'border', 'screen'); - xoff = e.screenX - x; - yoff = e.screenY - y; + const [x, y] = Window.this.box('position', 'border', 'screen'); + xoff = e.screenX - x; + yoff = e.screenY - y; - dragging = true; - } + dragging = true; + } - function onMouseMove(e) { - if (dragging) { - Window.this.move( - (e.screenX - xoff).limit(minXY, maxX), - (e.screenY - yoff).limit(minXY, maxY), - ); - } - } + function onMouseMove(e) { + if (dragging) { + Window.this.move((e.screenX - xoff).limit(minXY, maxX), (e.screenY - yoff).limit(minXY, maxY)); + } + } - function onMouseUp(e) { - if (dragging) { - dragging = false; - e.target.state.capture(false); - } - } + function onMouseUp(e) { + if (dragging) { + dragging = false; + e.target.state.capture(false); + } + } - const elements = document.querySelectorAll(s); - for (let i = 0; i < elements.length; ++i) { - // elements[i].on('mousedown', onMouseDown); - // elements[i].on('mousemove', onMouseMove); - // elements[i].on('mouseup', onMouseUp); - } - return !!elements.length; + const elements = document.querySelectorAll(s); + for (let i = 0; i < elements.length; ++i) { + // elements[i].on('mousedown', onMouseDown); + // elements[i].on('mousemove', onMouseMove); + // elements[i].on('mouseup', onMouseUp); + } + return !!elements.length; } // | Module export (uncomment bellow) diff --git a/src/modules/vtuber/js/perlin_noise.js b/src/modules/vtuber/js/perlin_noise.js index 29c0119..1f308ac 100644 --- a/src/modules/vtuber/js/perlin_noise.js +++ b/src/modules/vtuber/js/perlin_noise.js @@ -11,14 +11,14 @@ // appreciate being told where this code finds any use, // but you may do as you like. -//Ported to JavaScript by Mike mikechambers -//http://www.mikechambers.com +// Ported to JavaScript by Mike mikechambers +// http://www.mikechambers.com // // Note, all return values are scaled to be between 0 and 1 // -//From original C at: -//https://github.com/stegu/perlin-noise -//https://github.com/stegu/perlin-noise/blob/master/src/noise1234.c +// From original C at: +// https://github.com/stegu/perlin-noise +// https://github.com/stegu/perlin-noise/blob/master/src/noise1234.c /* * This implementation is "Improved Noise" as presented by @@ -43,7 +43,7 @@ function lerp(t, a, b) { return a + t * (b - a); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // Static data /* @@ -64,521 +64,27 @@ function lerp(t, a, b) { * float-valued 4D noise 64 times. We want this to fit in the cache! */ const perm = [ - 151, - 160, - 137, - 91, - 90, - 15, - 131, - 13, - 201, - 95, - 96, - 53, - 194, - 233, - 7, - 225, - 140, - 36, - 103, - 30, - 69, - 142, - 8, - 99, - 37, - 240, - 21, - 10, - 23, - 190, - 6, - 148, - 247, - 120, - 234, - 75, - 0, - 26, - 197, - 62, - 94, - 252, - 219, - 203, - 117, - 35, - 11, - 32, - 57, - 177, - 33, - 88, - 237, - 149, - 56, - 87, - 174, - 20, - 125, - 136, - 171, - 168, - 68, - 175, - 74, - 165, - 71, - 134, - 139, - 48, - 27, - 166, - 77, - 146, - 158, - 231, - 83, - 111, - 229, - 122, - 60, - 211, - 133, - 230, - 220, - 105, - 92, - 41, - 55, - 46, - 245, - 40, - 244, - 102, - 143, - 54, - 65, - 25, - 63, - 161, - 1, - 216, - 80, - 73, - 209, - 76, - 132, - 187, - 208, - 89, - 18, - 169, - 200, - 196, - 135, - 130, - 116, - 188, - 159, - 86, - 164, - 100, - 109, - 198, - 173, - 186, - 3, - 64, - 52, - 217, - 226, - 250, - 124, - 123, - 5, - 202, - 38, - 147, - 118, - 126, - 255, - 82, - 85, - 212, - 207, - 206, - 59, - 227, - 47, - 16, - 58, - 17, - 182, - 189, - 28, - 42, - 223, - 183, - 170, - 213, - 119, - 248, - 152, - 2, - 44, - 154, - 163, - 70, - 221, - 153, - 101, - 155, - 167, - 43, - 172, - 9, - 129, - 22, - 39, - 253, - 19, - 98, - 108, - 110, - 79, - 113, - 224, - 232, - 178, - 185, - 112, - 104, - 218, - 246, - 97, - 228, - 251, - 34, - 242, - 193, - 238, - 210, - 144, - 12, - 191, - 179, - 162, - 241, - 81, - 51, - 145, - 235, - 249, - 14, - 239, - 107, - 49, - 192, - 214, - 31, - 181, - 199, - 106, - 157, - 184, - 84, - 204, - 176, - 115, - 121, - 50, - 45, - 127, - 4, - 150, - 254, - 138, - 236, - 205, - 93, - 222, - 114, - 67, - 29, - 24, - 72, - 243, - 141, - 128, - 195, - 78, - 66, - 215, - 61, - 156, - 180, - 151, - 160, - 137, - 91, - 90, - 15, - 131, - 13, - 201, - 95, - 96, - 53, - 194, - 233, - 7, - 225, - 140, - 36, - 103, - 30, - 69, - 142, - 8, - 99, - 37, - 240, - 21, - 10, - 23, - 190, - 6, - 148, - 247, - 120, - 234, - 75, - 0, - 26, - 197, - 62, - 94, - 252, - 219, - 203, - 117, - 35, - 11, - 32, - 57, - 177, - 33, - 88, - 237, - 149, - 56, - 87, - 174, - 20, - 125, - 136, - 171, - 168, - 68, - 175, - 74, - 165, - 71, - 134, - 139, - 48, - 27, - 166, - 77, - 146, - 158, - 231, - 83, - 111, - 229, - 122, - 60, - 211, - 133, - 230, - 220, - 105, - 92, - 41, - 55, - 46, - 245, - 40, - 244, - 102, - 143, - 54, - 65, - 25, - 63, - 161, - 1, - 216, - 80, - 73, - 209, - 76, - 132, - 187, - 208, - 89, - 18, - 169, - 200, - 196, - 135, - 130, - 116, - 188, - 159, - 86, - 164, - 100, - 109, - 198, - 173, - 186, - 3, - 64, - 52, - 217, - 226, - 250, - 124, - 123, - 5, - 202, - 38, - 147, - 118, - 126, - 255, - 82, - 85, - 212, - 207, - 206, - 59, - 227, - 47, - 16, - 58, - 17, - 182, - 189, - 28, - 42, - 223, - 183, - 170, - 213, - 119, - 248, - 152, - 2, - 44, - 154, - 163, - 70, - 221, - 153, - 101, - 155, - 167, - 43, - 172, - 9, - 129, - 22, - 39, - 253, - 19, - 98, - 108, - 110, - 79, - 113, - 224, - 232, - 178, - 185, - 112, - 104, - 218, - 246, - 97, - 228, - 251, - 34, - 242, - 193, - 238, - 210, - 144, - 12, - 191, - 179, - 162, - 241, - 81, - 51, - 145, - 235, - 249, - 14, - 239, - 107, - 49, - 192, - 214, - 31, - 181, - 199, - 106, - 157, - 184, - 84, - 204, - 176, - 115, - 121, - 50, - 45, - 127, - 4, - 150, - 254, - 138, - 236, - 205, - 93, - 222, - 114, - 67, - 29, - 24, - 72, - 243, - 141, - 128, - 195, - 78, - 66, - 215, - 61, - 156, - 180, + 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, + 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, + 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, + 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, + 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, + 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, + 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, + 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, + 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, + 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, + 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, + 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, + 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, + 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, + 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, + 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, + 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, + 180 ]; -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /* * Helper functions to compute gradients-dot-residualvectors (1D to 4D) @@ -594,41 +100,45 @@ const perm = [ */ function grad1(hash, x) { - let h = hash & 15; + const h = hash & 15; let grad = 1.0 + (h & 7); // Gradient value 1.0, 2.0, ..., 8.0 if (h & 8) grad = -grad; // and a random sign for the gradient return grad * x; // Multiply the gradient with the distance } function grad2(hash, x, y) { - let h = hash & 7; // Convert low 3 bits of hash code - let u = h < 4 ? x : y; // into 8 simple gradient directions, - let v = h < 4 ? y : x; // and compute the dot product with (x,y). + const h = hash & 7; // Convert low 3 bits of hash code + const u = h < 4 ? x : y; // into 8 simple gradient directions, + const v = h < 4 ? y : x; // and compute the dot product with (x,y). return (h & 1 ? -u : u) + (h & 2 ? -2.0 * v : 2.0 * v); } function grad3(hash, x, y, z) { - let h = hash & 15; // Convert low 4 bits of hash code into 12 simple - let u = h < 8 ? x : y; // gradient directions, and compute dot product. - let v = h < 4 ? y : h == 12 || h == 14 ? x : z; // Fix repeats at h = 12 to 15 + const h = hash & 15; // Convert low 4 bits of hash code into 12 simple + const u = h < 8 ? x : y; // gradient directions, and compute dot product. + const v = h < 4 ? y : h === 12 || h === 14 ? x : z; // Fix repeats at h = 12 to 15 return (h & 1 ? -u : u) + (h & 2 ? -v : v); } function grad4(hash, x, y, z, t) { - let h = hash & 31; // Convert low 5 bits of hash code into 32 simple - let u = h < 24 ? x : y; // gradient directions, and compute dot product. - let v = h < 16 ? y : z; - let w = h < 8 ? z : t; + const h = hash & 31; // Convert low 5 bits of hash code into 32 simple + const u = h < 24 ? x : y; // gradient directions, and compute dot product. + const v = h < 16 ? y : z; + const w = h < 8 ? z : t; return (h & 1 ? -u : u) + (h & 2 ? -v : v) + (h & 4 ? -w : w); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 1D float Perlin noise, SL "noise()" */ export function noise1(x) { - let ix0, ix1; - let fx0, fx1; - let s, n0, n1; + let ix0 = null; + let ix1 = null; + let fx0 = null; + let fx1 = null; + let s = null; + let n0 = null; + let n1 = null; ix0 = Math.floor(x); // Integer part of x fx0 = x - ix0; // Fractional part of x @@ -643,131 +153,121 @@ export function noise1(x) { return scale(0.188 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 1D float Perlin periodic noise, SL "pnoise()" */ export function pnoise1(x, px) { - let ix0, ix1; - let fx0, fx1; - let s, n0, n1; - - ix0 = Math.floor(x); // Integer part of x - fx0 = x - ix0; // Fractional part of x - fx1 = fx0 - 1.0; - ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 *and* wrap to 0..255 + let ix0 = Math.floor(x); // Integer part of x + const fx0 = x - ix0; // Fractional part of x + const fx1 = fx0 - 1.0; + const ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 *and* wrap to 0..255 ix0 = ix0 % px & 0xff; // (because px might be greater than 256) - s = fade(fx0); + const s = fade(fx0); - n0 = grad1(perm[ix0], fx0); - n1 = grad1(perm[ix1], fx1); + const n0 = grad1(perm[ix0], fx0); + const n1 = grad1(perm[ix1], fx1); return scale(0.188 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 2D float Perlin noise. */ export function noise2(x, y) { - let ix0, iy0, ix1, iy1; - let fx0, fy0, fx1, fy1; - let s, t, nx0, nx1, n0, n1; + // let ix0, iy0, ix1, iy1; + // let fx0, fy0, fx1, fy1; + // let s, t, nx0, nx1, n0, n1; + + let ix0 = Math.floor(x); // Integer part of x + let iy0 = Math.floor(y); // Integer part of y + const fx0 = x - ix0; // Fractional part of x + const fy0 = y - iy0; // Fractional part of y + const fx1 = fx0 - 1.0; + const fy1 = fy0 - 1.0; + const ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + const iy1 = (iy0 + 1) & 0xff; - ix0 = Math.floor(x); // Integer part of x - iy0 = Math.floor(y); // Integer part of y - fx0 = x - ix0; // Fractional part of x - fy0 = y - iy0; // Fractional part of y - fx1 = fx0 - 1.0; - fy1 = fy0 - 1.0; - ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 - iy1 = (iy0 + 1) & 0xff; ix0 = ix0 & 0xff; iy0 = iy0 & 0xff; - t = fade(fy0); - s = fade(fx0); + const t = fade(fy0); + const s = fade(fx0); - nx0 = grad2(perm[ix0 + perm[iy0]], fx0, fy0); - nx1 = grad2(perm[ix0 + perm[iy1]], fx0, fy1); - n0 = lerp(t, nx0, nx1); + let nx0 = grad2(perm[ix0 + perm[iy0]], fx0, fy0); + let nx1 = grad2(perm[ix0 + perm[iy1]], fx0, fy1); + const n0 = lerp(t, nx0, nx1); nx0 = grad2(perm[ix1 + perm[iy0]], fx1, fy0); nx1 = grad2(perm[ix1 + perm[iy1]], fx1, fy1); - n1 = lerp(t, nx0, nx1); + const n1 = lerp(t, nx0, nx1); return scale(0.507 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 2D float Perlin periodic noise. */ export function pnoise2(x, y, px, py) { - let ix0, iy0, ix1, iy1; - let fx0, fy0, fx1, fy1; - let s, t, nx0, nx1, n0, n1; - - ix0 = Math.floor(x); // Integer part of x - iy0 = Math.floor(y); // Integer part of y - fx0 = x - ix0; // Fractional part of x - fy0 = y - iy0; // Fractional part of y - fx1 = fx0 - 1.0; - fy1 = fy0 - 1.0; - ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 and wrap to 0..255 - iy1 = (iy0 + 1) % py & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + let ix0 = Math.floor(x); // Integer part of x + let iy0 = Math.floor(y); // Integer part of y + const fx0 = x - ix0; // Fractional part of x + const fy0 = y - iy0; // Fractional part of y + const fx1 = fx0 - 1.0; + const fy1 = fy0 - 1.0; + const ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + const iy1 = (iy0 + 1) % py & 0xff; // Wrap to 0..py-1 and wrap to 0..255 ix0 = ix0 % px & 0xff; iy0 = iy0 % py & 0xff; - t = fade(fy0); - s = fade(fx0); + const t = fade(fy0); + const s = fade(fx0); - nx0 = grad2(perm[ix0 + perm[iy0]], fx0, fy0); - nx1 = grad2(perm[ix0 + perm[iy1]], fx0, fy1); - n0 = lerp(t, nx0, nx1); + let nx0 = grad2(perm[ix0 + perm[iy0]], fx0, fy0); + let nx1 = grad2(perm[ix0 + perm[iy1]], fx0, fy1); + const n0 = lerp(t, nx0, nx1); nx0 = grad2(perm[ix1 + perm[iy0]], fx1, fy0); nx1 = grad2(perm[ix1 + perm[iy1]], fx1, fy1); - n1 = lerp(t, nx0, nx1); + const n1 = lerp(t, nx0, nx1); return scale(0.507 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 3D float Perlin noise. */ export function noise3(x, y, z) { - let ix0, iy0, ix1, iy1, iz0, iz1; - let fx0, fy0, fz0, fx1, fy1, fz1; - let s, t, r; - let nxy0, nxy1, nx0, nx1, n0, n1; + let ix0 = Math.floor(x); // Integer part of x + let iy0 = Math.floor(y); // Integer part of y + let iz0 = Math.floor(z); // Integer part of z + + const fx0 = x - ix0; // Fractional part of x + const fy0 = y - iy0; // Fractional part of y + const fz0 = z - iz0; // Fractional part of z + const fx1 = fx0 - 1.0; + const fy1 = fy0 - 1.0; + const fz1 = fz0 - 1.0; + const ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + const iy1 = (iy0 + 1) & 0xff; + const iz1 = (iz0 + 1) & 0xff; - ix0 = Math.floor(x); // Integer part of x - iy0 = Math.floor(y); // Integer part of y - iz0 = Math.floor(z); // Integer part of z - fx0 = x - ix0; // Fractional part of x - fy0 = y - iy0; // Fractional part of y - fz0 = z - iz0; // Fractional part of z - fx1 = fx0 - 1.0; - fy1 = fy0 - 1.0; - fz1 = fz0 - 1.0; - ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 - iy1 = (iy0 + 1) & 0xff; - iz1 = (iz0 + 1) & 0xff; ix0 = ix0 & 0xff; iy0 = iy0 & 0xff; iz0 = iz0 & 0xff; - r = fade(fz0); - t = fade(fy0); - s = fade(fx0); + const r = fade(fz0); + const t = fade(fy0); + const s = fade(fx0); - nxy0 = grad3(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); - nxy1 = grad3(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); - nx0 = lerp(r, nxy0, nxy1); + let nxy0 = grad3(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); + let nxy1 = grad3(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); + let nx0 = lerp(r, nxy0, nxy1); nxy0 = grad3(perm[ix0 + perm[iy1 + perm[iz0]]], fx0, fy1, fz0); nxy1 = grad3(perm[ix0 + perm[iy1 + perm[iz1]]], fx0, fy1, fz1); - nx1 = lerp(r, nxy0, nxy1); + let nx1 = lerp(r, nxy0, nxy1); - n0 = lerp(t, nx0, nx1); + const n0 = lerp(t, nx0, nx1); nxy0 = grad3(perm[ix1 + perm[iy0 + perm[iz0]]], fx1, fy0, fz0); nxy1 = grad3(perm[ix1 + perm[iy0 + perm[iz1]]], fx1, fy0, fz1); @@ -777,49 +277,44 @@ export function noise3(x, y, z) { nxy1 = grad3(perm[ix1 + perm[iy1 + perm[iz1]]], fx1, fy1, fz1); nx1 = lerp(r, nxy0, nxy1); - n1 = lerp(t, nx0, nx1); + const n1 = lerp(t, nx0, nx1); return scale(0.936 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 3D float Perlin periodic noise. */ export function pnoise3(x, y, z, px, py, pz) { - let ix0, iy0, ix1, iy1, iz0, iz1; - let fx0, fy0, fz0, fx1, fy1, fz1; - let s, t, r; - let nxy0, nxy1, nx0, nx1, n0, n1; - - ix0 = Math.floor(x); // Integer part of x - iy0 = Math.floor(y); // Integer part of y - iz0 = Math.floor(z); // Integer part of z - fx0 = x - ix0; // Fractional part of x - fy0 = y - iy0; // Fractional part of y - fz0 = z - iz0; // Fractional part of z - fx1 = fx0 - 1.0; - fy1 = fy0 - 1.0; - fz1 = fz0 - 1.0; - ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 and wrap to 0..255 - iy1 = (iy0 + 1) % py & 0xff; // Wrap to 0..py-1 and wrap to 0..255 - iz1 = (iz0 + 1) % pz & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 + let ix0 = Math.floor(x); // Integer part of x + let iy0 = Math.floor(y); // Integer part of y + let iz0 = Math.floor(z); // Integer part of z + const fx0 = x - ix0; // Fractional part of x + const fy0 = y - iy0; // Fractional part of y + const fz0 = z - iz0; // Fractional part of z + const fx1 = fx0 - 1.0; + const fy1 = fy0 - 1.0; + const fz1 = fz0 - 1.0; + const ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + const iy1 = (iy0 + 1) % py & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + const iz1 = (iz0 + 1) % pz & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 ix0 = ix0 % px & 0xff; iy0 = iy0 % py & 0xff; iz0 = iz0 % pz & 0xff; - r = fade(fz0); - t = fade(fy0); - s = fade(fx0); + const r = fade(fz0); + const t = fade(fy0); + const s = fade(fx0); - nxy0 = grad3(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); - nxy1 = grad3(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); - nx0 = lerp(r, nxy0, nxy1); + let nxy0 = grad3(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); + let nxy1 = grad3(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); + let nx0 = lerp(r, nxy0, nxy1); nxy0 = grad3(perm[ix0 + perm[iy1 + perm[iz0]]], fx0, fy1, fz0); nxy1 = grad3(perm[ix0 + perm[iy1 + perm[iz1]]], fx0, fy1, fz1); - nx1 = lerp(r, nxy0, nxy1); + let nx1 = lerp(r, nxy0, nxy1); - n0 = lerp(t, nx0, nx1); + const n0 = lerp(t, nx0, nx1); nxy0 = grad3(perm[ix1 + perm[iy0 + perm[iz0]]], fx1, fy0, fz0); nxy1 = grad3(perm[ix1 + perm[iy0 + perm[iz1]]], fx1, fy0, fz1); @@ -829,365 +324,163 @@ export function pnoise3(x, y, z, px, py, pz) { nxy1 = grad3(perm[ix1 + perm[iy1 + perm[iz1]]], fx1, fy1, fz1); nx1 = lerp(r, nxy0, nxy1); - n1 = lerp(t, nx0, nx1); + const n1 = lerp(t, nx0, nx1); return scale(0.936 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 4D float Perlin noise. */ export function noise4(x, y, z, w) { - let ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1; - let fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1; - let s, t, r, q; - let nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1; - - ix0 = Math.floor(x); // Integer part of x - iy0 = Math.floor(y); // Integer part of y - iz0 = Math.floor(z); // Integer part of y - iw0 = Math.floor(w); // Integer part of w - fx0 = x - ix0; // Fractional part of x - fy0 = y - iy0; // Fractional part of y - fz0 = z - iz0; // Fractional part of z - fw0 = w - iw0; // Fractional part of w - fx1 = fx0 - 1.0; - fy1 = fy0 - 1.0; - fz1 = fz0 - 1.0; - fw1 = fw0 - 1.0; - ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 - iy1 = (iy0 + 1) & 0xff; - iz1 = (iz0 + 1) & 0xff; - iw1 = (iw0 + 1) & 0xff; + let ix0 = Math.floor(x); // Integer part of x + let iy0 = Math.floor(y); // Integer part of y + let iz0 = Math.floor(z); // Integer part of y + let iw0 = Math.floor(w); // Integer part of w + const fx0 = x - ix0; // Fractional part of x + const fy0 = y - iy0; // Fractional part of y + const fz0 = z - iz0; // Fractional part of z + const fw0 = w - iw0; // Fractional part of w + const fx1 = fx0 - 1.0; + const fy1 = fy0 - 1.0; + const fz1 = fz0 - 1.0; + const fw1 = fw0 - 1.0; + const ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + const iy1 = (iy0 + 1) & 0xff; + const iz1 = (iz0 + 1) & 0xff; + const iw1 = (iw0 + 1) & 0xff; ix0 = ix0 & 0xff; iy0 = iy0 & 0xff; iz0 = iz0 & 0xff; iw0 = iw0 & 0xff; - q = fade(fw0); - r = fade(fz0); - t = fade(fy0); - s = fade(fx0); + const q = fade(fw0); + const r = fade(fz0); + const t = fade(fy0); + const s = fade(fx0); - nxyz0 = grad4( - perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], - fx0, - fy0, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], - fx0, - fy0, - fz0, - fw1 - ); + let nxyz0 = grad4(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0); + let nxyz1 = grad4(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1); + let nxy0 = lerp(q, nxyz0, nxyz1); + + nxyz0 = grad4(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0); + nxyz1 = grad4(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1); + let nxy1 = lerp(q, nxyz0, nxyz1); + + let nx0 = lerp(r, nxy0, nxy1); + + nxyz0 = grad4(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0); + nxyz1 = grad4(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1); nxy0 = lerp(q, nxyz0, nxyz1); - nxyz0 = grad4( - perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], - fx0, - fy0, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], - fx0, - fy0, - fz1, - fw1 - ); + nxyz0 = grad4(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0); + nxyz1 = grad4(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1); + nxy1 = lerp(q, nxyz0, nxyz1); + + let nx1 = lerp(r, nxy0, nxy1); + + const n0 = lerp(t, nx0, nx1); + + nxyz0 = grad4(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1); + nxy0 = lerp(q, nxyz0, nxyz1); + + nxyz0 = grad4(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1); nxy1 = lerp(q, nxyz0, nxyz1); nx0 = lerp(r, nxy0, nxy1); - nxyz0 = grad4( - perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], - fx0, - fy1, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], - fx0, - fy1, - fz0, - fw1 - ); + nxyz0 = grad4(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1); nxy0 = lerp(q, nxyz0, nxyz1); - nxyz0 = grad4( - perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], - fx0, - fy1, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], - fx0, - fy1, - fz1, - fw1 - ); + nxyz0 = grad4(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1); nxy1 = lerp(q, nxyz0, nxyz1); nx1 = lerp(r, nxy0, nxy1); - n0 = lerp(t, nx0, nx1); - - nxyz0 = grad4( - perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], - fx1, - fy0, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], - fx1, - fy0, - fz0, - fw1 - ); - nxy0 = lerp(q, nxyz0, nxyz1); - - nxyz0 = grad4( - perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], - fx1, - fy0, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], - fx1, - fy0, - fz1, - fw1 - ); - nxy1 = lerp(q, nxyz0, nxyz1); - - nx0 = lerp(r, nxy0, nxy1); - - nxyz0 = grad4( - perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], - fx1, - fy1, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], - fx1, - fy1, - fz0, - fw1 - ); - nxy0 = lerp(q, nxyz0, nxyz1); - - nxyz0 = grad4( - perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], - fx1, - fy1, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], - fx1, - fy1, - fz1, - fw1 - ); - nxy1 = lerp(q, nxyz0, nxyz1); - - nx1 = lerp(r, nxy0, nxy1); - - n1 = lerp(t, nx0, nx1); + const n1 = lerp(t, nx0, nx1); return scale(0.87 * lerp(s, n0, n1)); } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- /** 4D float Perlin periodic noise. */ export function pnoise4(x, y, z, w, px, py, pz, pw) { - let ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1; - let fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1; - let s, t, r, q; - let nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1; - - ix0 = Math.floor(x); // Integer part of x - iy0 = Math.floor(y); // Integer part of y - iz0 = Math.floor(z); // Integer part of y - iw0 = Math.floor(w); // Integer part of w - fx0 = x - ix0; // Fractional part of x - fy0 = y - iy0; // Fractional part of y - fz0 = z - iz0; // Fractional part of z - fw0 = w - iw0; // Fractional part of w - fx1 = fx0 - 1.0; - fy1 = fy0 - 1.0; - fz1 = fz0 - 1.0; - fw1 = fw0 - 1.0; - ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 and wrap to 0..255 - iy1 = (iy0 + 1) % py & 0xff; // Wrap to 0..py-1 and wrap to 0..255 - iz1 = (iz0 + 1) % pz & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 - iw1 = (iw0 + 1) % pw & 0xff; // Wrap to 0..pw-1 and wrap to 0..255 + let ix0 = Math.floor(x); // Integer part of x + let iy0 = Math.floor(y); // Integer part of y + let iz0 = Math.floor(z); // Integer part of y + let iw0 = Math.floor(w); // Integer part of w + const fx0 = x - ix0; // Fractional part of x + const fy0 = y - iy0; // Fractional part of y + const fz0 = z - iz0; // Fractional part of z + const fw0 = w - iw0; // Fractional part of w + const fx1 = fx0 - 1.0; + const fy1 = fy0 - 1.0; + const fz1 = fz0 - 1.0; + const fw1 = fw0 - 1.0; + const ix1 = (ix0 + 1) % px & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + const iy1 = (iy0 + 1) % py & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + const iz1 = (iz0 + 1) % pz & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 + const iw1 = (iw0 + 1) % pw & 0xff; // Wrap to 0..pw-1 and wrap to 0..255 ix0 = ix0 % px & 0xff; iy0 = iy0 % py & 0xff; iz0 = iz0 % pz & 0xff; iw0 = iw0 % pw & 0xff; - q = fade(fw0); - r = fade(fz0); - t = fade(fy0); - s = fade(fx0); + const q = fade(fw0); + const r = fade(fz0); + const t = fade(fy0); + const s = fade(fx0); - nxyz0 = grad4( - perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], - fx0, - fy0, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], - fx0, - fy0, - fz0, - fw1 - ); + let nxyz0 = grad4(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0); + let nxyz1 = grad4(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1); + let nxy0 = lerp(q, nxyz0, nxyz1); + + nxyz0 = grad4(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0); + nxyz1 = grad4(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1); + let nxy1 = lerp(q, nxyz0, nxyz1); + + let nx0 = lerp(r, nxy0, nxy1); + + nxyz0 = grad4(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0); + nxyz1 = grad4(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1); nxy0 = lerp(q, nxyz0, nxyz1); - nxyz0 = grad4( - perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], - fx0, - fy0, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], - fx0, - fy0, - fz1, - fw1 - ); + nxyz0 = grad4(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0); + nxyz1 = grad4(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1); + nxy1 = lerp(q, nxyz0, nxyz1); + + let nx1 = lerp(r, nxy0, nxy1); + + const n0 = lerp(t, nx0, nx1); + + nxyz0 = grad4(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1); + nxy0 = lerp(q, nxyz0, nxyz1); + + nxyz0 = grad4(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1); nxy1 = lerp(q, nxyz0, nxyz1); nx0 = lerp(r, nxy0, nxy1); - nxyz0 = grad4( - perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], - fx0, - fy1, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], - fx0, - fy1, - fz0, - fw1 - ); + nxyz0 = grad4(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1); nxy0 = lerp(q, nxyz0, nxyz1); - nxyz0 = grad4( - perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], - fx0, - fy1, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], - fx0, - fy1, - fz1, - fw1 - ); + nxyz0 = grad4(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0); + nxyz1 = grad4(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1); nxy1 = lerp(q, nxyz0, nxyz1); nx1 = lerp(r, nxy0, nxy1); - n0 = lerp(t, nx0, nx1); - - nxyz0 = grad4( - perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], - fx1, - fy0, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], - fx1, - fy0, - fz0, - fw1 - ); - nxy0 = lerp(q, nxyz0, nxyz1); - - nxyz0 = grad4( - perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], - fx1, - fy0, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], - fx1, - fy0, - fz1, - fw1 - ); - nxy1 = lerp(q, nxyz0, nxyz1); - - nx0 = lerp(r, nxy0, nxy1); - - nxyz0 = grad4( - perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], - fx1, - fy1, - fz0, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], - fx1, - fy1, - fz0, - fw1 - ); - nxy0 = lerp(q, nxyz0, nxyz1); - - nxyz0 = grad4( - perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], - fx1, - fy1, - fz1, - fw0 - ); - nxyz1 = grad4( - perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], - fx1, - fy1, - fz1, - fw1 - ); - nxy1 = lerp(q, nxyz0, nxyz1); - - nx1 = lerp(r, nxy0, nxy1); - - n1 = lerp(t, nx0, nx1); + const n1 = lerp(t, nx0, nx1); return scale(0.87 * lerp(s, n0, n1)); } @@ -1199,17 +492,14 @@ function scale(n) { export default function noise(x, y, z, w) { switch (arguments.length) { case 1: - return noise1(x); //todo: move these to perlin functions - break; + return noise1(x); // todo: move these to perlin functions case 2: - return noise2(x, y); //todo: move these to perlin functions - break; + return noise2(x, y); // todo: move these to perlin functions case 3: return noise3(x, y, z); - case 3: + case 4: return noise4(x, y, z, w); - break; } } -//--------------------------------------------------------------------- +// ---------------------------------------------------------------------