diff options
author | RaindropsSys <raindrops@equestria.dev> | 2024-02-04 13:37:54 +0100 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2024-02-04 13:37:54 +0100 |
commit | e5e5aa2c92ce7694449c19b94dd2af0f41e93e3f (patch) | |
tree | 3ff3ebfd00400d5b5108368566d719194c3f6f5a | |
parent | 01a027a0a189389188eac692b309c21d690cd582 (diff) | |
download | chatroom-e5e5aa2c92ce7694449c19b94dd2af0f41e93e3f.tar.gz chatroom-e5e5aa2c92ce7694449c19b94dd2af0f41e93e3f.tar.bz2 chatroom-e5e5aa2c92ce7694449c19b94dd2af0f41e93e3f.zip |
Updated 4 files, added 2 files and deleted bot.zip (automated)
-rw-r--r-- | bot.zip | bin | 11173720 -> 0 bytes | |||
-rwxr-xr-x | build.js | 14 | ||||
-rw-r--r-- | client/home.html | 62 | ||||
-rw-r--r-- | client/icons/newtab.svg | 20 | ||||
-rw-r--r-- | client/index.html | 140 | ||||
-rwxr-xr-x | client/main.js | 996 | ||||
-rw-r--r-- | launcher/client/index.html | 90 |
7 files changed, 869 insertions, 453 deletions
diff --git a/bot.zip b/bot.zip Binary files differdeleted file mode 100644 index 3b1635c..0000000 --- a/bot.zip +++ /dev/null @@ -40,6 +40,16 @@ function scandir(path) { let list = scandir("./client"); let pack = []; +function processFile(item) { + if (item.endsWith("main.js")) { + let data = fs.readFileSync(item).toString(); + data = data.replace(/\/\/ --- >START< @BUILDNUMBER@ >START< --- \/\/\n((.|\n)*)\n\/\/ --- >FINAL< @BUILDNUMBER@ >FINAL< --- \/\/\n\n/gm, "// --- >START< @BUILDNUMBER@ >START< --- //\nconst buildNumber = \"" + new Date().toISOString().split("T")[0] + "\";\n// --- >FINAL< @BUILDNUMBER@ >FINAL< --- //\n\n"); + return Buffer.from(data); + } else { + return fs.readFileSync(item); + } +} + for (let item of list) { if (fs.lstatSync(item).isDirectory()) { pack.push({ @@ -51,8 +61,8 @@ for (let item of list) { pack.push({ type: "file", name: item, - content: zlib.brotliCompressSync(fs.readFileSync(item)).toString("base64"), - hash: crypto.createHash("sha256").update(fs.readFileSync(item)).digest("base64") + content: zlib.brotliCompressSync(processFile(item)).toString("base64"), + hash: crypto.createHash("sha256").update(processFile(item)).digest("base64") }); } } diff --git a/client/home.html b/client/home.html new file mode 100644 index 0000000..617a042 --- /dev/null +++ b/client/home.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>New Tab</title> + <link rel="icon" href="./icons/newtab.svg"> + <link href="./bs.css" rel="stylesheet"> + <script src="./bs.js"></script> + <style> + @media (prefers-color-scheme: dark) { + main { + filter: invert(1) hue-rotate(180deg); + background-color: #ddd !important; + } + } + </style> +</head> +<body> + <main style="background-color: #eee; position: fixed; inset: 0; overflow: auto;"> + <div style="margin-left: auto; margin-right: auto; width: max-content; margin-top: 50px;"> + <img src="./icon.png" style="filter: invert(1) hue-rotate(180deg); width: 96px; vertical-align: middle;"> + <span style="vertical-align: middle; margin-left: 20px; font-size: 36px;">Chatroom</span> + </div> + <form action="https://duckduckgo.com"> + <input type="text" name="q" class="form-control" placeholder="Search the web without being tracked" style="margin-top: 50px; width: 50%; margin-left: auto; margin-right: auto;"> + </form> + + <div class="container" style="margin-top: 50px; margin-bottom: 50px;"> + <hr style="margin-bottom: 30px;"> + + <h3>What's new in Chatroom?</h3> + + <h5>Chatroom 2.6.0</h5> + <ul> + <li>Fixed a bug that was causing some buttons to be hidden below the window controls on Windows</li> + <li>Fixed a bug that was causing the window controls on Windows to show up in light theme even when dark theme is on</li> + <li>Fixed a bug that was causing an error message to show up when pressing Ctrl/Cmd+W on Chrome Dev Tools</li> + <li>Introduced a new launcher experience</li> + <li>Improved dark theme support introduced in version 2.5.0</li> + <li>Fixed a bug where some websites would show a broken tab icon</li> + <li>Made the tab bar shrink, so you can open a lot more tabs at once (about 30 with the default window size)</li> + <li>Added a new home page, replacing the DuckDuckGo homepage</li> + <li>Added a confirmation dialog when closing Chatroom</li> + <li>A basic right click menu has been added, giving you the option to (for example) open links in new tabs</li> + </ul> + + <h5>Chatroom 2.5.1</h5> + <ul> + <li>Fixed a bug that prevented accessing the chat</li> + </ul> + + <h5>Chatroom 2.5.0</h5> + <ul> + <li>Added dark theme support</li> + <li>Added an option to turn the built-in ad blocker on or off</li> + <li>Fixed a bug that was making it possible to scroll the main browser UI</li> + <li>Added new modern icons</li> + </ul> + </div> + </main> +</body> +</html>
\ No newline at end of file diff --git a/client/icons/newtab.svg b/client/icons/newtab.svg new file mode 100644 index 0000000..bb30c5f --- /dev/null +++ b/client/icons/newtab.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 27.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 256 256" style="enable-background:new 0 0 256 256;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#1ABCB900;} + .st1{fill:#000000;} +</style> +<path class="st0" d="M218.63,256H37.37C16.73,256,0,239.27,0,218.63V37.37C0,16.73,16.73,0,37.37,0h181.26 + C239.27,0,256,16.73,256,37.37v181.26C256,239.27,239.27,256,218.63,256z"/> +<path class="st1" d="M66.51,186.68c-3.75-2.02-6.68-4.84-8.77-8.44c-2.09-3.61-3.14-7.51-3.14-11.69v-45.47l-22.73-12.55 + c-2.04-1.14-3.53-2.56-4.45-4.27c-0.93-1.71-1.39-3.6-1.39-5.69c0-2.02,0.46-3.92,1.39-5.71c0.93-1.79,2.41-3.27,4.45-4.47 + l78.81-43.09c1.73-1.01,3.52-1.73,5.36-2.17s3.74-0.65,5.68-0.65c1.94,0,3.83,0.22,5.68,0.65c1.84,0.43,3.63,1.15,5.36,2.17 + l91.37,49.8c1.86,0.95,3.29,2.32,4.32,4.13c1.02,1.8,1.53,3.75,1.53,5.83v61.06c0,3.18-1.12,5.88-3.36,8.12 + c-2.24,2.24-4.94,3.36-8.12,3.36c-3.18,0-5.88-1.12-8.12-3.36c-2.24-2.24-3.36-4.94-3.36-8.12v-55.21l-18.19,10.18v45.47 + c0,4.19-1.05,8.08-3.14,11.69c-2.09,3.61-5.02,6.42-8.77,8.44l-44.17,24.03c-1.73,1.01-3.52,1.73-5.36,2.17 + c-1.84,0.43-3.74,0.65-5.68,0.65c-1.94,0-3.83-0.22-5.68-0.65c-1.84-0.43-3.63-1.15-5.36-2.17L66.51,186.68z M121.72,131.25 + l60.63-32.91l-60.63-32.69L61.31,98.34L121.72,131.25z M121.72,190.36l44.17-23.82v-33.56l-33.13,18.4c-1.73,1.01-3.5,1.73-5.3,2.17 + c-1.8,0.43-3.72,0.65-5.74,0.65c-2.02,0-3.93-0.22-5.74-0.65s-3.57-1.15-5.3-2.17l-33.13-18.4v33.56L121.72,190.36z"/> +</svg> diff --git a/client/index.html b/client/index.html index 0e59212..d95083f 100644 --- a/client/index.html +++ b/client/index.html @@ -3,8 +3,8 @@ <head> <meta charset="UTF-8"> <title>Chatroom Workspace</title> - <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> - <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> + <link href="./bs.css" rel="stylesheet"> + <script src="./bs.js"></script> <style> * { -webkit-user-drag: none; @@ -63,6 +63,10 @@ filter: invert(1) hue-rotate(180deg); } + #changelog { + filter: invert(1) hue-rotate(180deg); + } + .nav-link.active { background-color: #ddd !important; border-bottom: none !important; @@ -71,16 +75,51 @@ img:not([src$=".svg"]) { filter: invert(1) hue-rotate(180deg); } + + #windows, body { + background-color: #111111; + } + + webview { + background-color: #111; + } + } + + .small-1 .tab-text { + width: 100px !important; + } + + .small-2 .tab-text { + width: 50px !important; + } + + .small-3 .tab-text { + opacity: 0 !important; + width: 7px !important; + } + + .small-4 .tab-text, .small-4 .tab-close { + display: none !important; + } + + .small-5 .nav-link { + padding: 0.5rem !important; + } + + .small-6 .nav-link img { + width: 16px !important; + height: 24px !important; + padding: 4px 0 !important; } </style> </head> -<body style="overflow-y: hidden;"> +<body style="overflow: hidden;"> <ul id="tabs" class="nav nav-tabs" style="background-color: #eee; -webkit-app-region: drag;"></ul> <script> if (process.platform === "darwin") { document.getElementById("tabs").style.paddingLeft = "86px"; } else { - document.getElementById("tabs").style.paddingRight = "96px"; + document.getElementById("tabs").style.paddingRight = "140px"; } </script> <div id="windows" style="display: flex;"></div> @@ -122,7 +161,7 @@ document.getElementById("tabs").innerHTML = `<div style="display: grid; grid-template-columns: 1fr max-content; width: 100%;"><span>` + window.tabs.map((i, j) => ` <li class="nav-item ${i.chat ? 'pinned' : ''}" style="width: max-content; display: inline-block;"> - <a class="nav-link ${j === window.activeTab ? 'active' : ''}" aria-current="page" href="#" onclick="if (event.target.classList.contains('nav-link')) switchToTab(${j});"><img style="width: 24px; height: 24px; pointer-events: none;" alt="" src="${i.icon}"><span class="tab-text" onclick="switchToTab(${j});" style="vertical-align: middle; margin-left: 5px; width: 171px; display: inline-block; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis">${i.name}</span><span class="tab-close" style="display: inline-block;" onclick="event.preventDefault(); closeTab(${j});"><img alt="" src="./icons/dismiss.svg"></span></a> + <a class="nav-link ${j === window.activeTab ? 'active' : ''}" aria-current="page" href="#" onclick="if (event.target.classList.contains('nav-link')) switchToTab(${j});"><img onerror="event.target.src = './icons/placeholder.svg';" style="width: 24px; height: 24px; pointer-events: none;" alt="" src="${i.icon}"><span class="tab-text" onclick="switchToTab(${j});" style="vertical-align: middle; margin-left: 5px; width: 171px; display: inline-block; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis">${i.name}</span><span class="tab-close" style="display: inline-block;" onclick="event.preventDefault(); closeTab(${j});"><img alt="" src="./icons/dismiss.svg"></span></a> </li> `).join("") + `<li class="nav-item" style="width: max-content; display: inline-block;"> <a class="nav-link" aria-current="page" href="#" onclick="openHome();"><img alt="" src="./icons/new.svg"></a> @@ -130,6 +169,68 @@ <a class="nav-link" aria-current="page" href="#" onclick="toggleProtection();"><img id="ad-protection-img" alt="" src="./icons/${window.protectionEnabled ? 'shield-on' : 'shield-off'}.svg"></a> </li></span></div>`; if (tabs[window.activeTab]) document.title = tabs[window.activeTab].name + " · Chatroom Workspace"; + + secureTabHeight(); + } + + let lastTabHeightUpdateCount = tabs.length; + + function secureTabHeight(force) { + let first = false; + let i = 0; + + while ((!first || document.getElementById("tabs").clientHeight > 43) && i < 10) { + if (document.getElementById("tabs").clientHeight > 43 && !document.getElementById("tabs").classList.contains("small-1")) { + document.getElementById("tabs").classList.add("small-1"); + } else if (document.getElementById("tabs").clientHeight > 43 && !document.getElementById("tabs").classList.contains("small-2")) { + document.getElementById("tabs").classList.add("small-1"); + document.getElementById("tabs").classList.add("small-2"); + } else if (document.getElementById("tabs").clientHeight > 43 && !document.getElementById("tabs").classList.contains("small-3")) { + document.getElementById("tabs").classList.add("small-1"); + document.getElementById("tabs").classList.add("small-2"); + document.getElementById("tabs").classList.add("small-3"); + } else if (document.getElementById("tabs").clientHeight > 43 && !document.getElementById("tabs").classList.contains("small-4")) { + document.getElementById("tabs").classList.add("small-1"); + document.getElementById("tabs").classList.add("small-2"); + document.getElementById("tabs").classList.add("small-3"); + document.getElementById("tabs").classList.add("small-4"); + } else if (document.getElementById("tabs").clientHeight > 43 && !document.getElementById("tabs").classList.contains("small-5")) { + document.getElementById("tabs").classList.add("small-1"); + document.getElementById("tabs").classList.add("small-2"); + document.getElementById("tabs").classList.add("small-3"); + document.getElementById("tabs").classList.add("small-4"); + document.getElementById("tabs").classList.add("small-5"); + } else if (document.getElementById("tabs").clientHeight > 43 && !document.getElementById("tabs").classList.contains("small-6")) { + document.getElementById("tabs").classList.add("small-1"); + document.getElementById("tabs").classList.add("small-2"); + document.getElementById("tabs").classList.add("small-3"); + document.getElementById("tabs").classList.add("small-4"); + document.getElementById("tabs").classList.add("small-5"); + document.getElementById("tabs").classList.add("small-6"); + } else { + if (force || tabs.length < lastTabHeightUpdateCount) { + document.getElementById("tabs").classList.remove("small-1"); + document.getElementById("tabs").classList.remove("small-2"); + document.getElementById("tabs").classList.remove("small-3"); + document.getElementById("tabs").classList.remove("small-4"); + document.getElementById("tabs").classList.remove("small-5"); + document.getElementById("tabs").classList.remove("small-6"); + } + } + + first = true; + i++; + } + + if (i >= 10) { + closeTab(tabs.length - 1); + } + + lastTabHeightUpdateCount = tabs.length; + } + + window.onresize = () => { + secureTabHeight(true); } function reloadWebview(force) { @@ -152,19 +253,20 @@ } function resetURL(id) { - if (document.getElementById("wv-item-" + id + "-inner").getURL() === "https://start.duckduckgo.com/") { + if (document.getElementById("wv-item-" + id + "-inner").getURL().startsWith("file://") && document.getElementById("wv-item-" + id + "-inner").getURL().endsWith("/home.html")) { document.getElementById("wv-item-" + id + "-bar-address").value = ""; } else { document.getElementById("wv-item-" + id + "-bar-address").value = document.getElementById("wv-item-" + id + "-inner").getURL(); } } - function openTab(url) { + function openTab(url, focusSearchBar) { let container = document.createElement("div"); let webview = document.createElement("webview"); + let tab = { icon: "./icons/placeholder.svg", - name: "Unnamed tab", + name: "New Tab", url, webview: container, id: crypto.randomUUID(), @@ -200,6 +302,12 @@ webview.id = "wv-item-" + tab.id + "-inner"; container.id = "wv-item-" + tab.id; container.classList.add("wv-container"); + webview.addEventListener('devtools-open-url', (e) => { + openTab(e.url); + }); + webview.addEventListener('close', () => { + closeTab(tabs.map((i, j) => [i, j]).filter(i => i[0].id === tab.id)[0][1]); + }); webview.addEventListener('page-title-updated', (e) => { if (webview.getURL().startsWith("https://school.equestria.dev/")) { tab.name = "Chat"; @@ -209,6 +317,9 @@ refreshTabBar(); }); + webview.addEventListener('context-menu', (e) => { + ipcRenderer.send('menu', e.params); + }); webview.addEventListener('page-favicon-updated', (e) => { if (webview.getURL().startsWith("https://school.equestria.dev/")) { tab.icon = "./icons/chat.svg"; @@ -242,6 +353,7 @@ document.getElementById('wv-item-' + tab.id + '-bar-address').onkeydown = (e) => { if (e.code === "Return" || e.code === "Enter") { loadURL(tab.id); + document.getElementById('wv-item-' + tab.id + '-bar-address').blur(); } } @@ -249,6 +361,10 @@ refreshTabBar(); switchToTab(tabs.length - 1); + + if (focusSearchBar) { + document.getElementById("wv-item-" + tab.id + "-bar-address").focus(); + } } function switchToTab(id) { @@ -274,7 +390,7 @@ } function openHome() { - openTab("https://start.duckduckgo.com"); + openTab("./home.html", true); } function closeTab(id) { @@ -335,8 +451,10 @@ } } - openTab("https://school.equestria.dev"); - openHome(); + window.onload = () => { + openTab("https://school.equestria.dev"); + openHome(); + } </script> </body> </html>
\ No newline at end of file diff --git a/client/main.js b/client/main.js index 0586b46..000d903 100755 --- a/client/main.js +++ b/client/main.js @@ -1,407 +1,591 @@ -const { app, BrowserWindow, webContents, globalShortcut, ipcMain, session, dialog, MenuItem, Menu, desktopCapturer, clipboard, nativeImage } = require('electron');
-const path = require('path');
-const os = require("os");
-const {appendFileSync, writeFileSync, existsSync, unlinkSync} = require("fs");
-const fs = require("fs");
-
-try {
- if (!app.getAppPath().endsWith("/launcher/client")) writeFileSync(app.getAppPath() + "/index.html", `
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <title>Chatroom</title>
- <style>
- #loader-circle-1, #loader-circle-2, #loader-circle-3 {
- animation-name: opacity;
- animation-timing-function: linear;
- animation-duration: 1.2s;
- animation-fill-mode: forwards;
- animation-iteration-count: infinite;
- }
-
- #loader-circle-2 {
- animation-delay: .25s;
- }
-
- #loader-circle-3 {
- animation-delay: .5s;
- }
-
- @keyframes opacity {
- 0% {
- opacity: 0;
- }
- 50% {
- opacity: 1;
- }
- 100% {
- opacity: 0;
- }
- }
- </style>
- <script>
- const { ipcRenderer } = require('electron');
-
- ipcRenderer.on('local', (_, data) => {
- loadApp(data);
- });
-
- ipcRenderer.on('download', (_) => {
- download();
- });
-
- function download() {
- document.getElementById("status").innerText = "Downloading application... 0%";
-
- const axios = require('./node_modules/axios/dist/node/axios.cjs');
- const fs = require("fs");
- const zlib = require("zlib");
- const crypto = require("crypto");
-
- let tempDir = require('@electron/remote').app.getPath('userData') + "/Chatroom";
- if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true });
- fs.mkdirSync(tempDir);
-
- function downloadClient() {
- return new Promise(async (res) => {
- const response = await axios({
- url: "http://51.68.173.117:21938/update/client.lctpk?_" + require('crypto').randomBytes(64).toString("hex"),
- method: 'GET',
- responseType: 'blob',
- onDownloadProgress: (event) => {
- document.getElementById("status").innerText = "Downloading application... " + Math.round(((event.loaded / event.total) / 2) * 100) + "%";
- }
- });
-
- document.getElementById("status").innerText = "Extracting...";
-
- res(JSON.parse(zlib.brotliDecompressSync(Buffer.from(await response.data.arrayBuffer())).toString()).map(i => {
- if (i['content']) i['content'] = zlib.brotliDecompressSync(Buffer.from(i['content'], "base64"));
- if (i['hash']) i['hash'] = crypto.createHash("sha256").update(i['content']).digest("base64") === i['hash'];
- return i;
- }));
- });
- }
-
- (async () => {
- let _client = await downloadClient();
- let files = [..._client];
-
- document.getElementById("status").innerText = "Installing application... 0%";
- let total = files.length;
- let index = 0;
-
- for (let file of files) {
- if (file.type === "file" && !file.hash) {
- alert("Unable to continue: file " + file.name + " is corrupted");
- window.close();
- }
-
- if (file.type === "file") {
- fs.writeFileSync(tempDir + "/" + file.name, file.content);
- } else {
- if (!fs.existsSync(tempDir + "/" + file.name)) fs.mkdirSync(tempDir + "/" + file.name);
- }
-
- index++;
- document.getElementById("status").innerText = "Installing application... " + Math.round((index / total) * 100) + "%";
- }
-
- document.getElementById("status").innerText = "Starting...";
-
- loadApp(tempDir + "/client");
- })();
- }
-
- function loadApp(path) {
- ipcRenderer.send("start", path);
- }
-
- //alert("Automatic updates could work on this system! Please click on OK and tell Raindrops.");
- </script>
-</head>
-<body style="margin: 0; user-select: none;">
- <div style="position: fixed; inset: 0; z-index: 9999; -webkit-app-region: drag;"></div>
-
- <div style="position: fixed; inset: 0; z-index: 999; display: flex; align-items: center; justify-content: center; text-align: center;">
- <div>
- <svg style="opacity: .25;" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 203.96 171.05">
- <defs>
- <style>
- .cls-1 {
- fill: #fff;
- }
- </style>
- </defs>
- <path class="cls-1" d="M40.49,144.2c-3.75-2.02-6.68-4.84-8.77-8.44-2.09-3.61-3.14-7.51-3.14-11.69v-45.47l-22.73-12.55c-2.04-1.14-3.53-2.56-4.45-4.27-.93-1.71-1.39-3.6-1.39-5.69s.46-3.92,1.39-5.71c.93-1.79,2.41-3.27,4.45-4.47L84.66,2.81c1.73-1.01,3.52-1.73,5.36-2.17s3.74-.65,5.68-.65,3.83,.22,5.68,.65,3.63,1.15,5.36,2.17l91.37,49.8c1.86,.95,3.29,2.32,4.32,4.13,1.02,1.8,1.53,3.75,1.53,5.83v61.06c0,3.18-1.12,5.88-3.36,8.12s-4.94,3.36-8.12,3.36-5.88-1.12-8.12-3.36c-2.24-2.24-3.36-4.94-3.36-8.12v-55.21l-18.19,10.18v45.47c0,4.19-1.05,8.08-3.14,11.69-2.09,3.61-5.02,6.42-8.77,8.44l-44.17,24.03c-1.73,1.01-3.52,1.73-5.36,2.17-1.84,.43-3.74,.65-5.68,.65s-3.83-.22-5.68-.65c-1.84-.43-3.63-1.15-5.36-2.17l-44.17-24.03Zm55.21-55.43l60.63-32.91L95.7,23.17,35.29,55.86l60.41,32.91Zm0,59.11l44.17-23.82v-33.56l-33.13,18.4c-1.73,1.01-3.5,1.73-5.3,2.17-1.8,.43-3.72,.65-5.74,.65s-3.93-.22-5.74-.65-3.57-1.15-5.3-2.17l-33.13-18.4v33.56l44.17,23.82Z"/>
- </svg>
- <br>
- <p style="color: white; opacity: .25; font-family: system-ui, -apple-system, sans-serif;" id="status">Starting...</p>
- </div>
- </div>
-</body>
-</html>
-`);
-} catch (e) {
- console.error(e);
-}
-
-const { ElectronBlocker } = require('@cliqz/adblocker-electron');
-const { fetch } = require('cross-fetch');
-
-ElectronBlocker.fromPrebuiltAdsAndTracking(fetch).then((blocker) => {
- global.blocker = blocker;
-});
-
-ipcMain.on('enable-protection', () => {
- let waiter = setInterval(() => {
- if (global.blocker) {
- clearInterval(waiter);
- try { global.blocker.enableBlockingInSession(session.defaultSession); } catch (e) {
- console.error(e);
- }
- }
- });
-});
-
-ipcMain.on('disable-protection', () => {
- let waiter = setInterval(() => {
- if (global.blocker) {
- clearInterval(waiter);
- try { global.blocker.disableBlockingInSession(session.defaultSession); } catch (e) {
- console.error(e);
- }
- }
- });
-});
-
-session.defaultSession.setUserAgent(session.defaultSession.getUserAgent().replace(/(.*)( Electron\/(.*) )/gm, "$1 ") + " Chatroom/1.0.0");
-
-let localchatDataRoot = (os.platform() === "win32" ? os.homedir() + "/AppData/Roaming" : (os.platform() === "darwin" ? os.homedir() + "/Library/Application Support" : os.homedir())) + (os.platform() === "darwin" ? "/ChatroomWorkspace" : "/.chatroom-workspace");
-
-if (!fs.existsSync(localchatDataRoot)) fs.mkdirSync(localchatDataRoot);
-if (!fs.existsSync(localchatDataRoot + "/session")) fs.mkdirSync(localchatDataRoot + "/session");
-if (!fs.existsSync(localchatDataRoot + "/data")) fs.mkdirSync(localchatDataRoot + "/data");
-if (!fs.existsSync(localchatDataRoot + "/logs")) fs.mkdirSync(localchatDataRoot + "/logs");
-
-app.setPath("userData", localchatDataRoot + "/data");
-app.setPath("sessionData", localchatDataRoot + "/session");
-app.setAppLogsPath(localchatDataRoot + "/logs");
-
-if (require('os').platform() !== "darwin" && require('os').platform() !== "win32" && require('os').platform() !== "linux") return;
-global.windows = [];
-
-if (!global._localchatPath) {
- global.nextGenChatroom = true;
- global._localchatPath = __dirname;
-}
-
-const createWindow = () => {
- app.setPath("userData", localchatDataRoot);
- app.setPath("sessionData", localchatDataRoot + "/session");
- app.setAppLogsPath(localchatDataRoot + "/logs");
-
- global.mainWindow = new BrowserWindow({
- width: 1280,
- minWidth: 300,
- height: 720,
- minHeight: 300,
- titleBarStyle: "hidden",
- titleBarOverlay: {
- color: "#eeeeee",
- symbolColor: "#222222",
- height: 43
- },
- trafficLightPosition: {
- x: 15,
- y: 15
- },
- icon: require('os').platform() === "darwin" ? "./icon.icns" : (require('os').platform() === "linux" ? "./icon.png" : "./icon.ico"),
- show: false,
- fullscreenable: false,
- autoHideMenuBar: true,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false,
- additionalArguments: "--user-data-dir=\"" + localchatDataRoot + "/client" + "\"",
- webviewTag: true
- }
- });
-
- if (global.nextGenChatroom) {
- mainWindow.loadFile(global._localchatPath + "/index.html");
- } else {
- mainWindow.loadFile(global._localchatPath + "/block.html");
- }
-
- let menu = Menu.buildFromTemplate([
- ...(process.platform === "darwin" ? [
- {
- role: "appMenu",
- }
- ] : []),
- {
- type: "submenu",
- label: "File",
- submenu: [
- {
- label: "New Tab",
- click: (_, win) => {
- win.webContents.executeJavaScript('window.openHome();');
- },
- accelerator: "CmdOrCtrl+T"
- },
- {
- label: "Switch to Next Tab",
- click: (_, win) => {
- win.webContents.executeJavaScript('window.switchRight();');
- },
- accelerator: "Ctrl+Tab"
- },
- {
- label: "Switch to Previous Tab",
- click: (_, win) => {
- win.webContents.executeJavaScript('window.switchLeft();');
- },
- accelerator: "Ctrl+Shift+Tab"
- },
- {
- label: "Close Tab",
- click: (_, win) => {
- win.webContents.executeJavaScript('window.closeCurrentTab();');
- },
- accelerator: "CmdOrCtrl+W"
- }
- ]
- },
- {
- role: "editMenu"
- },
- {
- type: "submenu",
- label: "View",
- submenu: [
- {
- label: "Host",
- submenu: [
- {
- role: "reload",
- label: "Reload",
- accelerator: "CmdOrCtrl+Alt+R"
- },
- {
- role: "forceReload",
- label: "Force Reload",
- accelerator: "CmdOrCtrl+Shift+Alt+R"
- },
- {
- role: "toggleDevTools",
- label: "Toggle Developer Tools",
- accelerator: "CmdOrCtrl+Alt+Shift+I"
- }
- ]
- },
- {
- label: "Renderer",
- submenu: [
- {
- label: "Reload",
- accelerator: "CmdOrCtrl+R",
- click: () => {
- mainWindow.webContents.executeJavaScript('window.reloadWebview(false);');
- }
- },
- {
- label: "Force Reload",
- accelerator: "CmdOrCtrl+Shift+R",
- click: () => {
- mainWindow.webContents.executeJavaScript('window.reloadWebview(true);');
- }
- },
- {
- label: "Toggle Developer Tools",
- accelerator: "CmdOrCtrl+Alt+I",
- click: () => {
- mainWindow.webContents.executeJavaScript('window.openDevTools();');
- }
- }
- ]
- },
- {
- type: "separator"
- },
- {
- role: "resetZoom"
- },
- {
- role: "zoomIn"
- },
- {
- role: "zoomOut"
- },
- {
- type: "separator"
- },
- {
- role: "togglefullscreen"
- }
- ]
- },
- {
- role: "windowMenu"
- }
- ]);
-
- mainWindow.setMenu(menu);
- Menu.setApplicationMenu(menu);
-
- mainWindow.webContents.setWindowOpenHandler(() => {
- return {
- action: "deny"
- }
- });
-
- windows.push(mainWindow);
- if (os.platform() === "win32") mainWindow.setContentProtection(true);
-
- ipcMain.on('setupIcon', (e, id, index) => {
- webContents.fromId(id).on('page-favicon-updated', (e, icons) => {
- mainWindow.send("favicon", {
- index,
- icons
- });
- })
- });
-
- mainWindow.once('ready-to-show', () => {
- mainWindow.show();
- try { loaderWindow.close(); } catch (e) {}
- });
-}
-
-app.whenReady().then(() => {
- globalShortcut.register('Alt+CommandOrControl+C', () => {
- for (let window of windows) {
- try {
- if (!window.isVisible()) {
- window.show();
- if (process.platform === "darwin") app.dock.show();
- } else {
- window.hide();
- if (process.platform === "darwin") app.dock.hide();
- }
- } catch (e) {}
- }
- });
-
- createWindow();
-
- app.on('activate', () => {
- if (BrowserWindow.getAllWindows().length === 0) createWindow();
- });
-});
-
-app.on('window-all-closed', () => {
- if (process.platform !== 'darwin' || !global.nextGenChatroom) app.quit();
+// --- >START< @BUILDNUMBER@ >START< --- // +const buildNumber = "main"; +// --- >FINAL< @BUILDNUMBER@ >FINAL< --- // + +const version = "2.6.0"; + +const { app, BrowserWindow, webContents, globalShortcut, nativeTheme, ipcMain, session, dialog, MenuItem, Menu, desktopCapturer, clipboard, nativeImage } = require('electron'); +const path = require('path'); +const os = require("os"); +const {appendFileSync, writeFileSync, existsSync, unlinkSync} = require("fs"); +const fs = require("fs"); + +app.setName("Chatroom"); +app.setAboutPanelOptions({ + applicationName: "Chatroom", + applicationVersion: version, + copyright: "Copyright © 2023-" + new Date().getFullYear() + " Equestria.dev. Released under the MIT License.", + version: buildNumber +}); + +try { + if (!app.getAppPath().endsWith("/launcher/client")) writeFileSync(app.getAppPath() + "/index.html", ` +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Chatroom</title> + <style> + @keyframes loaded-1 { + 0% { + background-color: #111111; + } + + 100% { + background-color: #1ABCB9; + } + } + + @keyframes loaded-2 { + 0% { + opacity: .3; + filter: drop-shadow(0 0 0 transparent); + } + + 100% { + opacity: 1; + filter: drop-shadow(0 0 15px rgba(0, 0, 0, .5)); + } + } + + body.loaded { + animation-name: loaded-1; + animation-duration: .5s; + animation-iteration-count: 1; + animation-fill-mode: forwards; + animation-direction: normal; + animation-play-state: running; + animation-timing-function: ease-in-out; + } + + body.loaded #ic { + animation-name: loaded-2; + animation-duration: .5s; + animation-iteration-count: 1; + animation-fill-mode: forwards; + animation-direction: normal; + animation-play-state: running; + animation-timing-function: ease-in-out; + } + </style> + <script> + const { ipcRenderer } = require('electron'); + + ipcRenderer.on('local', (_, data) => { + download(data); + }); + + ipcRenderer.on('download', (_) => { + download(null); + }); + + function download(data) { + const axios = require('./node_modules/axios/dist/node/axios.cjs'); + const fs = require("fs"); + const zlib = require("zlib"); + const crypto = require("crypto"); + + let tempDir = require('@electron/remote').app.getPath('userData') + "/Chatroom"; + if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true }); + fs.mkdirSync(tempDir); + + function downloadClient() { + document.getElementById("progress-outer").style.display = ""; + + return new Promise(async (res) => { + const response = await axios({ + url: "http://51.68.173.117:21938/update/client.lctpk?_" + require('crypto').randomBytes(64).toString("hex"), + method: 'GET', + responseType: 'blob', + onDownloadProgress: (event) => { + document.getElementById("progress").style.width = ((event.loaded / event.total) * 100) + "%"; + } + }); + + res(JSON.parse(zlib.brotliDecompressSync(Buffer.from(await response.data.arrayBuffer())).toString()).map(i => { + if (i['content']) i['content'] = zlib.brotliDecompressSync(Buffer.from(i['content'], "base64")); + if (i['hash']) i['hash'] = crypto.createHash("sha256").update(i['content']).digest("base64") === i['hash']; + return i; + })); + }); + } + + (async () => { + let _client = await downloadClient(); + let files = [..._client]; + + let total = files.length; + let index = 0; + + for (let file of files) { + if (file.type === "file" && !file.hash) { + alert("Unable to continue: file " + file.name + " is corrupted"); + window.close(); + } + + if (file.type === "file") { + fs.writeFileSync(tempDir + "/" + file.name, file.content); + } else { + if (!fs.existsSync(tempDir + "/" + file.name)) fs.mkdirSync(tempDir + "/" + file.name); + } + + index++; + document.getElementById("progress").style.width = ((index / total) * 100) + "%"; + } + + document.getElementById("progress-outer").style.display = "none"; + document.body.classList.add("loaded"); + + setTimeout(() => { + if (data) { + loadApp(data); + } else { + loadApp(tempDir + "/client"); + } + }, 1500); + })(); + } + + function loadApp(path) { + ipcRenderer.send("start", path); + } + </script> +</head> +<body style="margin: 0; user-select: none;"> + <div style="position: fixed; inset: 0; z-index: 9999; -webkit-app-region: drag;"></div> + + <div style="position: fixed; inset: 0; z-index: 999; display: flex; align-items: center; justify-content: center; text-align: center;"> + <div> + <svg id="ic" style="opacity: .3; width: 64px;" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 203.96 171.05"> + <defs> + <style> + .cls-1 { + fill: #fff; + } + </style> + </defs> + <path class="cls-1" d="M40.49,144.2c-3.75-2.02-6.68-4.84-8.77-8.44-2.09-3.61-3.14-7.51-3.14-11.69v-45.47l-22.73-12.55c-2.04-1.14-3.53-2.56-4.45-4.27-.93-1.71-1.39-3.6-1.39-5.69s.46-3.92,1.39-5.71c.93-1.79,2.41-3.27,4.45-4.47L84.66,2.81c1.73-1.01,3.52-1.73,5.36-2.17s3.74-.65,5.68-.65,3.83,.22,5.68,.65,3.63,1.15,5.36,2.17l91.37,49.8c1.86,.95,3.29,2.32,4.32,4.13,1.02,1.8,1.53,3.75,1.53,5.83v61.06c0,3.18-1.12,5.88-3.36,8.12s-4.94,3.36-8.12,3.36-5.88-1.12-8.12-3.36c-2.24-2.24-3.36-4.94-3.36-8.12v-55.21l-18.19,10.18v45.47c0,4.19-1.05,8.08-3.14,11.69-2.09,3.61-5.02,6.42-8.77,8.44l-44.17,24.03c-1.73,1.01-3.52,1.73-5.36,2.17-1.84,.43-3.74,.65-5.68,.65s-3.83-.22-5.68-.65c-1.84-.43-3.63-1.15-5.36-2.17l-44.17-24.03Zm55.21-55.43l60.63-32.91L95.7,23.17,35.29,55.86l60.41,32.91Zm0,59.11l44.17-23.82v-33.56l-33.13,18.4c-1.73,1.01-3.5,1.73-5.3,2.17-1.8,.43-3.72,.65-5.74,.65s-3.93-.22-5.74-.65-3.57-1.15-5.3-2.17l-33.13-18.4v33.56l44.17,23.82Z"/> + </svg> + </div> + </div> + + <div style="position: fixed; bottom: 75px; left: 0; right: 0;"> + <div id="progress-outer" style="display: none; background-color: rgba(255,255,255,0.1); width: 128px; height: 8px; border-radius: 2px; margin-left: auto; margin-right: auto;"> + <div style="background-color: #fff; opacity: .3; width: 0; height: 8px; border-radius: 2px;" id="progress"></div> + </div> + </div> +</body> +</html> +`); +} catch (e) { + console.error(e); +} + +const { ElectronBlocker } = require('@cliqz/adblocker-electron'); +const { fetch } = require('cross-fetch'); + +ElectronBlocker.fromPrebuiltAdsAndTracking(fetch).then((blocker) => { + global.blocker = blocker; +}); + +ipcMain.on('enable-protection', () => { + let waiter = setInterval(() => { + if (global.blocker) { + clearInterval(waiter); + try { global.blocker.enableBlockingInSession(session.defaultSession); } catch (e) { + console.error(e); + } + } + }); +}); + +ipcMain.on('disable-protection', () => { + let waiter = setInterval(() => { + if (global.blocker) { + clearInterval(waiter); + try { global.blocker.disableBlockingInSession(session.defaultSession); } catch (e) { + console.error(e); + } + } + }); +}); + +session.defaultSession.setUserAgent(session.defaultSession.getUserAgent().replace(/(.*)( Electron\/(.*) )/gm, "$1 ").replace(/(.*)( Chatroom\/(.*) )/gm, "$1 ") + " Chatroom/" + version); + +let localchatDataRoot = (os.platform() === "win32" ? os.homedir() + "/AppData/Roaming" : (os.platform() === "darwin" ? os.homedir() + "/Library/Application Support" : os.homedir())) + (os.platform() === "darwin" ? "/ChatroomWorkspace" : "/.chatroom-workspace"); + +if (!fs.existsSync(localchatDataRoot)) fs.mkdirSync(localchatDataRoot); +if (!fs.existsSync(localchatDataRoot + "/session")) fs.mkdirSync(localchatDataRoot + "/session"); +if (!fs.existsSync(localchatDataRoot + "/data")) fs.mkdirSync(localchatDataRoot + "/data"); +if (!fs.existsSync(localchatDataRoot + "/logs")) fs.mkdirSync(localchatDataRoot + "/logs"); + +app.setPath("userData", localchatDataRoot + "/data"); +app.setPath("sessionData", localchatDataRoot + "/session"); +app.setAppLogsPath(localchatDataRoot + "/logs"); + +if (require('os').platform() !== "darwin" && require('os').platform() !== "win32" && require('os').platform() !== "linux") return; +global.windows = []; + +if (!global._localchatPath) { + global.nextGenChatroom = true; + global._localchatPath = __dirname; +} + +app.on('before-quit', (event) => { + if (dialog.showMessageBoxSync({ + type: "error", + message: "Quit Chatroom?", + detail: "Are you sure you want to quit Chatroom? Unsaved data will be lost.", + noLink: true, + buttons: ["Yes", "No"] + }) === 1) { + event.preventDefault(); + } +}); + +const createWindow = () => { + app.setPath("userData", localchatDataRoot); + app.setPath("sessionData", localchatDataRoot + "/session"); + app.setAppLogsPath(localchatDataRoot + "/logs"); + + global.mainWindow = new BrowserWindow({ + width: 1280, + minWidth: 900, + height: 720, + minHeight: 300, + titleBarStyle: "hidden", + titleBarOverlay: nativeTheme.shouldUseDarkColors ? { + color: "#111111", + symbolColor: "#eeeeee", + height: 43 + } : { + color: "#eeeeee", + symbolColor: "#222222", + height: 43 + }, + backgroundColor: nativeTheme.shouldUseDarkColors ? "#111111" : "#eeeeee", + trafficLightPosition: { + x: 15, + y: 15 + }, + icon: require('os').platform() === "darwin" ? "./icon.icns" : (require('os').platform() === "linux" ? "./icon.png" : "./icon.ico"), + show: false, + fullscreenable: false, + autoHideMenuBar: true, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + additionalArguments: "--user-data-dir=\"" + localchatDataRoot + "/client" + "\"", + webviewTag: true + } + }); + + if (global.nextGenChatroom) { + mainWindow.loadFile(global._localchatPath + "/index.html"); + } else { + mainWindow.loadFile(global._localchatPath + "/block.html"); + } + + let menu = Menu.buildFromTemplate([ + ...(process.platform === "darwin" ? [ + { + role: "appMenu", + } + ] : []), + { + type: "submenu", + label: "File", + submenu: [ + { + label: "New Tab", + click: (_, win) => { + try { win.webContents.executeJavaScript('window.openHome();'); } catch (e) { console.error(e); } + }, + accelerator: "CmdOrCtrl+T" + }, + { + label: "Switch to Next Tab", + click: (_, win) => { + try { win.webContents.executeJavaScript('window.switchRight();'); } catch (e) { console.error(e); } + }, + accelerator: "Ctrl+Tab" + }, + { + label: "Switch to Previous Tab", + click: (_, win) => { + try { win.webContents.executeJavaScript('window.switchLeft();'); } catch (e) { console.error(e); } + }, + accelerator: "Ctrl+Shift+Tab" + }, + { + label: "Close Tab", + click: (_, win) => { + try { win.webContents.executeJavaScript('window.closeCurrentTab();'); } catch (e) { console.error(e); } + }, + accelerator: "CmdOrCtrl+W" + } + ] + }, + { + role: "editMenu" + }, + { + type: "submenu", + label: "View", + submenu: [ + { + label: "Host", + submenu: [ + { + role: "reload", + label: "Reload", + accelerator: "CmdOrCtrl+Alt+R" + }, + { + role: "forceReload", + label: "Force Reload", + accelerator: "CmdOrCtrl+Shift+Alt+R" + }, + { + role: "toggleDevTools", + label: "Toggle Developer Tools", + accelerator: "CmdOrCtrl+Alt+Shift+I" + } + ] + }, + { + label: "Renderer", + submenu: [ + { + label: "Reload", + accelerator: "CmdOrCtrl+R", + click: () => { + mainWindow.webContents.executeJavaScript('window.reloadWebview(false);'); + } + }, + { + label: "Force Reload", + accelerator: "CmdOrCtrl+Shift+R", + click: () => { + mainWindow.webContents.executeJavaScript('window.reloadWebview(true);'); + } + }, + { + label: "Toggle Developer Tools", + accelerator: "CmdOrCtrl+Alt+I", + click: () => { + mainWindow.webContents.executeJavaScript('window.openDevTools();'); + } + } + ] + }, + { + type: "separator" + }, + { + role: "resetZoom" + }, + { + role: "zoomIn" + }, + { + role: "zoomOut" + }, + { + type: "separator" + }, + { + role: "togglefullscreen" + } + ] + }, + { + role: "windowMenu" + } + ]); + + mainWindow.setMenu(menu); + Menu.setApplicationMenu(menu); + + mainWindow.webContents.setWindowOpenHandler(() => { + return { + action: "deny" + } + }); + + windows.push(mainWindow); + if (os.platform() === "win32") mainWindow.setContentProtection(true); + + ipcMain.on('setupIcon', (e, id, index) => { + webContents.fromId(id).on('page-favicon-updated', (e, icons) => { + mainWindow.send("favicon", { + index, + icons + }); + }) + }); + + mainWindow.once('ready-to-show', () => { + mainWindow.show(); + try { loaderWindow.close(); } catch (e) {} + }); +} + +app.whenReady().then(() => { + globalShortcut.register('Alt+CommandOrControl+C', () => { + for (let window of windows) { + try { + if (!window.isVisible()) { + window.show(); + if (process.platform === "darwin") app.dock.show(); + } else { + window.hide(); + if (process.platform === "darwin") app.dock.hide(); + } + } catch (e) {} + } + }); + + createWindow(); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin' || !global.nextGenChatroom) app.quit(); +}); + +ipcMain.on('menu', (_, params) => { + console.log(params); + + let items = []; + + if (params.linkURL.trim() !== "") { + items.push({ + label: "Open Link in New Tab", + click: (item, win) => { + win.webContents.executeJavaScript(`openTab("${params.linkURL.replaceAll('"', '\\"')}");`); + } + }); + } + + if (params.frameURL.trim() !== "") { + items.push({ + label: "Open Frame in New Tab", + click: (item, win) => { + win.webContents.executeJavaScript(`openTab("${params.frameURL.replaceAll('"', '\\"')}");`); + } + }); + } + + if (params.srcURL.trim() !== "") { + let type = "Media"; + + switch (params.mediaType) { + case "audio": + type = "Audio"; + break; + + case "image": + type = "Image"; + break; + + case "video": + type = "Video"; + break; + + case "canvas": + type = "Canvas"; + break; + + case "file": + type = "File"; + break; + } + + items.push({ + label: "Open " + type + " in New Tab", + click: (item, win) => { + win.webContents.executeJavaScript(`openTab("${params.srcURL.replaceAll('"', '\\"')}");`); + } + }); + } + + if (process.platform === "darwin" && (params.selectionRect.width > 2 && params.selectionRect.height > 2)) { + items.push({ + label: params.selectionText.trim() === "" ? "Look Up" : "Look Up “" + (params.selectionText.length < 100 ? params.selectionText : params.selectionText.substring(0, 100) + "…") + "”", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].showDefinitionForSelection();`); + } + }); + } + + if (items.length > 0) { + items.push({ + type: "separator" + }); + } + + items.push({ + enabled: params.editFlags.canCut, + label: "Cut", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].cut();`); + } + }); + + items.push({ + enabled: params.selectionText.trim() !== "" || params.editFlags.canCopy, + label: "Copy", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].cut();`); + } + }); + + items.push({ + enabled: params.editFlags.canPaste, + label: "Paste", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].paste();`); + } + }); + + items.push({ + type: "separator" + }); + + items.push({ + enabled: params.editFlags.canSelectAll, + label: "Select All", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].selectAll();`); + } + }); + + items.push({ + enabled: params.editFlags.canUndo, + label: "Undo", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].undo();`); + } + }); + + items.push({ + enabled: params.editFlags.canRedo, + label: "Redo", + click: (item, win) => { + win.webContents.executeJavaScript(`tabs[activeTab].webview.children[1].redo();`); + } + }); + + let menu = Menu.buildFromTemplate(items); + + menu.popup({ + window: mainWindow, + x: params.x, + y: params.y, + sourceType: params.menuSourceType + }); });
\ No newline at end of file diff --git a/launcher/client/index.html b/launcher/client/index.html index 00813c7..79d70b2 100644 --- a/launcher/client/index.html +++ b/launcher/client/index.html @@ -4,48 +4,60 @@ <meta charset="UTF-8"> <title>Chatroom</title> <style> - #loader-circle-1, #loader-circle-2, #loader-circle-3 { - animation-name: opacity; - animation-timing-function: linear; - animation-duration: 1.2s; - animation-fill-mode: forwards; - animation-iteration-count: infinite; - } - - #loader-circle-2 { - animation-delay: .25s; - } + @keyframes loaded-1 { + 0% { + background-color: #111111; + } - #loader-circle-3 { - animation-delay: .5s; + 100% { + background-color: #1ABCB9; + } } - @keyframes opacity { + @keyframes loaded-2 { 0% { - opacity: 0; - } - 50% { - opacity: 1; + opacity: .3; + filter: drop-shadow(0 0 0 transparent); } + 100% { - opacity: 0; + opacity: 1; + filter: drop-shadow(0 0 15px rgba(0, 0, 0, .5)); } } + + body.loaded { + animation-name: loaded-1; + animation-duration: .5s; + animation-iteration-count: 1; + animation-fill-mode: forwards; + animation-direction: normal; + animation-play-state: running; + animation-timing-function: ease-in-out; + } + + body.loaded #ic { + animation-name: loaded-2; + animation-duration: .5s; + animation-iteration-count: 1; + animation-fill-mode: forwards; + animation-direction: normal; + animation-play-state: running; + animation-timing-function: ease-in-out; + } </style> <script> const { ipcRenderer } = require('electron'); ipcRenderer.on('local', (_, data) => { - loadApp(data); + download(data); }); ipcRenderer.on('download', (_) => { - download(); + download(null); }); - function download() { - document.getElementById("status").innerText = "Downloading application... 0%"; - + function download(data) { const axios = require('./node_modules/axios/dist/node/axios.cjs'); const fs = require("fs"); const zlib = require("zlib"); @@ -56,18 +68,18 @@ fs.mkdirSync(tempDir); function downloadClient() { + document.getElementById("progress-outer").style.display = ""; + return new Promise(async (res) => { const response = await axios({ url: "http://51.68.173.117:21938/update/client.lctpk?_" + require('crypto').randomBytes(64).toString("hex"), method: 'GET', responseType: 'blob', onDownloadProgress: (event) => { - document.getElementById("status").innerText = "Downloading application... " + Math.round(((event.loaded / event.total) / 2) * 100) + "%"; + document.getElementById("progress").style.width = ((event.loaded / event.total) * 100) + "%"; } }); - document.getElementById("status").innerText = "Extracting..."; - res(JSON.parse(zlib.brotliDecompressSync(Buffer.from(await response.data.arrayBuffer())).toString()).map(i => { if (i['content']) i['content'] = zlib.brotliDecompressSync(Buffer.from(i['content'], "base64")); if (i['hash']) i['hash'] = crypto.createHash("sha256").update(i['content']).digest("base64") === i['hash']; @@ -80,7 +92,6 @@ let _client = await downloadClient(); let files = [..._client]; - document.getElementById("status").innerText = "Installing application... 0%"; let total = files.length; let index = 0; @@ -97,12 +108,19 @@ } index++; - document.getElementById("status").innerText = "Installing application... " + Math.round((index / total) * 100) + "%"; + document.getElementById("progress").style.width = ((index / total) * 100) + "%"; } - document.getElementById("status").innerText = "Starting..."; + document.getElementById("progress-outer").style.display = "none"; + document.body.classList.add("loaded"); - loadApp(tempDir + "/client"); + setTimeout(() => { + if (data) { + loadApp(data); + } else { + loadApp(tempDir + "/client"); + } + }, 1500); })(); } @@ -116,7 +134,7 @@ <div style="position: fixed; inset: 0; z-index: 999; display: flex; align-items: center; justify-content: center; text-align: center;"> <div> - <svg style="opacity: .25;" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 203.96 171.05"> + <svg id="ic" style="opacity: .3; width: 64px;" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 203.96 171.05"> <defs> <style> .cls-1 { @@ -126,8 +144,12 @@ </defs> <path class="cls-1" d="M40.49,144.2c-3.75-2.02-6.68-4.84-8.77-8.44-2.09-3.61-3.14-7.51-3.14-11.69v-45.47l-22.73-12.55c-2.04-1.14-3.53-2.56-4.45-4.27-.93-1.71-1.39-3.6-1.39-5.69s.46-3.92,1.39-5.71c.93-1.79,2.41-3.27,4.45-4.47L84.66,2.81c1.73-1.01,3.52-1.73,5.36-2.17s3.74-.65,5.68-.65,3.83,.22,5.68,.65,3.63,1.15,5.36,2.17l91.37,49.8c1.86,.95,3.29,2.32,4.32,4.13,1.02,1.8,1.53,3.75,1.53,5.83v61.06c0,3.18-1.12,5.88-3.36,8.12s-4.94,3.36-8.12,3.36-5.88-1.12-8.12-3.36c-2.24-2.24-3.36-4.94-3.36-8.12v-55.21l-18.19,10.18v45.47c0,4.19-1.05,8.08-3.14,11.69-2.09,3.61-5.02,6.42-8.77,8.44l-44.17,24.03c-1.73,1.01-3.52,1.73-5.36,2.17-1.84,.43-3.74,.65-5.68,.65s-3.83-.22-5.68-.65c-1.84-.43-3.63-1.15-5.36-2.17l-44.17-24.03Zm55.21-55.43l60.63-32.91L95.7,23.17,35.29,55.86l60.41,32.91Zm0,59.11l44.17-23.82v-33.56l-33.13,18.4c-1.73,1.01-3.5,1.73-5.3,2.17-1.8,.43-3.72,.65-5.74,.65s-3.93-.22-5.74-.65-3.57-1.15-5.3-2.17l-33.13-18.4v33.56l44.17,23.82Z"/> </svg> - <br> - <p style="color: white; opacity: .25; font-family: system-ui, -apple-system, sans-serif;" id="status">Starting...</p> + </div> + </div> + + <div style="position: fixed; bottom: 75px; left: 0; right: 0;"> + <div id="progress-outer" style="display: none; background-color: rgba(255,255,255,0.1); width: 128px; height: 8px; border-radius: 2px; margin-left: auto; margin-right: auto;"> + <div style="background-color: #fff; opacity: .3; width: 0; height: 8px; border-radius: 2px;" id="progress"></div> </div> </div> </body> |