From ee076010f45db2eff4d0863b1a36ab0ddcb095b2 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 8 May 2025 10:53:37 -0700 Subject: [PATCH 1/5] Add UI template options to config file --- config/defaults-milkyway/config.json.dist | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/config/defaults-milkyway/config.json.dist b/config/defaults-milkyway/config.json.dist index 97b1b13..2fe185b 100644 --- a/config/defaults-milkyway/config.json.dist +++ b/config/defaults-milkyway/config.json.dist @@ -369,5 +369,23 @@ "min_value": 0, "max_value": false, "units": "Minutes" + }, + "ui_dialing_template": { + "value": "default", + "desc": "What page design to use for Home/Dialing", + "type": "str-enum", + "enum_values": [ + "default", + "dialing retro v1" + ] + }, + "ui_address_book_template": { + "value": "default", + "desc": "What page design to use for Address Book", + "type": "str-enum", + "enum_values": [ + "default", + "address retro v1" + ] } } From 12b4250843cd8a3788f7ae43e46177b057ada3f6 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 8 May 2025 10:54:06 -0700 Subject: [PATCH 2/5] Update web_server to redirect dialing and address_book to correct files --- classes/web_server.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/classes/web_server.py b/classes/web_server.py index 86b7fc6..6baa83a 100644 --- a/classes/web_server.py +++ b/classes/web_server.py @@ -25,7 +25,29 @@ def do_GET(self): # pylint: disable=invalid-name try: request_path, get_vars = self.parse_get_vars() - if request_path == "/get/is_alive": + if request_path == '/dial': + parsed = urllib.parse.urlparse(self.path) + template = self.stargate.cfg.get("ui_dialing_template") + + if template == 'dialing retro v1': + new_path = "/retro/dial.html" + else: + new_path = "/index.htm" + self.send_response(302) # Temporary redirect + self.send_header("Location", new_path + ("?" + parsed.query if parsed.query else "")) + self.end_headers() + return + elif request_path == '/address_book': + template = self.stargate.cfg.get("ui_address_book_template") + self.send_response(302) # Temporary redirect + if template == 'address retro v1': + self.send_header("Location", "/retro/address_book.html") + else: + self.send_header("Location", "/address_book.htm") + self.end_headers() + return + + elif request_path == "/get/is_alive": data = { 'is_alive': True } elif request_path == "/get/address_book": From 3bf320b24a5dade8c40e41e626e89314c94e35b3 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 8 May 2025 10:55:47 -0700 Subject: [PATCH 3/5] Add in retro ui with changes so links point to /stargate/(dial/address_book) instead of hard coded html files --- web/retro/address_book.html | 234 ++++++++++++ web/retro/css/address_book.css | 503 +++++++++++++++++++++++++ web/retro/css/crt.css | 232 ++++++++++++ web/retro/css/dial.css | 667 +++++++++++++++++++++++++++++++++ web/retro/dial.html | 276 ++++++++++++++ web/retro/images/dhd.svg | 8 + web/retro/images/shield.gif | Bin 0 -> 94769 bytes web/retro/js/address_book.js | 424 +++++++++++++++++++++ web/retro/js/crt.js | 35 ++ web/retro/js/dial.js | 616 ++++++++++++++++++++++++++++++ web/retro/js/navigation.js | 88 +++++ 11 files changed, 3083 insertions(+) create mode 100644 web/retro/address_book.html create mode 100644 web/retro/css/address_book.css create mode 100644 web/retro/css/crt.css create mode 100644 web/retro/css/dial.css create mode 100644 web/retro/dial.html create mode 100644 web/retro/images/dhd.svg create mode 100644 web/retro/images/shield.gif create mode 100644 web/retro/js/address_book.js create mode 100644 web/retro/js/crt.js create mode 100644 web/retro/js/dial.js create mode 100644 web/retro/js/navigation.js diff --git a/web/retro/address_book.html b/web/retro/address_book.html new file mode 100644 index 0000000..e25eed1 --- /dev/null +++ b/web/retro/address_book.html @@ -0,0 +1,234 @@ + + + + + + + + + + + + +
+ +
SYSTEM GLYPHS /
+
FILE ARCHIVE /
+
DISPLAY COMPLETE
+
+
+ +
+
Standard:.
+
Fan:.
+
+ +
+
+
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
PROFILE
+
+
+ +
+
+ + + + + +
+
+
+ 80de2ce1fb3742759aecc1a773d07450212fa26e5d9d4f63b27ccfd2c183b0fe + d37b0ea87c514c608ac761efce1e2b1a3a549963404f4c01b0b08e0d89cbb869 + 2b6eb3aaf14b4cf9b9ede16df4df95c48d6137def558411bba36350dee0e3db7 + 3989d6a8cfc2479eae8ee3440f57eb8d90be2c3e04e44a89883551c24c96c789 + 7e6aa73f3d0f4a9d82cc1ef0a4b1cd105f4de9ff19b7461e983fd45a7b9844ad + ffcd55830cf74d3489eb20a031a3302de04ccee43e354d5cacffbe827cfff160 + cdb52a946dfb46408ff0a421fd86ec92d9a46b7b9b2d428ca495863b36270569 + 4252393e87dc47afbe4c93afcd16ad88dbdea380be7849cd84529182ad4bf1ec + b313744a84fe43259984ddc4057ea6f70f924606281a4ffa8afb528fe3dc1f3e + 61de89262d0d48628fe1d5ec9222a24a01922bdd80434448aded8b4f12057eb7 +
+
+ 80de2ce1fb3742759aecc1a773d07450212fa26e5d9d4f63b27ccfd2c183b0fe + d37b0ea87c514c608ac761efce1e2b1a3a549963404f4c01b0b08e0d89cbb869 + 2b6eb3aaf14b4cf9b9ede16df4df95c48d6137def558411bba36350dee0e3db7 + 3989d6a8cfc2479eae8ee3440f57eb8d90be2c3e04e44a89883551c24c96c789 + 7e6aa73f3d0f4a9d82cc1ef0a4b1cd105f4de9ff19b7461e983fd45a7b9844ad + ffcd55830cf74d3489eb20a031a3302de04ccee43e354d5cacffbe827cfff160 + cdb52a946dfb46408ff0a421fd86ec92d9a46b7b9b2d428ca495863b36270569 + 4252393e87dc47afbe4c93afcd16ad88dbdea380be7849cd84529182ad4bf1ec + b313744a84fe43259984ddc4057ea6f70f924606281a4ffa8afb528fe3dc1f3e + 61de89262d0d48628fe1d5ec9222a24a01922bdd80434448aded8b4f12057eb7 +
+
+
+ +
+
+ + + + + + diff --git a/web/retro/css/address_book.css b/web/retro/css/address_book.css new file mode 100644 index 0000000..4ee9a27 --- /dev/null +++ b/web/retro/css/address_book.css @@ -0,0 +1,503 @@ +@charset "UTF-8"; +:root { + /*! UPDATE COLORS HERE !!! -------------------------------------------------------------------------------------- */ + --color: #37bfde; + --color-dark: #4a7297; + --color-danger: #c70036; + --color-good: #07ff0b; + --color-alt: white; + --background-color: #020f25; + --glyph-color: #fffea5; + /*! Calculate glyph-color-svg here: https://codepen.io/sosuke/pen/Pjoqqp */ + --glyph-color-svg: invert(100%) sepia(21%) saturate(5367%) hue-rotate(312deg) + brightness(111%) contrast(103%); + --glyph-color-danger-svg: invert(16%) sepia(84%) saturate(3541%) + hue-rotate(331deg) brightness(81%) contrast(117%); + --color-wormhole-danger-1: yellow; + --color-wormhole-danger-2: orange; + --color-wormhole-danger-3: red; + --color-wormhole-1: royalblue; + --color-wormhole-2: cyan; + --color-wormhole-3: cornflowerblue; + --border: solid clamp(0px, 0.5vmin, 5px) var(--color); + --border-thin: solid clamp(0px, 0.3vmin, 3px) var(--color); +} + +* { + box-sizing: border-box; +} + +body { + display: flex; + flex-direction: column; +} + +.genos-font { + font-family: "Genos", sans-serif; + font-optical-sizing: auto; + font-weight: 400; + font-style: normal; + font-size: clamp(-100px, 3.5vmin, 35px); +} + +.hidden { + display: none !important; +} + +a:link { + text-decoration: inherit; + color: inherit; + cursor: auto; +} + +a:visited { + text-decoration: inherit; + color: inherit; + cursor: auto; +} + +.navigation-menu-wrapper { + height: 0; + position: relative; + margin: 0 auto; +} + +.navigation-menu { + margin: auto; + width: clamp(-100px, 100vmin, 1000px); + display: flex; + align-items: center; + gap: clamp(-100px, 1vmin, 10px); + margin-bottom: 0; + margin-top: clamp(-100px, 0.5vmin, 5px); + padding-left: clamp(-100px, 4vmin, 40px); + opacity: 0.1; + transition: opacity 0.3s linear; + position: absolute; + left: 0; + font-size: clamp(-100px, 2vmin, 20px); +} +.navigation-menu:hover { + opacity: 1; +} +.navigation-menu a { + color: var(--color); + border: var(--border-thin); + border-radius: clamp(-100px, 1vmin, 10px); + padding: 0 clamp(-100px, 0.6vmin, 6px); + cursor: pointer; +} +.navigation-menu a:hover { + background-color: var(--color-dark); +} +.navigation-menu a.active-link { + color: var(--glyph-color); +} + +.dropbtn { + cursor: pointer; +} + +/* Dropdown button on hover & focus */ +.dropbtn:hover, +.dropbtn:focus { + background-color: var(--color-dark); +} + +/* Dropdown Content (Hidden by Default) */ +.dropdown-content { + display: none; + position: absolute; + background-color: var(--background-color); + z-index: 9999; +} + +/* Links inside the dropdown */ +.dropdown-content a { + color: var(--color-alt); + padding: clamp(-100px, 1vmin, 10px); + text-decoration: none; + display: block; +} + +/* Change color of dropdown links on hover */ +.dropdown-content a:hover { + background-color: var(--color-dark); +} + +/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ +.show { + display: block; +} + +body { + background-color: var(--background-color); + color: var(--color); + margin: 0; + height: 100vh; + display: flex; +} + +.navigation-menu-wrapper { + width: clamp(-100px, 98vmin, 980px); +} + +.border { + border: var(--border); + border-radius: clamp(-100px, 6vmin, 60px); + width: clamp(-100px, 98vmin, 980px); + height: clamp(-100px, 93vmin, 930px); + margin: auto; + overflow: hidden; + position: relative; +} + +.header { + display: flex; + gap: clamp(-100px, 1vmin, 10px); + margin-left: clamp(-100px, 4.2vmin, 42px); + margin-right: clamp(-100px, 8.5vmin, 85px); + margin-top: clamp(-100px, 0.8vmin, 8px); + position: relative; +} +.header .header-2 { + color: var(--color-alt); + font-size: clamp(-100px, 3.2vmin, 32px); + line-height: clamp(-100px, 4.1vmin, 41px); + align-content: end; +} +.header .header-3 { + color: var(--color-alt); + font-size: clamp(-100px, 2.9vmin, 29px); + line-height: clamp(-100px, 3.9vmin, 39px); + align-content: end; +} +.header .header-border { + border-top: var(--border); + position: absolute; + width: 100%; + bottom: clamp(-100px, 0.6vmin, 6px); +} + +.address-book-glyph { + position: relative; + float: left; + max-width: clamp(-100px, 6vmin, 60px); + filter: var(--glyph-color-svg); +} + +.address-counts { + position: absolute; + font-size: clamp(-100px, 2vmin, 20px); + line-height: clamp(-100px, 1.6vmin, 16px); + right: clamp(-100px, 1.3vmin, 13px); + display: flex; + flex-direction: column; + justify-content: flex-end; + text-align: end; + width: clamp(-100px, 12vmin, 120px); +} +.address-counts > div { + display: flex; + justify-content: space-between; +} + +section { + margin: 0 clamp(-100px, 1vmin, 10px); + position: relative; +} +section header { + display: flex; /* aligns all child elements (flex items) in a row */ + margin-bottom: clamp(-100px, 1.5vmin, 15px); + line-height: clamp(-100px, 3.5vmin, 35px); +} +section header .col { + width: clamp(-100px, 7.52vmin, 75.2px); + text-align: center; + border-bottom: var(--border); +} +section header .col.col-1 { + width: clamp(-100px, 3.2vmin, 32px); + border-bottom: unset; +} +section header .col.col-2 { + border-image: linear-gradient(to left, var(--color) 50%, transparent 50%) 100% 1; +} +section header .col.col-9 { + flex: 1; + text-align: start; +} +section .rows { + max-height: clamp(-100px, 66.5vmin, 665px); + min-height: clamp(-100px, 66.5vmin, 665px); + overflow-y: scroll; + scrollbar-color: var(--color); + scrollbar-width: auto; + position: relative; +} +section .row { + display: flex; /* aligns all child elements (flex items) in a row */ + position: relative; + margin-bottom: clamp(-100px, 1vmin, 10px); + margin-right: clamp(-100px, 1.5vmin, 15px); + line-height: clamp(-100px, 3.5vmin, 35px); + max-height: clamp(-100px, 9.6vmin, 96px); + overflow: hidden; + cursor: pointer; +} +section .row.danger .glyph, +section .row.danger .glyph > span, +section .row.danger .info { + border-color: var(--color-danger) !important; +} +section .row.danger .small-box { + background-color: var(--color-danger) !important; +} +section .row.danger .address-book-glyph { + filter: var(--glyph-color-danger-svg) !important; +} +section .row.fan .info-name { + color: var(--color-alt) !important; +} +section .row.offline .status .glyph-color { + color: var(--color-danger) !important; +} +section .row .col { + width: clamp(-100px, 7.4vmin, 74px); + text-align: center; + border-bottom: var(--border); +} +section .row .col.box { + flex: 0; + align-content: end; + padding-right: clamp(-100px, 0.2vmin, 2px); + border: unset; +} +section .row .col.box div { + width: clamp(-100px, 3vmin, 30px); + line-height: clamp(-100px, 2vmin, 20px); + text-align: center; + background-color: var(--color); + color: var(--background-color); + padding-bottom: clamp(-100px, 1.5vmin, 15px); +} +section .row .col.glyph { + border: var(--border); + border-right: unset; + flex: 0; + min-width: clamp(-100px, 7vmin, 70px); + max-width: clamp(-100px, 7vmin, 70px); + font-size: clamp(-100px, 1.8vmin, 18px); + white-space: nowrap; + color: var(--glyph-color); + display: flex; + flex-direction: column; +} +section .row .col.glyph > img { + margin: auto; + text-shadow: unset; + height: clamp(-100px, 6vmin, 60px); +} +section .row .col.glyph > span { + text-align: center; + border-top: var(--border); + text-overflow: ellipsis; + overflow: hidden; + line-height: clamp(-100px, 2.3vmin, 23px); +} +section .row .col.info { + flex: 1; + text-align: start; + border-bottom: unset; + border-top: var(--border); + border-left: var(--border); + font-size: clamp(-100px, 2.75vmin, 27.5px); + padding-left: clamp(-100px, 0.5vmin, 5px); + line-height: clamp(-100px, 2.3vmin, 23px); +} +section .row .col.info .info-title { + display: flex; + gap: clamp(-100px, 1vmin, 10px); +} +section .row .col.info .info-title .info-name { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} +section .row .col.info .info-body { + display: flex; + gap: clamp(-100px, 2vmin, 20px); +} +section .row .col.info .info-body .info-a { + flex: 1; + font-size: clamp(-100px, 2vmin, 20px); + line-height: clamp(-100px, 1.7vmin, 17px); + margin-left: clamp(-100px, 1vmin, 10px); +} +section .row .col.info .info-body .info-b { + flex: 1; + font-size: clamp(-100px, 2vmin, 20px); + line-height: clamp(-100px, 1.7vmin, 17px); +} +section .row .col.info .info-body .info-b > div { + display: flex; + gap: clamp(-100px, 0.69vmin, 6.9px); +} +section .row .col.info .info-body .info-b .glyph-color { + color: var(--glyph-color); +} +section .row .col.info .info-body .info-b .alt-color { + color: var(--color-alt); +} +section .row::after { + content: "▼"; + width: calc(100% - clamp(-100px, 1vmin, 10px)); + height: calc(100% - clamp(-100px, 0.7vmin, 7px)); + border: var(--border); + border-color: var(--color-good); + color: var(--color-good); + position: absolute; + font-size: clamp(-100px, 2.25vmin, 22.5px); + line-height: clamp(-100px, 2.25vmin, 22.5px); + padding-left: clamp(-100px, 0.2vmin, 2px); + pointer-events: none; + opacity: 0; +} +section .row:hover::after { + opacity: 1; +} + +.table-footer { + border: var(--border); + border-left: unset; + border-right: unset; + color: var(--color-alt); + font-size: clamp(-100px, 2.5vmin, 25px); + padding-left: clamp(-100px, 0.5vmin, 5px); + line-height: clamp(-100px, 2.5vmin, 25px); +} + +.footer { + display: flex; + border-bottom: var(--border); +} +.footer .footer-left { + flex: 1 0 auto; + max-width: clamp(-100px, 72vmin, 720px); + min-width: clamp(-100px, 72vmin, 720px); +} +.footer .footer-left > .footer-text { + border: var(--border); + border-left: unset; + border-bottom: unset; + margin-right: clamp(-100px, 0.5vmin, 5px); + font-size: clamp(-100px, 2vmin, 20px); + line-height: clamp(-100px, 1.6vmin, 16px); + padding-left: clamp(-100px, 0.5vmin, 5px); + height: clamp(-100px, 4vmin, 40px); + overflow: hidden; +} +.footer .footer-left > .footer-text div { + line-height: clamp(-100px, 1.6vmin, 16px); + animation: footer-text-anim 15s steps(1) forwards; +} +.footer .footer-right { + flex: 1 1 auto; + font-size: clamp(-100px, 1.6vmin, 16px); + color: var(--glyph-color); + max-height: clamp(-100px, 8vmin, 80px); + overflow: hidden; +} + +@keyframes footer-text-anim { + 0% { + transform: translateY(0%); + } + 10% { + transform: translateY(-10%); + } + 20% { + transform: translateY(-20%); + } + 30% { + transform: translateY(-30%); + } + 40% { + transform: translateY(-40%); + } + 50% { + transform: translateY(-50%); + } + 60% { + transform: translateY(-60%); + } + 70% { + transform: translateY(-70%); + } + 80% { + transform: translateY(-80%); + } + 100% { + transform: translateY(-80%); + } /* Hold final position */ +} +.footer-buttons { + display: flex; + font-size: clamp(-100px, 2.5vmin, 25px); + text-align: center; + margin: clamp(-100px, 0.5vmin, 5px); + gap: clamp(-100px, 0.5vmin, 5px); +} +.footer-buttons a { + flex: 1; + border: var(--border); + border-radius: clamp(-100px, 0.5vmin, 5px); + line-height: clamp(-100px, 2.5vmin, 25px); + cursor: pointer; + color: var(--color); + text-decoration: unset !important; +} +.footer-buttons a:hover { + color: var(--color-alt) !important; +} +.footer-buttons a.active-button { + color: var(--glyph-color) !important; +} + +.scrolling-section-wrapper { + width: clamp(-100px, 87vmin, 870px); + border: var(--border-thin); + margin: clamp(-100px, 0.5vmin, 5px) clamp(-100px, 5vmin, 50px); + overflow: hidden; +} + +.scrolling-section { + display: flex; + flex-wrap: nowrap; + width: max-content; + font-size: clamp(-100px, 2vmin, 20px); + animation: move 40s infinite linear; + line-height: clamp(-100px, 1.5vmin, 15px); +} + +@keyframes move { + to { + transform: translateX(-50%); + } +} +.scrolling-sectionY { + display: flex; + flex-wrap: wrap; + width: 100%; + line-height: clamp(-100px, 1.4vmin, 14px); + font-size: clamp(-100px, 2vmin, 20px); + animation: moveY 1.5s infinite linear; +} + +@keyframes moveY { + to { + transform: translateY(-50%); + } +} + +/*# sourceMappingURL=address_book.css.map */ diff --git a/web/retro/css/crt.css b/web/retro/css/crt.css new file mode 100644 index 0000000..fa8f931 --- /dev/null +++ b/web/retro/css/crt.css @@ -0,0 +1,232 @@ +:root { + --screen-door-small: 100% 2px, 3px 100%; + --screen-door-medium: 100% 4px, 6px 100%; + --screen-door-large: 100% 6px, 9px 100%; +} + +/* CRT CSS CODE: https://aleclownes.com/2017/02/01/crt-display.html */ +@keyframes flicker { + 0% { + opacity: 0.27861; + } + 5% { + opacity: 0.34769; + } + 10% { + opacity: 0.23604; + } + 15% { + opacity: 0.90626; + } + 20% { + opacity: 0.18128; + } + 25% { + opacity: 0.83891; + } + 30% { + opacity: 0.65583; + } + 35% { + opacity: 0.67807; + } + 40% { + opacity: 0.26559; + } + 45% { + opacity: 0.84693; + } + 50% { + opacity: 0.96019; + } + 55% { + opacity: 0.08594; + } + 60% { + opacity: 0.20313; + } + 65% { + opacity: 0.71988; + } + 70% { + opacity: 0.53455; + } + 75% { + opacity: 0.37288; + } + 80% { + opacity: 0.71428; + } + 85% { + opacity: 0.70419; + } + 90% { + opacity: 0.7003; + } + 95% { + opacity: 0.36108; + } + 100% { + opacity: 0.24387; + } +} +@keyframes textShadow { + 0% { + text-shadow: 0.4389924193300864px 0 1px rgba(0, 30, 255, 0.5), + -0.4389924193300864px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 5% { + text-shadow: 2.7928974010788217px 0 1px rgba(0, 30, 255, 0.5), + -2.7928974010788217px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 10% { + text-shadow: 0.02956275843481219px 0 1px rgba(0, 30, 255, 0.5), + -0.02956275843481219px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 15% { + text-shadow: 0.40218538552878136px 0 1px rgba(0, 30, 255, 0.5), + -0.40218538552878136px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 20% { + text-shadow: 3.4794037899852017px 0 1px rgba(0, 30, 255, 0.5), + -3.4794037899852017px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 25% { + text-shadow: 1.6125630401149584px 0 1px rgba(0, 30, 255, 0.5), + -1.6125630401149584px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 30% { + text-shadow: 0.7015590085143956px 0 1px rgba(0, 30, 255, 0.5), + -0.7015590085143956px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 35% { + text-shadow: 3.896914047650351px 0 1px rgba(0, 30, 255, 0.5), + -3.896914047650351px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 40% { + text-shadow: 3.870905614848819px 0 1px rgba(0, 30, 255, 0.5), + -3.870905614848819px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 45% { + text-shadow: 2.231056963361899px 0 1px rgba(0, 30, 255, 0.5), + -2.231056963361899px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 50% { + text-shadow: 0.08084290417898504px 0 1px rgba(0, 30, 255, 0.5), + -0.08084290417898504px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 55% { + text-shadow: 2.3758461067427543px 0 1px rgba(0, 30, 255, 0.5), + -2.3758461067427543px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 60% { + text-shadow: 2.202193051050636px 0 1px rgba(0, 30, 255, 0.5), + -2.202193051050636px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 65% { + text-shadow: 2.8638780614874975px 0 1px rgba(0, 30, 255, 0.5), + -2.8638780614874975px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 70% { + text-shadow: 0.48874025155497314px 0 1px rgba(0, 30, 255, 0.5), + -0.48874025155497314px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 75% { + text-shadow: 1.8948491305757957px 0 1px rgba(0, 30, 255, 0.5), + -1.8948491305757957px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 80% { + text-shadow: 0.0833037308038857px 0 1px rgba(0, 30, 255, 0.5), + -0.0833037308038857px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 85% { + text-shadow: 0.09769827255241735px 0 1px rgba(0, 30, 255, 0.5), + -0.09769827255241735px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 90% { + text-shadow: 3.443339761481782px 0 1px rgba(0, 30, 255, 0.5), + -3.443339761481782px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 95% { + text-shadow: 2.1841838852799786px 0 1px rgba(0, 30, 255, 0.5), + -2.1841838852799786px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } + 100% { + text-shadow: 2.6208764473832513px 0 1px rgba(0, 30, 255, 0.5), + -2.6208764473832513px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px; + } +} +.crt::after { + content: " "; + display: block; + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: rgba(18, 16, 16, 0.1); + opacity: 0; + z-index: 2; + pointer-events: none; +} +.crt::before { + content: " "; + display: block; + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: linear-gradient( + rgba(18, 16, 16, 0) 50%, + rgba(0, 0, 0, 0.25) 50% + ), + linear-gradient( + 90deg, + rgba(255, 0, 0, 0.06), + rgba(0, 255, 0, 0.02), + rgba(0, 0, 255, 0.06) + ); + z-index: 2; + background-size: var(--screen-door-medium); + pointer-events: none; +} +.crt { + /* ENABLE THIS IF YOU WANT TO MAKE YOUR COMPUTER HURT */ + /* Firefox handles it better than Chrome */ + /* Looks super dope tho. */ + /* animation: textShadow 3.5s infinite; */ + + + filter: contrast(1.5) brightness(1.1) saturate(1.1); +} + +.crt.flicker::after { + animation: flicker 0.15s infinite; +} + +@keyframes crt-scanline { + 0% { + top: -5%; + } + 100% { + top: 125%; + } +} + +.crt-distortion { + position: absolute; + top: -5%; + left: 0; + width: 100%; + height: 2vmin; /* Small strip for tearing effect */ + background: rgba(255, 255, 255, 0.1); /* Very faint */ + backdrop-filter: blur(1px); + filter: blur(1vmin); + pointer-events: none; + z-index: 100; +} + +.scanline-animation { + animation: crt-scanline 8s linear 1; +} \ No newline at end of file diff --git a/web/retro/css/dial.css b/web/retro/css/dial.css new file mode 100644 index 0000000..fb72787 --- /dev/null +++ b/web/retro/css/dial.css @@ -0,0 +1,667 @@ +:root { + /*! UPDATE COLORS HERE !!! -------------------------------------------------------------------------------------- */ + --color: #37bfde; + --color-dark: #4a7297; + --color-danger: #c70036; + --color-good: #07ff0b; + --color-alt: white; + --background-color: #020f25; + --glyph-color: #fffea5; + /*! Calculate glyph-color-svg here: https://codepen.io/sosuke/pen/Pjoqqp */ + --glyph-color-svg: invert(100%) sepia(21%) saturate(5367%) hue-rotate(312deg) + brightness(111%) contrast(103%); + --glyph-color-danger-svg: invert(16%) sepia(84%) saturate(3541%) + hue-rotate(331deg) brightness(81%) contrast(117%); + --color-wormhole-danger-1: yellow; + --color-wormhole-danger-2: orange; + --color-wormhole-danger-3: red; + --color-wormhole-1: royalblue; + --color-wormhole-2: cyan; + --color-wormhole-3: cornflowerblue; + --border: solid clamp(0px, 0.5vmin, 5px) var(--color); + --border-thin: solid clamp(0px, 0.3vmin, 3px) var(--color); +} + +* { + box-sizing: border-box; +} + +body { + display: flex; + flex-direction: column; +} + +.genos-font { + font-family: "Genos", sans-serif; + font-optical-sizing: auto; + font-weight: 400; + font-style: normal; + font-size: clamp(-100px, 3.5vmin, 35px); +} + +.hidden { + display: none !important; +} + +a:link { + text-decoration: inherit; + color: inherit; + cursor: auto; +} + +a:visited { + text-decoration: inherit; + color: inherit; + cursor: auto; +} + +.navigation-menu-wrapper { + height: 0; + position: relative; + margin: 0 auto; +} + +.navigation-menu { + margin: auto; + width: clamp(-100px, 100vmin, 1000px); + display: flex; + align-items: center; + gap: clamp(-100px, 1vmin, 10px); + margin-bottom: 0; + margin-top: clamp(-100px, 0.5vmin, 5px); + padding-left: clamp(-100px, 4vmin, 40px); + opacity: 0.1; + transition: opacity 0.3s linear; + position: absolute; + left: 0; + font-size: clamp(-100px, 2vmin, 20px); +} +.navigation-menu:hover { + opacity: 1; +} +.navigation-menu a { + color: var(--color); + border: var(--border-thin); + border-radius: clamp(-100px, 1vmin, 10px); + padding: 0 clamp(-100px, 0.6vmin, 6px); + cursor: pointer; +} +.navigation-menu a:hover { + background-color: var(--color-dark); +} +.navigation-menu a.active-link { + color: var(--glyph-color); +} + +.dropbtn { + cursor: pointer; +} + +/* Dropdown button on hover & focus */ +.dropbtn:hover, +.dropbtn:focus { + background-color: var(--color-dark); +} + +/* Dropdown Content (Hidden by Default) */ +.dropdown-content { + display: none; + position: absolute; + background-color: var(--background-color); + z-index: 9999; +} + +/* Links inside the dropdown */ +.dropdown-content a { + color: var(--color-alt); + padding: clamp(-100px, 1vmin, 10px); + text-decoration: none; + display: block; +} + +/* Change color of dropdown links on hover */ +.dropdown-content a:hover { + background-color: var(--color-dark); +} + +/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ +.show { + display: block; +} + +.reference { + background-image: url("../../references/gate-ref.jpg"); + width: 100%; + height: 100%; + position: absolute; + background-size: cover; + opacity: 0.5; +} + +body { + background-color: var(--background-color); + color: var(--color); + margin: 0; + height: 100vh; + display: flex; +} + +.navigation-menu-wrapper { + width: clamp(-100px, 98vmin, 980px); +} + +.border { + border: var(--border); + border-radius: clamp(-100px, 3vmin, 30px); + width: clamp(-100px, 98vmin, 980px); + height: clamp(-100px, 72vmin, 720px); + margin: auto; + overflow: hidden; + position: relative; +} + +.crosshair { + display: flex; + width: clamp(-100px, 45.1vmin, 451px); + align-items: center; + justify-content: center; +} +.crosshair div { + text-align: center; + align-content: center; + position: absolute; + color: var(--glyph-color); +} + +.border.idle .crosshair .blink { + width: clamp(-100px, 16vmin, 160px); + height: clamp(-100px, 16vmin, 160px); + position: absolute; + background: radial-gradient(circle, var(--color-danger) 0%, transparent 70%); + animation: blink 3s infinite ease; +} + +@keyframes blink { + 0% { + opacity: 0; + } + 40% { + opacity: 0; + } + 50% { + opacity: 1; + } + 60% { + opacity: 0; + } + 100% { + opacity: 0; + } +} +.chevron-box { + border: var(--border-thin); + width: clamp(-100px, 8.6vmin, 86px); + height: clamp(-100px, 6vmin, 60px); + left: clamp(-100px, 81.4vmin, 814px); + position: absolute; + border-radius: clamp(-100px, 1.5vmin, 15px) 0 0; + overflow: hidden; + text-shadow: unset !important; +} +.chevron-box.b1 { + top: clamp(-100px, 11vmin, 110px); +} +.chevron-box.b2 { + top: clamp(-100px, 19vmin, 190px); +} +.chevron-box.b3 { + top: clamp(-100px, 27vmin, 270px); +} +.chevron-box.b4 { + top: clamp(-100px, 35vmin, 350px); +} +.chevron-box.b5 { + top: clamp(-100px, 43vmin, 430px); +} +.chevron-box.b6 { + top: clamp(-100px, 51vmin, 510px); +} +.chevron-box.b7 { + top: clamp(-100px, 59vmin, 590px); +} + +.chevron-box-labels { + position: absolute; + top: clamp(-100px, 14.2vmin, 142px); + right: clamp(-100px, 16.7vmin, 167px); + display: flex; + flex-direction: column; + color: var(--color-alt); +} +.chevron-box-labels > span { + margin-bottom: clamp(-100px, 3.8vmin, 38px); + line-height: clamp(-100px, 4.2vmin, 42px); + font-size: clamp(-100px, 2.6vmin, 26px); +} + +.lst-code-1, +.lst-code-2 { + position: absolute; + bottom: clamp(-100px, 15.8vmin, 158px); + color: var(--color-alt); + font-size: clamp(-100px, 1.8vmin, 18px); +} +.lst-code-1 span, +.lst-code-2 span { + font-size: clamp(-100px, 2.5vmin, 25px); +} + +.lst-code-1 { + left: clamp(-100px, 19.6vmin, 196px); +} + +.lst-code-2 { + left: clamp(-100px, 67.6vmin, 676px); +} + +.auth-code-label { + position: absolute; + bottom: clamp(-100px, 0.2vmin, 2px); + left: clamp(-100px, 17.7vmin, 177px); + color: var(--color-alt); + font-size: clamp(-100px, 2vmin, 20px); +} + +.auth-code { + position: absolute; + bottom: clamp(-100px, 0.4vmin, 4px); + left: clamp(-100px, 37vmin, 370px); + color: var(--color-alt); + font-size: clamp(-100px, 2.3vmin, 23px); + display: flex; +} +.auth-code div { + width: clamp(-100px, 2.3vmin, 23px); + text-align: center; + border-bottom: var(--border-thin); + border-right: var(--border-thin); + border-color: var(--color-dark); +} +.auth-code div:nth-child(1) { + padding-left: clamp(-100px, 3.3vmin, 33px); + width: clamp(-100px, 6vmin, 60px); +} +.auth-code div:nth-child(7) { + padding: 0 clamp(-100px, 1vmin, 10px); + width: clamp(-100px, 5vmin, 50px); +} +.auth-code div:nth-child(15) { + padding-right: clamp(-100px, 0.7vmin, 7px); + width: clamp(-100px, 3vmin, 30px); +} + +.system { + position: absolute; + bottom: clamp(-100px, 0.8vmin, 8px); + left: clamp(-100px, 78.8vmin, 788px); + color: var(--color-alt); + font-size: clamp(-100px, 1.1vmin, 11px); + display: flex; + flex-direction: column; +} + +.info-box { + color: var(--color-danger); + font-weight: bold; + position: absolute; + bottom: clamp(-100px, 4.2vmin, 42px); + left: clamp(-100px, 20.9vmin, 209px); + border: var(--border); + width: clamp(-100px, 53.7vmin, 537px); + height: clamp(-100px, 7.9vmin, 79px); + text-align: center; + font-size: clamp(-100px, 9vmin, 90px); + line-height: clamp(-100px, 6vmin, 60px); + word-spacing: clamp(-100px, 14vmin, 140px); + letter-spacing: clamp(-100px, 1.5vmin, 15px); + padding-left: clamp(-100px, 1.3vmin, 13px); + animation: pulsingTextDanger 3.4s linear infinite; +} + +.sidebar { + border: var(--border); + border-left: unset; + border-radius: 0 clamp(-100px, 2vmin, 20px) clamp(-100px, 2vmin, 20px) 0; + position: absolute; + top: clamp(-100px, 10.8vmin, 108px); + left: clamp(-100px, 0vmin, 0px); + width: clamp(-100px, 17.9vmin, 179px); + height: clamp(-100px, 56.1vmin, 561px); +} +.sidebar .keyboard { + width: clamp(-100px, 16vmin, 160px); + height: clamp(-100px, 39vmin, 390px); + display: flex; + flex-wrap: wrap; + justify-content: start; + align-content: start; + margin: auto; +} +.sidebar .keyboard div { + width: clamp(-100px, 3.9vmin, 39px); + height: clamp(-100px, 3.9vmin, 39px); + cursor: pointer; + border: var(--border-thin); + border-color: rgba(0, 0, 0, 0); + border-radius: clamp(-100px, 1vmin, 10px); +} +.sidebar .keyboard div:hover { + border-color: var(--color-dark); +} +.sidebar .keyboard div.disabled { + opacity: 0.4; +} +.sidebar .keyboard div img { + width: clamp(-100px, 3.6vmin, 36px); + height: clamp(-100px, 3.6vmin, 36px); + filter: var(--glyph-color-svg); +} +.sidebar .status { + color: var(--color-alt); + font-size: clamp(-100px, 1.1vmin, 11px); + padding-left: clamp(-100px, 1.5vmin, 15px); +} + +.timer { + position: absolute; + bottom: clamp(-100px, 0.7vmin, 7px); + left: clamp(-100px, 1.4vmin, 14px); + font-size: clamp(-100px, 4vmin, 40px); + border: var(--border-thin); + width: clamp(-100px, 15vmin, 150px); + height: clamp(-100px, 3.2vmin, 32px); + text-align: center; + line-height: clamp(-100px, 2.3vmin, 23px); + overflow: hidden; + text-overflow: ellipsis; + animation: pulsingText 3s linear infinite; +} + +.gate-name { + position: absolute; + top: clamp(-100px, 1.7vmin, 17px); + left: clamp(-100px, 10.9vmin, 109px); + font-size: clamp(-100px, 3.5vmin, 35px); + border: var(--border-thin); + border-color: var(--color-dark); + width: clamp(-100px, 48vmin, 480px); + height: clamp(-100px, 4.5vmin, 45px); + line-height: clamp(-100px, 4vmin, 40px); + padding-left: clamp(-100px, 0.6vmin, 6px); + overflow: hidden; + text-overflow: ellipsis; +} + +.destination-box { + position: absolute; + top: clamp(-100px, 1.7vmin, 17px); + right: clamp(-100px, 1.1vmin, 11px); + font-size: clamp(-100px, 1.9vmin, 19px); + border: var(--border-thin); + border-color: var(--color-dark); + width: clamp(-100px, 36vmin, 360px); + height: clamp(-100px, 4.5vmin, 45px); + line-height: clamp(-100px, 6.2vmin, 62px); + text-align: center; + color: white; +} + +.destination { + position: absolute; + top: clamp(-100px, 1.7vmin, 17px); + right: clamp(-100px, 1.2vmin, 12px); + font-size: clamp(-100px, 3.5vmin, 35px); + width: clamp(-100px, 36.3vmin, 363px); + height: clamp(-100px, 3.2vmin, 32px); + line-height: clamp(-100px, 3vmin, 30px); + text-align: center; + text-overflow: ellipsis; + overflow: hidden; +} + +.destination-glyphs { + position: absolute; + top: clamp(-100px, 1.7vmin, 17px); + right: clamp(-100px, 1.2vmin, 12px); + width: clamp(-100px, 36.3vmin, 363px); + height: clamp(-100px, 3.2vmin, 32px); + overflow: hidden; + display: flex; + justify-content: center; +} +.destination-glyphs img { + width: clamp(-100px, 2.5vmin, 25px); + filter: var(--glyph-color-svg); +} + +.chevron-states { + font-size: clamp(-100px, 2vmin, 20px); + line-height: clamp(-100px, 1.6vmin, 16px); + border-collapse: collapse; + table-layout: fixed; + width: clamp(-100px, 18vmin, 180px); +} +.chevron-states .chevron-open, +.chevron-states .chevron-locked { + width: clamp(-100px, 5.2vmin, 52px); +} +.chevron-states .chevron-open > div, +.chevron-states .chevron-locked > div { + border: clamp(-100px, 0.2vmin, 2px) solid var(--color-dark); + width: clamp(-100px, 3.5vmin, 35px); + height: clamp(-100px, 1vmin, 10px); + background-color: rgba(0, 0, 0, 0); + transition: background-color 0.5s ease; +} +.chevron-states .chevron-open > div { + background-color: var(--color-danger); +} +.chevron-states .chevron-number { + color: var(--color-alt); + width: clamp(-100px, 2vmin, 20px); +} +.chevron-states .chevron-state { + color: var(--color-good); + font-size: clamp(-100px, 1.3vmin, 13px); + visibility: hidden; +} +.chevron-states tr { + height: clamp(-100px, 2.1vmin, 21px); +} +.chevron-states td { + padding-left: clamp(-100px, 1.6vmin, 16px); +} +.chevron-states tr.locked .chevron-open > div { + background-color: rgba(0, 0, 0, 0); +} +.chevron-states tr.locked .chevron-locked > div { + background-color: var(--color-good); +} +.chevron-states tr.locked .chevron-state { + visibility: visible; +} + +.dial-append { + position: relative; + top: 0; + left: 0; +} + +div.shield { + position: absolute; + top: clamp(-100px, 1.5vmin, 15px); + left: clamp(-100px, 1.5vmin, 15px); + width: clamp(-100px, 8.8vmin, 88px); + height: clamp(-100px, 8.8vmin, 88px); + background-image: url("../images/shield.gif"); + background-size: contain; + background-blend-mode: overlay; + filter: brightness(2) contrast(0.5); + border: var(--border); + border-right: unset; + border-radius: clamp(-100px, 2vmin, 20px) 0 0 clamp(-100px, 1vmin, 10px); +} + +div.shield-buddy { + position: absolute; + top: clamp(-100px, 2.3vmin, 23px); + left: clamp(-100px, 9.5vmin, 95px); + width: clamp(-100px, 8vmin, 80px); + height: clamp(-100px, 8vmin, 80px); + border-bottom: var(--border); + text-shadow: unset !important; +} + +div.clip-1 { + border-color: var(--color-danger); + clip-path: inset(0 100% 0 0); /* Hidden initially (right side at 100%) */ + transition: clip-path 0.8s linear; +} + +div.clip-2 { + border-color: var(--color-danger); + clip-path: inset(0 0 0 100%); /* Hidden initially (right side at 100%) */ + transition: clip-path 0.8s linear; +} + +div.locked { + clip-path: inset(0 0 0 0); +} + +div:not(.active) .ring-1 circle { + fill: none !important; +} + +img.glyph { + text-shadow: unset; + filter: var(--glyph-color-svg); + top: clamp(-100px, 19vmin, 190px); + left: clamp(-100px, 33.1vmin, 331px); + height: clamp(-100px, 30vmin, 300px); + position: absolute; + transition-property: top, left, height; + transition-duration: 0.8s; + transition-timing-function: ease; + animation: revealAnimation 0.8s forwards ease; +} +img.glyph.locked { + left: clamp(-100px, 82.2vmin, 822px); + height: clamp(-100px, 6.6vmin, 66px); +} +img.glyph.locked.g1 { + top: clamp(-100px, 10.7vmin, 107px); +} +img.glyph.locked.g2 { + top: clamp(-100px, 18.7vmin, 187px); +} +img.glyph.locked.g3 { + top: clamp(-100px, 26.7vmin, 267px); +} +img.glyph.locked.g4 { + top: clamp(-100px, 34.7vmin, 347px); +} +img.glyph.locked.g5 { + top: clamp(-100px, 42.7vmin, 427px); +} +img.glyph.locked.g6 { + top: clamp(-100px, 50.7vmin, 507px); +} +img.glyph.locked.g7 { + top: clamp(-100px, 58.7vmin, 587px); +} +img.glyph.locked.g8 { + top: clamp(-100px, 80vmin, 800px); +} +img.glyph.locked.g9 { + top: clamp(-100px, 80vmin, 800px); +} +img.glyph.blur { + filter: blur(clamp(-100px, 1vmin, 10px)) var(--glyph-color-svg); +} + +div.chevron-link { + position: absolute; + left: clamp(-100px, 0vmin, 0px); + height: clamp(-100px, 73vmin, 730px); + pointer-events: none; + text-shadow: unset !important; + animation: none; +} + +img.gate, +div.gate { + position: absolute; + left: clamp(-100px, 25.6vmin, 256px); + top: clamp(-100px, 12.9vmin, 129px); + height: clamp(-100px, 44.8vmin, 448px); +} + +@keyframes revealAnimation { + from { + transform: scale(0.1); + } + to { + transform: scale(1); + } +} +@keyframes pulsingText { + 0% { + color: rgb(from var(--color) r g b/100%); + } + 50% { + color: rgb(from var(--color) r g b/100%); + } + 80% { + color: rgb(from var(--color) r g b/40%); + } + 95% { + color: rgb(from var(--color) r g b/60%); + } + 100% { + color: rgb(from var(--color) r g b/100%); + } +} +@keyframes pulsingTextDanger { + 0% { + color: rgb(from var(--color-danger) r g b/100%); + } + 50% { + color: rgb(from var(--color-danger) r g b/100%); + } + 80% { + color: rgb(from var(--color-danger) r g b/60%); + } + 95% { + color: rgb(from var(--color-danger) r g b/80%); + } + 100% { + color: rgb(from var(--color-danger) r g b/100%); + } +} +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} +.rotating { + animation: spin 8s ease-in infinite; +} + +.slow-rotate { + transition: transform 0.4s ease-out; +} + +/*# sourceMappingURL=dial.css.map */ diff --git a/web/retro/dial.html b/web/retro/dial.html new file mode 100644 index 0000000..3ba28d1 --- /dev/null +++ b/web/retro/dial.html @@ -0,0 +1,276 @@ + + + + Stargate Command + + + + + + + + + + +
+ + +
+
+ +
+ +
DESTINATION
+
+
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+ +
+
+
+
+
+
+
+ +
+ 1 + 2 + 3 + 4 + 5 + 6 + 7 +
+ +
LST CODE # 1
+
LST CODE # 2
+ +
AUTHORIZATION CODE:
+
+
7
+
7
+
8
+
9
+
2
+
7
+
-
+
5
+
7
+
8
+
9
+
2
+
3
+
8
+
7
+
+ +
+ USER: SGT. W HARRIMANSYS: NOMINAL +
+ +
+ + + +
0:00
+ + +
+ +
+
+ + + + + + diff --git a/web/retro/images/dhd.svg b/web/retro/images/dhd.svg new file mode 100644 index 0000000..d1b6653 --- /dev/null +++ b/web/retro/images/dhd.svg @@ -0,0 +1,8 @@ + + + + Layer 1 + + + + \ No newline at end of file diff --git a/web/retro/images/shield.gif b/web/retro/images/shield.gif new file mode 100644 index 0000000000000000000000000000000000000000..afb46596715c8ebc5c5abdb926b27f1e8b9d0788 GIT binary patch literal 94769 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 literal 0 HcmV?d00001 diff --git a/web/retro/js/address_book.js b/web/retro/js/address_book.js new file mode 100644 index 0000000..d0e9f86 --- /dev/null +++ b/web/retro/js/address_book.js @@ -0,0 +1,424 @@ +const scrollingDiv = document.getElementById('scrollingDiv'); +const tableRowTemplate = document.getElementById('tableRow'); +const tableBody = document.getElementById('tableBody'); +const standardCounts = document.querySelector('.standard-count'); +const fanCounts = document.querySelector('.fan-count'); + +addresses = []; +symbols = []; + +fetchData(); + +function updateIp(ip) { + const parts = ip.split('.').map(Number); + + return parts.join('·'); +} + +function hash(str) { + let hash = 0, + i, + chr; + if (str.length === 0) return hash; + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = (hash << 5) - hash + chr; + hash |= 0; // Convert to 32bit integer + } + return hash; +} + +const randomText = ['E
M', 'P
Q', 'G
X', 'T
V', 'I
X']; + +async function fetchData() { + try { + const response = await fetch('/stargate/get/address_book?type=all'); + const data = await response.json(); + standardCounts.textContent = data.summary.standard; + fanCounts.textContent = data.summary.fan; + addresses = Object.values(data['address_book']); + + const responseSymbols = await fetch('/stargate/get/symbols_all'); + symbols = await responseSymbols.json(); + + parseData(); + } catch (error) { + console.error('Error fetching data:', error); + } +} + +function parseData() { + addresses.forEach(address => { + const aTag = document.createElement('a'); + aTag.setAttribute('href', `/stargate/dial?address=${address.gate_address.join('-')}`); + address.htmlData = aTag; + + const newRow = tableRowTemplate.cloneNode(true); + aTag.appendChild(newRow); + newRow.removeAttribute('id'); + newRow.classList.remove('hidden'); + + let keyboardAddress = ''; + let hasUnknownGlyph = false; + + address['gate_address'].forEach((glyph, i) => { + const symbol = symbols.find(x => x['index'] === glyph); + + if (!symbol || symbol['keyboard_mapping'] === false) { + keyboardAddress += '?'; + hasUnknownGlyph = true; + } else { + keyboardAddress += symbol['keyboard_mapping']; + } + + if (i < 7) { + newRow.querySelector(`.glyph-name-${i + 1}`).textContent = + symbol?.['name'] ?? 'Unknown'; + + const imgElement = newRow.querySelector(`.glyph-${i + 1}`); + imgElement.src = ''; // Empty it temporarily + imgElement.src = '..' + symbol?.['imageSrc']; // Set it again to force a reload + } + }); + + const randomNumber = Math.floor(Math.random() * 5); + newRow.querySelector('.small-box').innerHTML = randomText[randomNumber]; + + newRow.querySelector( + `.info-name`, + ).textContent = `${address['name']} # ${keyboardAddress}8`; + + if ( + address['is_black_hole'] || + hasUnknownGlyph || + address['gate_address'].length > 6 + ) { + newRow.classList.add('danger'); + } + + if (address['type'] === 'fan') { + newRow.classList.add('fan'); + newRow + .querySelector('.info-type') + .querySelectorAll('span')[1].textContent = 'Fan'; + } else { + newRow + .querySelector('.info-type') + .querySelectorAll('span')[1].textContent = 'Standard'; + } + + if (address['is_gate_online'] === '0') { + newRow.classList.add('offline'); + newRow.querySelector('.status').querySelectorAll('span')[1].textContent = + 'Offline'; + } else { + newRow.querySelector('.status').querySelectorAll('span')[1].textContent = + 'Online'; + } + + if (address['ip_address']) { + newRow + .querySelector('.info-coord') + .querySelectorAll('span')[1].textContent = updateIp( + address['ip_address'], + ); + } else { + newRow + .querySelector('.info-coord') + .querySelectorAll('span')[0].textContent = ''; + newRow + .querySelector('.info-coord') + .querySelectorAll('span')[1].textContent = ''; + } + + newRow + .querySelector('.info-const') + .querySelectorAll('span')[1].textContent = Math.abs( + hash(JSON.stringify(address)), + ); + + newRow + .querySelector('.info-ref') + .querySelectorAll('span')[1].textContent = `${Math.floor( + Math.random() * 999, + ) + .toString() + .padStart(3, '0')}x${Math.floor(Math.random() * 9999)}`; + + newRow.querySelector('.info-a').innerHTML = generatePlanetData(); + + tableBody.appendChild(aTag); + }); + + sortData('name'); +} + +function sortData(sortProperty) { + addresses.sort((a, b) => a.name.localeCompare(b.name)); + + if (sortProperty === 'type') { + addresses.sort((a, b) => a.type.localeCompare(b.type)); + } else if (sortProperty === 'status') { + addresses.sort( + (a, b) => + a.type.localeCompare(b.type) || + (b.is_gate_online ?? '0').localeCompare(a.is_gate_online ?? '0'), + ); + } else if (sortProperty === 'glyph') { + addresses.sort((a, b) => + a.gate_address + .map(x => x.toString().padStart(3, '0')) + .join('') + .localeCompare( + b.gate_address.map(x => x.toString().padStart(3, '0')).join(''), + ), + ); + } + + addresses.forEach(address => { + tableBody.appendChild(address.htmlData); + }); + + tableBody.scrollTo(0, 0); +} + +const labelOptions = { + Mission: [ + 'Complete', + 'Pending', + 'Active', + 'Failed', + 'Aborted', + 'Ongoing', + 'Incomplete', + 'Success', + 'Recon', + 'Contact', + 'Delayed', + ], + Survey: [ + 'Complete', + 'Partial', + 'In progress', + 'Failed', + 'Limited scan', + 'Area mapped', + 'Outpost found', + 'No data', + 'Hazard zones', + 'Energy spike', + 'Inconclusive', + ], + Terrain: [ + 'Mixed', + 'Plateau', + 'Valley', + 'Forest', + 'Desert', + 'Jungle', + 'Glacier', + 'Marsh', + 'Tundra', + 'Oasis', + 'Ocean', + ], + Life: ['Detected', 'Unknown', 'Extinct'], + Team: [ + 'Deployed', + 'Returned', + 'Missing', + 'Awaiting evac', + 'En route', + 'No contact', + 'In orbit', + 'Standing by', + 'Request backup', + 'Safe', + ], + Tech: [ + 'Unknown', + 'Primitive', + 'Advanced', + 'Inactive', + 'Damaged', + 'Non-native', + 'Functional', + 'No signs', + ], + Scan: [ + 'Normal', + 'Stable', + 'Interference', + 'Disturbance', + 'Power reading', + 'Active signals', + 'Structural mass', + 'Unknown field', + 'Signal trace', + 'Bio signature', + ], + Air: [ + 'Breathable', + 'Thin', + 'Toxic', + 'Heavy gases', + 'Oxygen rich', + 'Unstable', + 'Safe level', + 'Mask required', + 'Contaminated', + 'No trace', + ], + 'O2 Level': [ + '19%', + '20%', + '21%', + '22%', + '23%', + '18%', + '17% (Low)', + '24%', + '16% (Risk)', + '25%', + ], + Temp: [ + '5°C', + '12°C', + '18°C', + '22°C', + '27°C', + '30°C', + '-5°C (Cold)', + '35°C (Hot)', + '0°C', + '15°C', + ], + Gravity: [ + '0.8G', + '0.9G', + '1.0G', + '1.1G', + '1.2G', + '0.95G', + '1.05G', + '0.7G (Low)', + '1.3G (High)', + '1.15G', + ], + Rad: [ + '0.1 mSv/h', + '0.2 mSv/h', + '0.05 mSv/h', + '0.3 mSv/h', + '0.4 mSv/h', + '0.0 mSv/h', + '0.6 mSv/h', + '0.9 mSv/h (Caution)', + '0.8 mSv/h', + '0.25 mSv/h', + ], + Atm: [ + '0.9 bar', + '1.0 bar', + '1.1 bar', + '1.2 bar', + '0.95 bar', + '1.05 bar', + '0.8 bar (Thin)', + '1.3 bar (Dense)', + '0.85 bar', + '1.15 bar', + ], + Seismic: [ + 'None', + 'Low', + 'Minor tremors', + 'Stable', + '0.3 Hz', + '0.5 Hz', + 'Microquakes', + '0.1 Hz', + 'Irregular', + '0.0 Hz', + ], + 'Mag Field': [ + '45 μT', + '50 μT', + '38 μT', + '60 μT', + '42 μT', + '55 μT', + '48 μT', + '35 μT', + '65 μT', + '40 μT', + ], + Wind: [ + '0 km/h', + '5 km/h', + '12 km/h', + '8 km/h', + '20 km/h', + '15 km/h', + '25 km/h (Gusty)', + '3 km/h', + '10 km/h', + '18 km/h', + ], +}; +const notes = [ + 'No anomalies', + 'Culture noted', + 'Further Review', + 'Awaiting orders', + 'Culture observed', + 'Gate unstable', + 'Threat detected', + 'Artifacts logged', + 'Scan incomplete', + 'Base camp set', + 'Unknown energy', + 'Transmission lost', + 'Possible ruins', + 'Minimal contact', + 'Team under review', + 'Quarantine zone', + 'Language unknown', + 'Debris analyzed', + 'Unreadable data', + 'Life signs low', + 'Survey incomplete', + 'Hostile encounter', + 'Pre-warp civ', + 'Tech interference', + 'Records missing', + 'Sensors limited', + 'Limited access', + 'Return scheduled', +]; + +// Generates 3 random attributes from the dict of labelOptions +// Small chance of adding a Notes section +// Even smaller chance of redacting the value +function generatePlanetData() { + let toReturn = []; + let options = Object.keys(labelOptions); + for (let i = 0; i < 3; i++) { + const index = Math.floor(Math.random() * options.length); + const entry = options.splice(index, 1); + const optionIndex = Math.floor(Math.random() * labelOptions[entry].length); + const redacted = Math.random() < 0.02; + if (redacted) { + toReturn.push(`${entry}: *****`); + } else { + toReturn.push(`${entry}: ${labelOptions[entry][optionIndex]}`); + } + } + if (Math.random() < 0.15) { + // Add Note + const noteIndex = Math.floor(Math.random() * notes.length); + toReturn.push(`Note: ${notes[noteIndex]}`); + } + + return toReturn.join('
'); +} diff --git a/web/retro/js/crt.js b/web/retro/js/crt.js new file mode 100644 index 0000000..bd806bf --- /dev/null +++ b/web/retro/js/crt.js @@ -0,0 +1,35 @@ +/* USER CUSTOMIZATIONS */ + +const CRT_SCREEN_FLICKER = false; + +/* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING!!!! */ + +const elem = document.body; + +function toggleFlicker() { + const shouldFlicker = Math.random() > 0.7; // 30% chance to flicker + if (shouldFlicker) { + elem.classList.add("flicker"); + setTimeout(() => { + elem.classList.remove("flicker"); + toggleFlicker(); + }, 1000); // flicker for 200ms + } else { + setTimeout(toggleFlicker, 300); // check every 300ms + } +} + +// Run it every random interval +if(CRT_SCREEN_FLICKER) { + setTimeout(toggleFlicker, 300); +} + +const distortion = document.querySelector('.crt-distortion'); +let $rand = 0; +distortion.addEventListener('animationend', function(){ + this.classList.remove("scanline-animation"); + $rand = (Math.floor(Math.random() * 6) + 4); + this.style.animationDuration = $rand + 's'; + void this.offsetWidth; // hack to reflow css animation + this.classList.add("scanline-animation"); +}); diff --git a/web/retro/js/dial.js b/web/retro/js/dial.js new file mode 100644 index 0000000..82535f1 --- /dev/null +++ b/web/retro/js/dial.js @@ -0,0 +1,616 @@ +/* USER CUSTOMIZATIONS */ + +// Spinning is so much cooler than not spinning +const RING_ANIMATION = true; + +const AUTHORIZATION_CODE_RANDOMIZE = true; +const AUTHORIZATION_CODE = '77892757892387'; + +const USER = 'SGT. W HARRIMAN'; + +// Used when gate is offline initially +const DEFAULT_GATE_NAME = 'STARGATE'; + +const TEXT_OFFLINE = 'OFFLINE'; +const TEXT_IDLE = 'IDLE'; +const TEXT_DIALING = 'DIALING'; +const TEXT_INCOMING = 'INCOMING'; +const TEXT_ENGAGED = 'ENGAGED'; + +/* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING!!!! */ + +const glyph = document.querySelector('.glyph'); +const appendTarget = document.querySelector('.dial-append'); +const timer = document.querySelector('.timer'); +const gateName = document.querySelector('.gate-name'); +const destination = document.querySelector('.destination'); +const destinationGlyphs = document.querySelector('.destination-glyphs'); +const ring1 = document.querySelector('.ring-1 circle'); +const ring3 = document.querySelector('.ring-3'); +const infoText = document.querySelector('.info-box'); +const border = document.querySelector('.border'); +const keyboard = document.querySelector('.keyboard'); +const systemEl = document.querySelector('.system'); +const authCode = document.querySelector('.auth-code'); +const statusEl = document.querySelector('.status'); + +let statusInterval; + +const STATE_ACTIVE = 'active'; +const STATE_IDLE = 'idle'; +const STATE_DIAL_OUT = 'dialing_out'; +const STATE_DIAL_IN = 'dialing_in'; + +let speedDialAddress = []; + +let encoding = false; +let state = STATE_IDLE; + +let gateStatus = {}; +let firstStatus = true; +let fetchingStatus = false; + +let buffer = []; +let bufferIndex = 0; + +// For animating glyph ring +let lastRingPos = -1; +let gateMoving = false; +let lastGateRotation = 0; + +let lockedGlyphs = {}; +let locked_chevrons = 0; + +let symbols = []; + + +// INITIALIZE -------------------------------------------------------------------------- +async function initialize_computer() { + initialize_text(); + + const responseSymbols = await fetch('/stargate/get/symbols_all'); + if (!responseSymbols.ok) { + handleOffline(); + return; + } + symbols = await responseSymbols.json(); + + buildKeyboard(); + updateStatusFrequency(5000); + speedDialStart(); +} +initialize_computer(); + +function updateStatusFrequency(ms) { + clearInterval(statusInterval); + statusInterval = setInterval(watch_dialing_status, ms); + watch_dialing_status(); +} + +// KEYBOARD DIALING ---------------------------------------------------------------------- +document.body.onkeydown = function (e) { + const charCode = typeof e.which == 'number' ? e.which : e.keyCode; + if (charCode > 0) { + const code = String.fromCharCode(charCode); + const symbol = symbols.find(x => x.keyboard_mapping === code); + if (symbol) { + dhd_press(`${symbol.index}`); + } else if (code === ' ' || code === '\r') { + dhd_press('0'); + } + } +}; + +// SPEED DIALING -------------------------------------------------------------------------- +async function speedDialStart() { + const parts = window.location.search.substring(1).split('&'); + const query = {}; + parts.forEach(part => { + const temp = part.split('='); + query[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]); + }); + + if (query.address) { + speedDialAddress = [...query.address.split('-').map(Number), 1, 0]; + window.history.pushState({}, document.title, window.location.pathname); + await clear_buffer(); + speedDial(); + } +} + +async function speedDial() { + if (speedDialAddress.length > 0) { + const a = speedDialAddress.splice(0, 1); + dhd_press(`${a}`); + setTimeout(speedDial, 1500); + } +} + +// STATUS UPDATES -------------------------------------------------------------------------- +async function watch_dialing_status() { + if (fetchingStatus) { + // Skip update until previous request finishes. + return; + } + + try { + fetchingStatus = true; + const responseStatus = await fetch('/stargate/get/dialing_status'); + if (!responseStatus.ok) { + handleOffline(); + fetchingStatus = false; + return; + } + gateStatus = await responseStatus.json(); + + const initialState = state; + updateText(gateName, gateStatus.gate_name); + + let [new_locked_chevrons, hardBreak] = handleActiveGate(); + + if (!hardBreak) { + new_locked_chevrons = handleDialingOut(new_locked_chevrons); + new_locked_chevrons = handleDialingIn(new_locked_chevrons); + + while (locked_chevrons < new_locked_chevrons) { + lock(locked_chevrons); + locked_chevrons += 1; + if (!encoding) { + dial(); + } + } + + if (!encoding) { + this.firstStatus = false; + } + + trySpinning(); + } + + updateState(); + updateTimer(gateStatus.wormhole_time_till_close); + updateText(destination, gateStatus.connected_planet); + + if (initialState !== state) { + if (state === STATE_IDLE) { + updateStatusFrequency(5000); + } else { + updateStatusFrequency(500); + } + } + } catch (err) { + console.error(err); + handleOffline(); + } + fetchingStatus = false; +} + +function handleActiveGate(new_locked_chevrons = 0) { + if ( + state === STATE_ACTIVE && + !gateStatus.wormhole_active && + gateStatus.address_buffer_incoming.length === 0 && + gateStatus.address_buffer_outgoing.length === 0 + ) { + resetGate(); + updateStatusFrequency(5000); + return [0, true]; + } else if (state !== STATE_ACTIVE && gateStatus.wormhole_active) { + // Active Incoming + if (gateStatus.address_buffer_incoming.length > 0) { + buffer = gateStatus.address_buffer_incoming; + new_locked_chevrons = gateStatus.locked_chevrons_incoming; + if (state === STATE_DIAL_OUT) { + resetGate(); + } + } + // Active Outgoing + if (gateStatus.address_buffer_outgoing.length > 0) { + buffer = gateStatus.address_buffer_outgoing; + new_locked_chevrons = gateStatus.locked_chevrons_outgoing; + const toRemove = document.querySelectorAll('.destination-glyphs img'); + toRemove.forEach(g => g.remove()); + if (state === STATE_DIAL_IN) { + resetGate(); + } + } + + state = STATE_ACTIVE; + dial(); + } + return [new_locked_chevrons, false]; +} + +function handleDialingOut(new_locked_chevrons) { + if ( + state === STATE_DIAL_OUT && + gateStatus.address_buffer_outgoing.length === 0 + ) { + resetGate(); + } else if ( + state !== STATE_DIAL_OUT && + state !== STATE_ACTIVE && + gateStatus.address_buffer_outgoing.length > 0 + ) { + resetGate(); + state = STATE_DIAL_OUT; + } + + // Dialing Out + if (state === STATE_DIAL_OUT) { + let bufferChange = + gateStatus.address_buffer_outgoing.length - buffer.length; + buffer = gateStatus.address_buffer_outgoing; + if (bufferChange > 0) { + updateDestination(bufferChange); + setKeysDisabled(buffer); + if (!encoding) { + dial(); + } + } + new_locked_chevrons = gateStatus.locked_chevrons_outgoing; + } + return new_locked_chevrons; +} + +function handleDialingIn(new_locked_chevrons) { + if ( + state === STATE_DIAL_IN && + gateStatus.address_buffer_incoming.length === 0 + ) { + resetGate(); + } else if ( + state !== STATE_DIAL_IN && + state !== STATE_ACTIVE && + gateStatus.address_buffer_incoming.length > 0 + ) { + resetGate(); + state = STATE_DIAL_IN; + } + + if (state === STATE_DIAL_IN) { + let bufferChange = + gateStatus.address_buffer_incoming.length - buffer.length; + buffer = gateStatus.address_buffer_incoming; + if (bufferChange > 0) { + if (!encoding) { + dial(); + } + } + new_locked_chevrons = gateStatus.locked_chevrons_incoming; + } + + return new_locked_chevrons; +} + +// That's a neat trick +function trySpinning() { + if (!RING_ANIMATION) { + return; + } + + if (lastRingPos === -1) { + lastRingPos = gateStatus.ring_position; + } else if (lastRingPos !== gateStatus.ring_position) { + lastRingPos = gateStatus.ring_position; + ring3.classList.add('rotating'); + ring3.classList.remove('slow-rotate'); + gateMoving = true; + } else if (gateMoving) { + gateMoving = false; + stopSpinning(ring3); + } +} + +function stopSpinning(el) { + // Step 1: Capture current computed transform (rotation) + const computedStyle = window.getComputedStyle(el); + const matrix = new DOMMatrixReadOnly(computedStyle.transform); + + // Calculate current rotation angle in degrees + let angle = Math.atan2(matrix.b, matrix.a) * (180 / Math.PI); + if (angle < 0) angle += 360; + angle = angle % 360; + + // Step 2: Remove animation + el.classList.remove('rotating'); + + // Step 3: Apply current rotation as a static transform + el.style.transform = `rotate(${angle}deg)`; + + // Force reflow to flush style changes + void el.offsetWidth; + + // Step 4: Add transition and apply a final slow rotation + el.classList.add('slow-rotate'); + + // Rotate 10° more over 1s (simulate deceleration) + el.style.transform = `rotate(${angle + 10}deg)`; + + // Optional cleanup after transition + el.addEventListener( + 'transitionend', + () => { + el.classList.remove('slow-rotate'); + lastGateRotation = (angle + 10 + lastGateRotation) % 360; + el.style.rotate = `${lastGateRotation}deg`; + el.style.transform = ''; + }, + {once: true}, + ); +} + +async function dhd_press(symbol, key) { + if (state === STATE_DIAL_OUT && buffer.find(x => `${x}` === symbol)) { + return; + } + + key?.classList.add('disabled'); + await fetch('/stargate/do/dhd_press', { + method: 'POST', + body: JSON.stringify({symbol}), + mode: 'no-cors', + }); + setTimeout(() => watch_dialing_status(), 300); +} + +async function clear_buffer() { + await fetch('/stargate/do/clear_outgoing_buffer', { + method: 'POST', + mode: 'no-cors', + }); + setTimeout(() => watch_dialing_status(), 300); +} + +function dial() { + if (buffer.length === 0) { + encoding = false; + bufferIndex = 0; + firstStatus = false; + return; + } + + if (bufferIndex >= locked_chevrons) { + if (buffer.length > bufferIndex) { + displayGlyph(); + } + encoding = false; + return; + } + + encoding = true; + + if (bufferIndex < 9) { + const [newGlyph, newGlyph2] = displayGlyph(); + if (firstStatus) { + newGlyph.classList.add('locked'); + newGlyph2.classList.add('locked'); + } else { + setTimeout(() => newGlyph.classList.add('locked'), 1); + setTimeout(() => newGlyph2.classList.add('locked'), 50); + } + } + bufferIndex += 1; + + if (gateStatus.wormhole_active || firstStatus) { + // Allow quick locking for active wormholes or partially dialed gates on page load + setTimeout(dial, 300); + } else { + // Add some delay between chevrons so previous animations can finish + setTimeout(dial, 1300); + } +} + +function displayGlyph() { + if (lockedGlyphs[bufferIndex] !== undefined) { + return lockedGlyphs[bufferIndex]; + } + const glyphIndex = buffer[bufferIndex]; + const symbol = symbols.find(x => x['index'] === glyphIndex); + + const newGlyph = glyph.cloneNode(true); + newGlyph.classList.remove('hidden'); + newGlyph.src = ''; + newGlyph.src = '..' + symbol['imageSrc']; + + newGlyph.classList.add(`g${bufferIndex + 1}`); + const newGlyph2 = newGlyph.cloneNode(true); + newGlyph2.classList.add('blur'); + appendTarget.append(newGlyph2); + appendTarget.append(newGlyph); + + lockedGlyphs[bufferIndex] = [newGlyph, newGlyph2]; + return [newGlyph, newGlyph2]; +} + +function lock(i) { + // Only allow locking 7 chevrons + if (i >= 9) { + return; + } + + startDrawingPath(i + 1); + + const chevrons = document.querySelectorAll( + `.chevron-${i + 1},.chevron-state-${i + 1}`, + ); + chevrons.forEach(c => c.classList.add('locked')); + + const b = document.querySelector(`.b${i + 1}`); + if (b) { + const newB = b.cloneNode(true); + newB.classList.add(`clip-${i < 3 ? '2' : '1'}`); + appendTarget.append(newB); + setTimeout(() => newB.classList.add('locked'), 10); + } +} + +// Clear all animations and get gate back into initial state +function resetGate() { + const chevrons = document.querySelectorAll( + '.gate.chevron.locked,.chevron-states tr.locked', + ); + chevrons.forEach(c => c.classList.remove('locked')); + + const toRemove = document.querySelectorAll( + '.dial-append > *,.destination-glyphs img', + ); + toRemove.forEach(g => g.remove()); + + const keys = document.querySelectorAll('.keyboard div'); + keys.forEach(k => k.classList.remove('disabled')); + + state = STATE_IDLE; + encoding = false; + buffer = []; + bufferIndex = 0; + lockedGlyphs = {}; + locked_chevrons = 0; +} + +function updateState() { + if (state === STATE_ACTIVE) { + setTimeout(() => { + updateText(infoText, 'ENGAGED'); + border.classList.add('active'); + border.classList.remove('idle'); + + if (gateStatus.black_hole_connected) { + ring1.setAttribute('fill', 'url(#radialGradientDanger)'); + } else { + ring1.setAttribute('fill', 'url(#radialGradient)'); + } + }, 500); + } else if (state === STATE_DIAL_OUT) { + updateText(infoText, 'DIALING'); + border.classList.remove('active'); + border.classList.remove('idle'); + } else if (state === STATE_DIAL_IN) { + updateText(infoText, 'INCOMING'); + border.classList.remove('active'); + border.classList.remove('idle'); + } else { + updateText(infoText, 'IDLE'); + border.classList.remove('active'); + border.classList.add('idle'); + } +} + +function updateDestination(lastXGlyphs) { + const toAdd = buffer.slice(buffer.length - lastXGlyphs); + toAdd.forEach(g => { + const symbol = symbols.find(x => x['index'] === g); + const glyph = document.createElement('img'); + glyph.src = '..' + symbol['imageSrc']; + destinationGlyphs.append(glyph); + }); +} + +function updateTimer(secondsLeft) { + if (gateStatus.black_hole_connected) { + secondsLeft = + 38 * 60 - + (gateStatus.wormhole_max_time - gateStatus.wormhole_time_till_close); + } + + const mins = Math.max(0, Math.floor(secondsLeft / 60)); + const secs = Math.max(0, secondsLeft % 60); + updateText(timer, `${mins}:${secs.toString().padStart(2, '0')}`); +} + +function initialize_text() { + updateText(gateName, DEFAULT_GATE_NAME); + updateText(systemEl.children.item(0), 'USER: ' + USER); + + const codeLength = Math.max(AUTHORIZATION_CODE.length, 15); + for (let i = 0; i < codeLength; i++) { + if (i !== 6) { + let code = AUTHORIZATION_CODE[i]; + + if (AUTHORIZATION_CODE_RANDOMIZE) { + code = Math.floor(Math.random() * 10); + } + + updateText(authCode.children.item(i), code); + } + } +} + +function handleOffline() { + updateText(infoText, TEXT_OFFLINE); + // setKeysDisabled([...symbols.map(x => x.index), 0, -1]); +} + +function buildKeyboard() { + symbols.forEach(symbol => { + if (symbol.keyboard_mapping) { + const keyWrapper = document.createElement('div'); + keyWrapper.classList.add(`symbol-${symbol.index}`); + const img = document.createElement('img'); + img.src = '..' + symbol.imageSrc; + img.onclick = () => dhd_press(`${symbol.index}`, img); + keyWrapper.appendChild(img); + keyboard.appendChild(keyWrapper); + } + }); + + const keyWrapper = document.createElement('div'); + keyWrapper.classList.add(`symbol-0`); + const img = document.createElement('img'); + img.src = `images/dhd.svg`; + img.onclick = () => dhd_press(`0`, img); + keyWrapper.appendChild(img); + keyboard.appendChild(keyWrapper); +} + +// Locking pre-dialed keys from the keyboard +function setKeysDisabled(keys, disabled = true) { + keys.forEach(k => setKeyDisabled(k, disabled)); +} +function setKeyDisabled(glyphIndex, disabled) { + const key = document.querySelector(`.keyboard .symbol-${glyphIndex}`); + if (key) { + if (disabled) { + key.classList.add('disabled'); + } else { + key.classList.remove('disabled'); + } + } +} + +// Animate the power line from the chevron to the glyph box +const pathTime = 800; // ms +function startDrawingPath(index) { + const svgBase = document.querySelector(`.cl${index}`); + if (svgBase) { + const svg = svgBase.cloneNode(true); + const path = svg.querySelector('path'); + const pathLength = path.getTotalLength(); + + svg.classList.add('locked'); + path.style.stroke = 'var(--color-danger)'; + path.style.strokeWidth = '6'; + appendTarget.append(svg); + + const start = performance.now(); + let length = 0; + function animate(now) { + const time = now - start; + length = Math.floor((time / pathTime) * pathLength); + path.style.strokeDasharray = [length, pathLength].join(' '); + + if (length < pathLength) { + requestAnimationFrame(animate); + } + } + animate(start); + } else { + // No chevron link path, probably 8th/9th chevron + } +} + +function updateText(elem, text) { + if (elem.textContent !== text) { + elem.textContent = text ?? ''; + } +} diff --git a/web/retro/js/navigation.js b/web/retro/js/navigation.js new file mode 100644 index 0000000..ce455bd --- /dev/null +++ b/web/retro/js/navigation.js @@ -0,0 +1,88 @@ +/* When the user clicks on the button, +toggle between hiding and showing the dropdown content */ +function openDropdown(elementId) { + document.getElementById(elementId).classList.toggle('show'); +} + +// Close the dropdown menu if the user clicks outside of it +window.onclick = function (event) { + if (!event.target.matches('.dropbtn')) { + const dropdowns = document.getElementsByClassName('dropdown-content'); + for (let i = 0; i < dropdowns.length; i++) { + const openDropdown = dropdowns[i]; + if (openDropdown.classList.contains('show')) { + openDropdown.classList.remove('show'); + } + } + } +}; + +async function restart() { + const response = confirm( + 'Are you sure you want to restart the Gate software?', + ); + if (response) { + await fetch('/stargate/do/restart', { + method: 'POST', + mode: 'no-cors', + }); + } +} + +async function reboot() { + const response = confirm( + 'Are you sure you want to restart the Raspberry Pi?', + ); + if (response) { + await fetch('/stargate/do/reboot', { + method: 'POST', + mode: 'no-cors', + }); + } +} + +async function shutdown() { + const response = confirm( + 'Are you sure you want to shutdown the Raspberry Pi?', + ); + if (response) { + await fetch('/stargate/do/shutdown', { + method: 'POST', + mode: 'no-cors', + }); + } +} + +function isActive(href) { + console.log(window.location.href); + return `href="${href}"` + (window.location.href.includes(href) ? 'class="active-link"' : ''); +} + +function initializeNavBar() { + const div = document.createElement('div'); + div.innerHTML = ` + + `; + const innerDiv = div.querySelector('div'); + const body = document.querySelector('body') + body.insertBefore(innerDiv, body.childNodes[0]) +} +initializeNavBar(); From 1a389ad09023ba357383c6a4b8a80601475f96ad Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 8 May 2025 11:06:47 -0700 Subject: [PATCH 4/5] Update htm and js files to point to new redirect endpoint --- web/address_book.htm | 2 +- web/config.htm | 4 ++-- web/debug.htm | 4 ++-- web/help.htm | 4 ++-- web/index.htm | 2 +- web/info.htm | 4 ++-- web/js/address_book.js | 2 +- web/js/config.js | 3 ++- web/symbol_overview.htm | 4 ++-- web/wiring.htm | 4 ++-- 10 files changed, 17 insertions(+), 16 deletions(-) diff --git a/web/address_book.htm b/web/address_book.htm index 9080893..3d67517 100644 --- a/web/address_book.htm +++ b/web/address_book.htm @@ -49,7 +49,7 @@