From 315fb5221d0ad5b9e6826f243ab4c195c0680846 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 23 Oct 2023 23:32:25 +0200 Subject: [PATCH] Rebrand Settings to More --- README.md | 23 +-- css/Flags/Dark.css | 8 +- css/Pages/Home.css | 24 ++- css/Pages/More/More.css | 14 ++ css/Pages/More/Privacy.css | 80 +++++++++ css/Pages/More/Settings.css | 72 ++++++++ css/Pages/Pages.css | 2 +- css/Pages/Settings/Settings.css | 165 ------------------ index.html | 10 +- js/App.js | 4 +- js/UI/Drawer/Drawer.js | 4 +- js/UI/Home/Home.js | 6 +- js/UI/More/More.js | 40 +++++ .../Settings.js => More/Privacy/Privacy.js} | 80 ++------- .../security.js => More/Privacy/analyzer.js} | 0 js/UI/More/Privacy/tiles.js | 27 +++ js/UI/More/Settings/Settings.js | 51 ++++++ js/UI/{ => More}/Settings/events.js | 0 js/UI/{ => More}/Settings/tiles.js | 32 +--- public/config/config.json | 3 +- 20 files changed, 356 insertions(+), 289 deletions(-) create mode 100644 css/Pages/More/More.css create mode 100644 css/Pages/More/Privacy.css create mode 100644 css/Pages/More/Settings.css delete mode 100644 css/Pages/Settings/Settings.css create mode 100644 js/UI/More/More.js rename js/UI/{Settings/Settings.js => More/Privacy/Privacy.js} (50%) rename js/UI/{Settings/security.js => More/Privacy/analyzer.js} (100%) create mode 100644 js/UI/More/Privacy/tiles.js create mode 100644 js/UI/More/Settings/Settings.js rename js/UI/{ => More}/Settings/events.js (100%) rename js/UI/{ => More}/Settings/tiles.js (53%) diff --git a/README.md b/README.md index 32c88bc..9ca8e5d 100644 --- a/README.md +++ b/README.md @@ -26,17 +26,18 @@ Configuration file is located at `config/config.json`. It is pretty readable, so The following keys are available under `ui` section. Some of them are listed in _Settings_ page and can be overriden by end-user. -| Key name | Description | in Settings | -|-----------------------|---------------------------------------------------------------------------------------|---------------| -| `name` | Name shown at the main screen and the tab title. | ❌ | -| `desc` | Short description shown under title at the main screen. | ❌ | -| `icon` | Icon shown at the main screen and as site's favicon. | ❌ | -| `wallpaper` | Background image visible when dark mode is disabled. | ❌ | -| `wallpaper_dark` | Background image visible when dark mode is enabled. | ❌ | -| `dark_mode` | Tells whether dark mode is enabled by default. | ✅ | -| `open_new_tab` | Tells whether clicking on a service will open it in new tab by default. | ✅ | -| `blur` | Tells whether card background blur is enabled by default. | ✅ | -| `animations` | Tells whether UI animations are enabled by default. | ✅ | +| Key name | Description | in Settings | +|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|---------------| +| `name` | Name shown at the main screen and the tab title. | ❌ | +| `desc` | Short description shown under title at the main screen. | ❌ | +| `icon` | Icon shown at the main screen and as site's favicon. | ❌ | +| `wallpaper` | Background image visible when dark mode is disabled. | ❌ | +| `wallpaper_dark` | Background image visible when dark mode is enabled. | ❌ | +| `dark_mode` | Tells whether dark mode is enabled by default. | ✅ | +| `open_new_tab` | Tells whether clicking on a service will open it in new tab by default. | ✅ | +| `blur` | Tells whether card background blur is enabled by default. | ✅ | +| `animations` | Tells whether UI animations are enabled by default. | ✅ | +| `https_importance` | How important is HTTPS comparing to independence. If set to `0.25`, HTTPS will score maximum 25% in Privacy Panel. Total importance is `1`. | ✅ | ### 🔗 Adding custom services diff --git a/css/Flags/Dark.css b/css/Flags/Dark.css index 589bfcf..93424a4 100644 --- a/css/Flags/Dark.css +++ b/css/Flags/Dark.css @@ -6,6 +6,10 @@ body.dark { --hover: #FFF1; } -body.dark #theme-switcher i::after { - content: "dark_mode" +body.dark #theme-switcher i::before { + --hidden: 1; +} + +body.dark #theme-switcher i::after { + --hidden: 0; } diff --git a/css/Pages/Home.css b/css/Pages/Home.css index 85615a7..71c0eac 100644 --- a/css/Pages/Home.css +++ b/css/Pages/Home.css @@ -18,8 +18,30 @@ opacity: 0; } +#theme-switcher i { + position: relative; + overflow: hidden; +} + +#theme-switcher i::before, #theme-switcher i::after { + position: absolute; + top: 50%; + left: 50%; + --hidden: 1; + opacity: calc(1 - var(--hidden)); + transform: translate(-50%, -50%) rotateZ(calc(var(--hidden) * 360deg)) scale(calc(1 - var(--hidden) / 2)); + transition: transform .3s, opacity .3s; +} + +#theme-switcher i::before { + --hidden: 0; + --dark: 0; + content: "light_mode"; +} + #theme-switcher i::after { - content: "light_mode" + --dark: 1; + content: "dark_mode"; } .home.page { diff --git a/css/Pages/More/More.css b/css/Pages/More/More.css new file mode 100644 index 0000000..bd60dbc --- /dev/null +++ b/css/Pages/More/More.css @@ -0,0 +1,14 @@ +@import url(Privacy.css); +@import url(Settings.css); + +.subpages { + position: relative; + transform: translateX(calc(var(--id) * -100%)); + transition: transform .4s, height .4s; +} + +.subpages > div { + position: absolute; + left: calc(var(--n) * 100%); + width: 100%; +} diff --git a/css/Pages/More/Privacy.css b/css/Pages/More/Privacy.css new file mode 100644 index 0000000..bb756ae --- /dev/null +++ b/css/Pages/More/Privacy.css @@ -0,0 +1,80 @@ +#report-boxes { + display: flex; + text-align: left; + flex-wrap: wrap; + margin-bottom: 8px; +} + +#report-boxes i::after { + color: var(--color); + text-shadow: 0 0 48px var(--color); + padding: 16px; + font-size: 28px; + border-radius: 32px; +} + +#report-boxes .icon-https::after { + --color: #0C7; + content: "lock"; +} + +#report-boxes .icon-rocket::after { + --color: #68F; + content: "rocket_launch"; +} + +#report-boxes .prewarn i::after { + --color: #EA0; +} + +#report-boxes .warn i::after { + --color: #F60; +} + +#report-boxes .error i::after { + --color: #F22; +} + +#report-boxes > div { + display: flex; + width: 50%; + min-width: 256px; + flex: 1; + padding: 20px 8px; + align-items: center; +} + +#report-boxes .title { + font-size: 16px; +} + +#report-boxes .subtitle { + opacity: .6; +} + +.security { + display: flex; + align-items: center; + justify-content: space-between; + max-width: 600px; + padding: 24px; + margin: 120px auto 80px; + text-align: right; +} + +.security i { + font-size: 80px; +} + +.security #report-score { + font-size: 48px; +} + +.security #report { + opacity: .6; +} + +.score::after { + content: "%"; + font-size: 18px; +} \ No newline at end of file diff --git a/css/Pages/More/Settings.css b/css/Pages/More/Settings.css new file mode 100644 index 0000000..35b961d --- /dev/null +++ b/css/Pages/More/Settings.css @@ -0,0 +1,72 @@ +.settings { + margin: 32px auto; + padding: 0 16px; +} + +.setting { + background: var(--bg2); + margin: 8px; + padding: 20px; + display: flex; + cursor: pointer; + border-radius: 16px; + align-items: center; + text-align: left; + transition: background .3s; +} + +.setting i { + margin-right: 14px; + font-size: 28px; +} + +.setting .name { + font-size: 16px; +} + +.setting .desc { + opacity: .6; + margin-right: 16px; +} + +.setting .switch { + position: relative; + width: 44px; + min-width: 44px; + height: 24px; + background: #8886; + border-radius: 100px; + margin: 0 4px 0 auto; + transition: border .4s, background .3s; +} + +.setting .switch:after { + content: ""; + position: absolute; + width: 16px; + height: 16px; + background: var(--color); + left: 4px; + top: 50%; + border-radius: 10px; + transform: translateY(-50%); + transition: left .2s, background .3s; +} + +.setting.checked .switch { + background-color: #68F; + border-color: #68F; +} + +.setting.checked .switch:after { + left: calc(100% - 20px); +} + +#no-cookies { + margin: 24px 0 -8px; + color: #F60; +} + +#no-cookies.hidden { + display: none; +} \ No newline at end of file diff --git a/css/Pages/Pages.css b/css/Pages/Pages.css index 4fa4c1a..655f598 100644 --- a/css/Pages/Pages.css +++ b/css/Pages/Pages.css @@ -1,6 +1,6 @@ @import url(Home.css); @import url(Services.css); -@import url(Settings/Settings.css); +@import url(More/More.css); .page { position: fixed; diff --git a/css/Pages/Settings/Settings.css b/css/Pages/Settings/Settings.css deleted file mode 100644 index 6a23312..0000000 --- a/css/Pages/Settings/Settings.css +++ /dev/null @@ -1,165 +0,0 @@ -.settings { - margin: 32px auto; - padding: 0 16px; -} - -.setting { - background: var(--bg2); - margin: 8px; - padding: 20px; - display: flex; - cursor: pointer; - border-radius: 16px; - align-items: center; - text-align: left; - transition: background .3s; -} - -.setting i { - margin-right: 14px; - font-size: 28px; -} - -.setting .name { - font-size: 16px; -} - -.setting .desc { - opacity: .6; - margin-right: 16px; -} - -.setting .switch { - position: relative; - width: 44px; - min-width: 44px; - height: 24px; - background: #8886; - border-radius: 100px; - margin: 0 4px 0 auto; - transition: border .4s, background .3s; -} - -.setting .switch:after { - content: ""; - position: absolute; - width: 16px; - height: 16px; - background: var(--color); - left: 4px; - top: 50%; - border-radius: 10px; - transform: translateY(-50%); - transition: left .2s, background .3s; -} - -.setting.checked .switch { - background-color: #68F; - border-color: #68F; -} - -.setting.checked .switch:after { - left: calc(100% - 20px); -} - -#no-cookies { - margin: 24px 0 -8px; - color: #F60; -} - -#no-cookies.hidden { - display: none; -} - -.subpages { - position: relative; - transform: translateX(calc(var(--id) * -100%)); - transition: transform .4s, height .4s; -} - -.subpages > div { - position: absolute; - left: calc(var(--n) * 100%); - width: 100%; -} - -#report-boxes { - display: flex; - text-align: left; - flex-wrap: wrap; - margin-bottom: 8px; -} - -#report-boxes i::after { - color: var(--color); - text-shadow: 0 0 48px var(--color); - padding: 16px; - font-size: 28px; - border-radius: 32px; -} - -#report-boxes .icon-https::after { - --color: #0C7; - content: "lock"; -} - -#report-boxes .icon-rocket::after { - --color: #68F; - content: "rocket_launch"; -} - -#report-boxes .prewarn i::after { - --color: #EA0; -} - -#report-boxes .warn i::after { - --color: #F60; -} - -#report-boxes .error i::after { - --color: #F22; -} - -#report-boxes > div { - display: flex; - width: 50%; - min-width: 256px; - flex: 1; - padding: 20px 8px; - align-items: center; -} - -#report-boxes .title { - font-size: 16px; -} - -#report-boxes .subtitle { - opacity: .6; -} - -.security { - display: flex; - align-items: center; - justify-content: space-between; - max-width: 600px; - padding: 24px; - margin: 120px auto 80px; - text-align: right; -} - -.security i { - font-size: 80px; -} - -.security #report-score { - font-size: 48px; -} - -.security #report { - opacity: .6; -} - -.score::after { - content: "%"; - font-size: 18px; -} diff --git a/index.html b/index.html index 179a3cf..eb41044 100644 --- a/index.html +++ b/index.html @@ -21,16 +21,16 @@
- +  
Theme
apps
Services
-
- settings -
Settings
+
+ more +
More
@@ -49,7 +49,7 @@ -
+
diff --git a/js/App.js b/js/App.js index 8f6a785..df7bf48 100644 --- a/js/App.js +++ b/js/App.js @@ -1,7 +1,7 @@ import Drawer from "./UI/Drawer/Drawer" import Home from "./UI/Home/Home" import Main from "./UI/Main/Main" -import Settings from "./UI/Settings/Settings" +import More from "./UI/More/More" import Config from "./Utils/Config" import { showPage } from "./Utils/DOMUtils" @@ -20,7 +20,7 @@ export default class App { this.main = new Main() this.home = new Home() this.drawer = new Drawer() - this.settings = new Settings() + this.more = new More() showPage("home") setTimeout(() => { diff --git a/js/UI/Drawer/Drawer.js b/js/UI/Drawer/Drawer.js index 322630e..37892f3 100644 --- a/js/UI/Drawer/Drawer.js +++ b/js/UI/Drawer/Drawer.js @@ -1,7 +1,7 @@ import App from "../../App"; export default class Drawer { - constructor(name) { + constructor() { this.app = new App() this.config = this.app.config this.init() @@ -24,4 +24,4 @@ export default class Drawer { ` } } -} +} \ No newline at end of file diff --git a/js/UI/Home/Home.js b/js/UI/Home/Home.js index d2c4704..970ec0d 100644 --- a/js/UI/Home/Home.js +++ b/js/UI/Home/Home.js @@ -7,11 +7,15 @@ export default class Home { this.app = new App() this.config = this.app.config this.init() + } + + init() { + this.initButtons() this.initHomeUI() this.initBackButtons() } - init() { + initButtons() { let buttons = document.getElementsByClassName("buttons")[0].children for (let button of buttons) { let target = button.getAttribute("t") diff --git a/js/UI/More/More.js b/js/UI/More/More.js new file mode 100644 index 0000000..53e1d2a --- /dev/null +++ b/js/UI/More/More.js @@ -0,0 +1,40 @@ +import App from "../../App"; +import Privacy from "./Privacy/Privacy"; +import Settings from "./Settings/Settings"; + + +export default class More { + constructor() { + this.app = new App() + this.config = this.app.config + this.privacy = new Privacy() + this.settings = new Settings() + this.init() + } + + init() { + this.privacy.init() + this.settings.init() + this.initPager() + } + + initPager() { + let switcher = document.getElementById("switch") + let buttons = switcher.children + let subsettings = document.getElementById("subsettings") + + for (let i = 0; i < buttons.length; i++) { + let button = buttons[i] + subsettings.children[i].setAttribute("style", `--n: ${i}`) + + button.addEventListener("click", () => { + let calculatedHeight = subsettings.children[i].offsetHeight + subsettings.style.height = `${calculatedHeight}px` + subsettings.parentNode.setAttribute("style", `--id: ${i}`) + switcher.setAttribute("style", `--switches: ${buttons.length}`) + }) + } + + buttons[0].click() + } +} diff --git a/js/UI/Settings/Settings.js b/js/UI/More/Privacy/Privacy.js similarity index 50% rename from js/UI/Settings/Settings.js rename to js/UI/More/Privacy/Privacy.js index 1c4ecab..9ab9674 100644 --- a/js/UI/Settings/Settings.js +++ b/js/UI/More/Privacy/Privacy.js @@ -1,74 +1,19 @@ -import App from "../../App"; -import * as EVENTS from "./events"; -import { analyzeService } from "./security"; -import * as tiles from "./tiles" +import App from "../../../App"; +import { analyzeService } from "./analyzer"; +import { privacyBox } from "./tiles"; -export default class Settings { +export default class Privacy { constructor() { this.app = new App() this.config = this.app.config - this.init() } init() { - this.checkLocalStorage() - this.initSecurityPanel() - this.initSettings() - this.initPager() + this.initPrivacyPanel() } - initSettings() { - let darkMode = tiles.addOnOffTile(this.config, - "dark_mode", "Dark mode", - "Make the colors more appropriate for low-light environments", - "dark_mode", EVENTS.onThemeChange - ) - - tiles.addOnOffTile(this.config, - "open_in_new", "Open in new tab", - "Clicking on application will open it in a new browser tab", - "open_new_tab", EVENTS.onNewTabChange - ) - - tiles.addOnOffTile(this.config, - "blur_on", "Enable blur", - "Improves UI sweetness but may have a huge impact on performance", - "blur", EVENTS.onBlurChange - ) - - tiles.addOnOffTile(this.config, - "animation", "Animations", - "Show nice and fancy page transitions for improved experience", - "animations", EVENTS.onAnimationChange - ) - - document.getElementById("theme-switcher").addEventListener("click", () => { - darkMode.click() - }) - } - - initPager() { - let switcher = document.getElementById("switch") - let buttons = switcher.children - let subsettings = document.getElementById("subsettings") - - for (let i = 0; i < buttons.length; i++) { - let button = buttons[i] - subsettings.children[i].setAttribute("style", `--n: ${i}`) - - button.addEventListener("click", () => { - let calculatedHeight = subsettings.children[i].offsetHeight - subsettings.style.height = `${calculatedHeight}px` - subsettings.parentNode.setAttribute("style", `--id: ${i}`) - switcher.setAttribute("style", `--switches: ${buttons.length}`) - }) - } - - buttons[0].click() - } - - initSecurityPanel() { + initPrivacyPanel() { let stats = { total: 0, secure: 0, @@ -83,7 +28,8 @@ export default class Settings { let secure_pp = 100 * stats.secure / stats.total let indepencence_pp = 100 * (stats.total - stats.thirdParties) / stats.total - let privacy_score = secure_pp * 0.5 + indepencence_pp * 0.5 + let https_importance = this.config.get("https_importance") + let privacy_score = secure_pp * https_importance + indepencence_pp * (1 - https_importance) let privacy_report; if (privacy_score == 100) { @@ -101,7 +47,7 @@ export default class Settings { document.getElementById("report").innerText = privacy_report const phrase = " of the listed services are using secure connections" - tiles.privacyBox(secure_pp, "icon-https", [ + privacyBox(secure_pp, "icon-https", [ { "from": 0, "name": "No encryption", @@ -129,7 +75,7 @@ export default class Settings { } ]) - tiles.privacyBox(indepencence_pp, "icon-rocket", [ + privacyBox(indepencence_pp, "icon-rocket", [ { "from": 0, "name": "Not independent", @@ -153,8 +99,4 @@ export default class Settings { ]) } - checkLocalStorage() { - let warn = document.getElementById("no-cookies").classList - if (this.config.storageAvailable) warn.add("hidden") - } -} +} \ No newline at end of file diff --git a/js/UI/Settings/security.js b/js/UI/More/Privacy/analyzer.js similarity index 100% rename from js/UI/Settings/security.js rename to js/UI/More/Privacy/analyzer.js diff --git a/js/UI/More/Privacy/tiles.js b/js/UI/More/Privacy/tiles.js new file mode 100644 index 0000000..68492a6 --- /dev/null +++ b/js/UI/More/Privacy/tiles.js @@ -0,0 +1,27 @@ +export function privacyBox(privacyScore, icon_class, levels) { + let name, desc + levels = levels.reverse() + + for (let i in levels) { + let item = levels[i] + if (item.from <= privacyScore) { + name = levels[i].name + desc = levels[i].desc + break + } + } + + let item = document.createElement("div") + item.innerHTML = ` +
+
${name}
+
${desc}
+
` + + if (privacyScore < 30) item.classList.add("error") + else if (privacyScore < 90) item.classList.add("warn") + else if (privacyScore < 100) item.classList.add("prewarn") + + document.getElementById("report-boxes").appendChild(item) + return item +} diff --git a/js/UI/More/Settings/Settings.js b/js/UI/More/Settings/Settings.js new file mode 100644 index 0000000..9fb743b --- /dev/null +++ b/js/UI/More/Settings/Settings.js @@ -0,0 +1,51 @@ +import App from "../../../App"; +import { addOnOffTile } from "./tiles"; +import * as EVENTS from "./events" + + +export default class Settings { + constructor() { + this.app = new App() + this.config = this.app.config + } + + init() { + this.checkLocalStorage() + this.initSettings() + } + + initSettings() { + let darkMode = addOnOffTile(this.config, + "dark_mode", "Dark mode", + "Make the colors more appropriate for low-light environments", + "dark_mode", EVENTS.onThemeChange + ) + + addOnOffTile(this.config, + "open_in_new", "Open in new tab", + "Clicking on application will open it in a new browser tab", + "open_new_tab", EVENTS.onNewTabChange + ) + + addOnOffTile(this.config, + "blur_on", "Enable blur", + "Improves UI sweetness but may have a huge impact on performance", + "blur", EVENTS.onBlurChange + ) + + addOnOffTile(this.config, + "animation", "Animations", + "Show nice and fancy page transitions for improved experience", + "animations", EVENTS.onAnimationChange + ) + + document.getElementById("theme-switcher").addEventListener("click", () => { + darkMode.click() + }) + } + + checkLocalStorage() { + let warn = document.getElementById("no-cookies").classList + if (this.config.storageAvailable) warn.add("hidden") + } +} \ No newline at end of file diff --git a/js/UI/Settings/events.js b/js/UI/More/Settings/events.js similarity index 100% rename from js/UI/Settings/events.js rename to js/UI/More/Settings/events.js diff --git a/js/UI/Settings/tiles.js b/js/UI/More/Settings/tiles.js similarity index 53% rename from js/UI/Settings/tiles.js rename to js/UI/More/Settings/tiles.js index 2a535af..550f08d 100644 --- a/js/UI/Settings/tiles.js +++ b/js/UI/More/Settings/tiles.js @@ -14,10 +14,12 @@ export function addOnOffTile(conf, icon, name, desc, key, func) { if (conf.get(key)) c.add("checked") else c.remove("checked") } + let write = () => { let target_value = !conf.get(key) conf.set(key, target_value) } + let f = () => {func(conf)} item.addEventListener("click", write) @@ -28,32 +30,4 @@ export function addOnOffTile(conf, icon, name, desc, key, func) { if (func && conf.changed(key)) f() document.getElementById("settings").appendChild(item) return item -} - -export function privacyBox(privacyScore, icon_class, levels) { - let name, desc - levels = levels.reverse() - - for (let i in levels) { - let item = levels[i] - if (item.from <= privacyScore) { - name = levels[i].name - desc = levels[i].desc - break - } - } - - let item = document.createElement("div") - item.innerHTML = ` -
-
${name}
-
${desc}
-
` - - if (privacyScore < 30) item.classList.add("error") - else if (privacyScore < 90) item.classList.add("warn") - else if (privacyScore < 100) item.classList.add("prewarn") - - document.getElementById("report-boxes").appendChild(item) - return item -} +} \ No newline at end of file diff --git a/public/config/config.json b/public/config/config.json index 8141ccb..a21b1a2 100644 --- a/public/config/config.json +++ b/public/config/config.json @@ -8,7 +8,8 @@ "dark_mode": false, "open_new_tab": false, "blur": true, - "animations": true + "animations": true, + "https_importance": 0.5 }, "services": [ {