From 856a694f0b1cfbbf30378bd04547ddfc185edc3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 16 Jul 2017 20:37:31 +0200 Subject: [PATCH] almost complete wifi page redesign --- html_orig/.gitignore | 2 +- html_orig/_debug_replacements.php | 29 + html_orig/{_test_env.php.example => _env.php} | 0 html_orig/_env.php.example | 3 + html_orig/_pages.php | 25 + html_orig/_start.php | 144 ---- html_orig/css/app.css | 664 +++++++++++++----- html_orig/index.php | 64 ++ html_orig/js/app.js | 27 +- html_orig/jssrc/chibi.js | 5 +- html_orig/jssrc/utils.js | 12 + html_orig/jssrc/wifi.js | 2 +- html_orig/messages/en.php | 35 + html_orig/pages/_cfg_menu.php | 15 + html_orig/pages/_head.php | 26 + html_orig/pages/_tail.php | 5 + html_orig/pages/cfg_network.php | 0 html_orig/pages/cfg_wifi.php | 123 ++++ html_orig/pages/term.php | 37 + html_orig/sass/_layout.scss | 178 ----- html_orig/sass/app.scss | 19 +- html_orig/sass/form/_form_elements.scss | 41 ++ html_orig/sass/form/_form_layout.scss | 55 +- html_orig/sass/form/_index.scss | 2 +- html_orig/sass/layout/_base.scss | 31 + html_orig/sass/layout/_box.scss | 91 +++ html_orig/sass/layout/_content.scss | 45 ++ .../sass/layout/_espterm_specific_old.scss | 76 ++ html_orig/sass/layout/_index.scss | 9 + html_orig/sass/layout/_loader.scss | 18 + html_orig/sass/layout/_menu.scss | 98 +++ html_orig/sass/{ => layout}/_modal.scss | 6 +- html_orig/sass/layout/_outer-wrap.scss | 22 + html_orig/sass/pages/_term.scss | 20 +- html_orig/sass/pages/_wifi.scss | 125 +++- html_orig/sass/utils/_background-tiling.scss | 68 ++ html_orig/sass/utils/_index.scss | 3 + html_orig/sass/utils/_misc.scss | 34 + html_orig/sass/utils/_pointer.scss | 26 + html_orig/server.sh | 2 +- user/cgi_wifi.c | 154 ++-- 41 files changed, 1691 insertions(+), 650 deletions(-) create mode 100644 html_orig/_debug_replacements.php rename html_orig/{_test_env.php.example => _env.php} (100%) create mode 100644 html_orig/_env.php.example create mode 100644 html_orig/_pages.php delete mode 100644 html_orig/_start.php create mode 100644 html_orig/index.php create mode 100644 html_orig/messages/en.php create mode 100644 html_orig/pages/_cfg_menu.php create mode 100644 html_orig/pages/_head.php create mode 100644 html_orig/pages/_tail.php create mode 100644 html_orig/pages/cfg_network.php create mode 100644 html_orig/pages/cfg_wifi.php create mode 100644 html_orig/pages/term.php delete mode 100644 html_orig/sass/_layout.scss create mode 100755 html_orig/sass/layout/_base.scss create mode 100755 html_orig/sass/layout/_box.scss create mode 100755 html_orig/sass/layout/_content.scss create mode 100644 html_orig/sass/layout/_espterm_specific_old.scss create mode 100755 html_orig/sass/layout/_index.scss create mode 100644 html_orig/sass/layout/_loader.scss create mode 100755 html_orig/sass/layout/_menu.scss rename html_orig/sass/{ => layout}/_modal.scss (92%) create mode 100755 html_orig/sass/layout/_outer-wrap.scss create mode 100755 html_orig/sass/utils/_background-tiling.scss create mode 100755 html_orig/sass/utils/_index.scss create mode 100755 html_orig/sass/utils/_misc.scss create mode 100755 html_orig/sass/utils/_pointer.scss diff --git a/html_orig/.gitignore b/html_orig/.gitignore index dec88d1..0a0f73a 100644 --- a/html_orig/.gitignore +++ b/html_orig/.gitignore @@ -1 +1 @@ -_test_env.php +pages/_test_env.php diff --git a/html_orig/_debug_replacements.php b/html_orig/_debug_replacements.php new file mode 100644 index 0000000..8b59dca --- /dev/null +++ b/html_orig/_debug_replacements.php @@ -0,0 +1,29 @@ + 'ESP8266 Wireless Terminal', + + '%b1%' => '1', + '%b2%' => '2', + '%b3%' => '3', + '%b4%' => '4', + '%b5%' => '5', + '%screenData%' => '{ + "w": 26, "h": 10, + "x": 0, "y": 0, + "cv": 1, + "screen": "70 t259" + }', + + '%ap_enable%' => '1', + '%tpw%' => '60', + '%ap_channel%' => '7', + '%ap_ssid%' => 'ESP-123456', + '%ap_password%' => 'Passw0rd!', + '%ap_hidden%' => '0', + '%sta_ssid%' => 'LibraryFreeWifi', + '%sta_password%' => 'windows XP is The Best', + '%sta_active_ip%' => '', + + '%sta_enable%' => '0', +]; diff --git a/html_orig/_test_env.php.example b/html_orig/_env.php similarity index 100% rename from html_orig/_test_env.php.example rename to html_orig/_env.php diff --git a/html_orig/_env.php.example b/html_orig/_env.php.example new file mode 100644 index 0000000..4d38f09 --- /dev/null +++ b/html_orig/_env.php.example @@ -0,0 +1,3 @@ + $bc, + 'path' => $path, + 'label' => tr("menu.$key"), + ]; +} + +pg('cfg_wifi', 'cfg', '/cfg/wifi'); +pg('cfg_network', 'cfg', '/cfg/network'); +pg('cfg_term', 'cfg', '/cfg/term'); +pg('about', 'cfg', '/about'); +pg('help', 'cfg', '/help'); +pg('term', 'term', '/'); + +// technical +pg('wifi_set', '', '/cfg/wifi/set'); + +return $pages; diff --git a/html_orig/_start.php b/html_orig/_start.php deleted file mode 100644 index 31bab8a..0000000 --- a/html_orig/_start.php +++ /dev/null @@ -1,144 +0,0 @@ - [ $prod ? '/status' : '/page_status.php', 'Home' ], - 'wifi' => [ $prod ? '/wifi' : '/page_wifi.php', 'WiFi config' ], - 'about' => [ $prod ? '/about' : '/page_about.php', 'About' ], -]; - -$appname = 'Current Analyser'; - -function e($s) { - return htmlspecialchars($s, ENT_HTML5|ENT_QUOTES); -} - -?> - - - - - - - <?= e($menu[$page][1]) ?> - <?= e($appname) ?> - - - - - - -
- -
- Loading… - - - - - - - - - - WiFi Settings - ESP8266 Remote Terminal - - - - - - -Loading… - -

WiFi settings

- -
- - - - - - - - - - - - - - - - - - - - - - -
WiFi mode%WiFiMode%
IP%StaIP%
Switch to
-
- -
-
-
- -
-
-

Some changes require a reboot, dropping connection. It can take a while to re-connect.

-

- If you lose access, hold the BOOT button for 2 seconds (the Tx LED starts blinking) to re-enable AP mode. - If that fails, hold the BOOT button for over 5 seconds (rapid Tx LED flashing) to perform a factory reset. -

-

-
- -
-

Select AP to join

-
Scanning.
-
Can't scan in AP-only mode.
- -
- - - - - - - - diff --git a/html_orig/css/app.css b/html_orig/css/app.css index d058ead..9075115 100644 --- a/html_orig/css/app.css +++ b/html_orig/css/app.css @@ -1,3 +1,4 @@ +@charset "UTF-8"; /* normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ /** * 1. Set default font family to sans-serif. @@ -313,84 +314,6 @@ html { *, *::after, *::before { box-sizing: inherit; } -.hidden { - display: none !important; } - -[onclick] { - cursor: pointer; } - -.Modal { - position: fixed; - width: 100%; - height: 100%; - left: 0; - top: 0; - right: 0; - bottom: 0; - display: flex; - justify-content: center; - align-items: center; - transition: opacity .5s; - background: rgba(0, 0, 0, 0.65); - opacity: 0; } - .Modal.visible { - opacity: 1; } - .Modal.hidden { - display: none; } - -.Dialog { - margin: 0.61805rem; - padding: 1rem; - overflow: hidden; - max-width: 100%; - max-height: 100%; - flex: 0 1 30rem; - background: #1c1c1e; - border-left: 6px solid #2972ba; - border-right: 6px solid #2972ba; - box-shadow: 0 0 2px 0 #434349, 0 0 6px 0 black; - border-radius: 6px; } - .Dialog h1, .Dialog h2 { - margin-top: 0; } - .Dialog p:last-child { - margin-bottom: 0; } - -/* -// "toast" -.NotifyMsg { - position: fixed; - bottom: dist(2); - padding: dist(-1) dist(0); - - // center horizontally - left: 50%; - @include translate(-50%,0); - // hack to remove blur in chrome - -webkit-font-smoothing: subpixel-antialiased; - -webkit-transform: translateZ(0) scale(1.0, 1.0); - - background: #37a349; - &.error { - background: #d03e42; - } - - color: white; - text-shadow: 0 0 2px black; - box-shadow: 0 0 6px 0 rgba(black, .6); - border-radius: 5px; - - max-width: 80%; - - @include media($phone) { - width: calc(100% - 1rem); - } - - transition: opacity .5s; - opacity: 0; - &.visible { opacity: 1 } - &.hidden { display: none } -} -*/ html { font-family: Arial, sans-serif; color: #D0D0D0; @@ -414,74 +337,131 @@ a:hover { color: #5abfff; text-decoration: underline; } -.Box { - display: block; - max-width: 900px; - margin-top: 1rem; - padding: 0.61805rem 1rem; - border-radius: 3px; - background-color: rgba(255, 255, 255, 0.07); } - @media screen and (max-width: 544px) { - .Box { - margin-top: 0.61805rem; - padding: 0.23608rem 0.38198rem; } } - .Box p:first-child { - margin-top: 0; } +.hidden { + display: none !important; } -body { +[onclick] { + cursor: pointer; } + +/* Main outer container */ +#outer { + display: flex; + position: absolute; + width: 100%; + height: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; + overflow: hidden; + flex-direction: row; } + +@media screen and (max-width: 544px) { + #outer { + display: block; + overflow-y: scroll; } } +#menu { + flex: 0 0 15rem; + background: #3983CD; } + #menu > * { + display: block; + text-decoration: none; + padding: 0.61805rem 1rem; + white-space: nowrap; + word-wrap: normal; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + #menu #brand { + color: white; + background: #2b6aa8; + font-size: 120%; + text-align: center; + position: relative; + transition: none; + font-weight: bold; + margin-bottom: 1rem; } + @media screen and (max-width: 544px) { + #menu #brand { + background: #3983CD; + cursor: pointer; + margin-bottom: 0.38198rem; } + #menu #brand::after { + position: absolute; + color: rgba(0, 0, 0, 0.4); + right: 1rem; + content: '▸'; + top: 50%; + font-size: 120%; + font-weight: bold; + transform: translate(0, -50%) rotate(90deg); } } + #menu.expanded #brand { + background: #2b6aa8; } + @media screen and (max-width: 544px) { + #menu.expanded #brand:after { + transform: translate(-25%, -50%) rotate(-90deg); } } + #menu a { + font-size: 130%; + color: white; + transition: background-color 0.2s; + text-shadow: 0 0 5px rgba(0, 0, 0, 0.4); } + #menu a:hover, #menu a.selected { + background: #5badff; + text-shadow: 0 0 5px rgba(0, 0, 0, 0.6); } + #menu a.selected { + position: relative; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.5); } + #menu a::before { + content: "▸"; + padding-right: .5rem; + position: relative; + top: -0.1rem; } + @media screen and (max-width: 544px) { + #menu a { + display: none; } } + #menu.expanded a { + display: block; } + @media screen and (min-width: 545px) and (max-width: 1000px) { + #menu { + flex-basis: 10rem; } + #menu #brand { + font-size: 95%; + margin-bottom: 0.61805rem; } + #menu a { + font-size: 105%; } + #menu > * { + padding: 0.38198rem 0.61805rem; } } + +#content { + flex-grow: 1; position: relative; padding: 1rem; overflow-y: auto; } @media screen and (max-width: 544px) { - body { + #content { padding: 0.61805rem; } } - body > * { + #content > * { margin-left: auto; margin-right: auto; } - -h1, h2 { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; } - -h1 { - text-align: center; - font-size: 2.02729em; - margin-top: 0; - margin-bottom: 1rem; } + #content h1 { + text-align: center; + font-size: 2.2807em; + margin-top: 0; + margin-bottom: 1rem; } @media screen and (max-width: 544px) { - h1 { - font-size: 1.42383em; + #content h1 { + font-size: 1.80203em; margin-bottom: 0.61805rem; } } - @media screen and (min-width: 545px) and (max-width: 1000px) { - h1 { - font-size: 1.80203em; } } - -h2 { - font-size: 1.26563em; - margin-bottom: 0.61805rem; } - -td, th { - padding: 0.38198rem; - white-space: nowrap; } - @media screen and (max-width: 544px) { - td, th { - padding: 0.23608rem; } } - -tbody th { - text-align: right; - width: 130px; - color: white; } - @media screen and (max-width: 544px) { - tbody th { - width: auto; } } - -tbody td input[type="text"], tbody td input[type="number"] { - width: 10em; } - @media screen and (max-width: 544px) { - tbody td input[type="text"], tbody td input[type="number"] { - width: 8em; } } + #content h2 { + font-size: 1.42383em; + margin-bottom: 0.61805rem; } + #content td, #content th { + padding: 0.38198rem; } + #content tbody th { + text-align: right; + width: 160px; + color: white; } #loader { position: absolute; @@ -496,20 +476,122 @@ tbody td input[type="text"], tbody td input[type="number"] { #loader.show { opacity: 1; } -ul > * { - padding-top: .1em; - padding-bottom: .1em; } +.Box { + display: block; + max-width: 900px; + margin-top: 1rem; + padding: 0.61805rem 1rem; + border-radius: 3px; + background-color: rgba(255, 255, 255, 0.07); } + @media screen and (max-width: 544px) { + .Box { + margin-top: 0.61805rem; } } + h1 + .Box { + margin-top: 0; } + .Box h2 { + margin-top: 0; } + .Box.wide { + width: initial; + max-width: initial; } + .Box.medium { + max-width: 1200px; } + .Box.str { + position: relative; } + .Box.str .Row.buttons { + position: absolute; + right: 1rem; + top: 2.7em; + margin: 12px auto; } + @media screen and (min-width: 545px) { + .Box.str .Row.buttons { + right: 0; + top: 0; } } -#botnav { - padding-top: 1.5em; - text-align: center; } - #botnav a { - padding: 0 0.38198rem; - text-decoration: underline; } - #botnav a, #botnav a:visited, #botnav a:link { - color: #2e4d6e; } - #botnav a:hover { - color: #5abfff; } +@media screen and (max-width: 544px) { + .Box.mobcol h2 { + position: relative; + cursor: pointer; + margin-bottom: 0 !important; } + .Box.mobcol h2::after { + position: absolute; + right: 0; + content: '▸'; + top: 50%; + font-size: 120%; + font-weight: bold; + transform: translate(0, -50%) rotate(90deg); } + .Box.mobcol.expanded h2::after { + transform: translate(-25%, -50%) rotate(-90deg); + margin-bottom: 1rem; } + .Box.mobcol .Row { + display: none; } + .Box.mobcol.expanded .Row { + display: flex; } } +.Modal { + position: fixed; + width: 100%; + height: 100%; + left: 0; + top: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + transition: opacity .5s; + background: rgba(0, 0, 0, 0.65); + opacity: 0; } + .Modal.visible { + opacity: 1; } + .Modal.hidden { + display: none; } + +.Dialog { + margin: 0.61805rem; + padding: 1rem; + overflow: hidden; + max-width: 100%; + max-height: 100%; + flex: 0 1 30rem; + background: #1c1c1e; + border-left: 6px solid #2972ba; + border-right: 6px solid #2972ba; + box-shadow: 0 0 2px 0 #434349, 0 0 6px 0 black; + border-radius: 6px; } + .Dialog h1, .Dialog h2 { + margin-top: 0; } + .Dialog p:last-child { + margin-bottom: 0; } + +.NotifyMsg { + position: fixed; + bottom: 2.61792rem; + padding: 0.61805rem 1rem; + left: 50%; + -webkit-transform: translate(-50%, 0); + -moz-transform: translate(-50%, 0); + -ms-transform: translate(-50%, 0); + -o-transform: translate(-50%, 0); + transform: translate(-50%, 0); + -webkit-font-smoothing: subpixel-antialiased; + -webkit-transform: translateZ(0) scale(1, 1); + background: #37a349; + color: white; + text-shadow: 0 0 2px black; + box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.6); + border-radius: 5px; + max-width: 80%; + transition: opacity .5s; + opacity: 0; } + .NotifyMsg.error { + background: #d03e42; } + @media screen and (max-width: 544px) { + .NotifyMsg { + width: calc(100% - 1rem); } } + .NotifyMsg.visible { + opacity: 1; } + .NotifyMsg.hidden { + display: none; } button, input[type=submit], .button { text-align: center; @@ -583,8 +665,8 @@ button, input[type=submit], .button { input[type="number"], input[type="password"], input[type="text"], textarea, select { border: 0 none; - border-bottom: 2px solid #214e7a; - background-color: #303030; + border-bottom: 2px solid #2972ba; + background-color: #3c3c3c; color: white; padding: 6px; line-height: 1em; @@ -592,13 +674,154 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele -moz-outline: 0 none !important; font-weight: normal; } input[type="number"]:focus, input[type="number"]:hover, input[type="password"]:focus, input[type="password"]:hover, input[type="text"]:focus, input[type="text"]:hover, textarea:focus, textarea:hover, select:focus, select:hover { - border-bottom-color: #2972ba; } + border-bottom-color: #2ea1f9; } + +.Row.checkbox { + line-height: 27px; } + .Row.checkbox .box { + width: 27px; + height: 27px; + border: 1px solid #808080; + border-radius: 3px; + background: #3c3c3c; + display: inline-block; + position: relative; + cursor: pointer; + color: #2ea1f9; } + .Row.checkbox .box::before { + font-weight: bold; + position: absolute; + content: '×'; + left: 0; + top: 0; + right: 0; + bottom: 0; + line-height: 26px; + text-align: center; + font-size: 27px; + vertical-align: middle; + display: none; } + .Row.checkbox .box.checked::before { + display: block; } + +.Row.range .display { + margin-left: 1ex; } +.Row.range label .display { + font-weight: normal; } #psk-modal form > *, #wificonfbox form > * { margin-right: 0.38198rem; } #psk-modal form > *:last-child, #wificonfbox form > *:last-child { margin-right: 0; } +form { + border: 0 none; + margin: 0; + padding: 0; + text-decoration: none; } + +input[type="number"], input[type="password"], input[type="text"], textarea, select, label.select-wrap { + width: 250px; } + +input[type="number"] { + width: 125px; } + +form .Row { + vertical-align: middle; + margin: 12px auto; + text-align: left; + display: flex; + flex-direction: row; + align-items: center; } + form .Row:first-child { + margin-top: 0; } + form .Row:last-child { + margin-bottom: 0; } + form .Row .spacer { + width: 160px; } + @media screen and (max-width: 544px) { + form .Row .spacer { + display: none; } } + form .Row.buttons { + margin: 16px auto; } + form .Row.buttons input, form .Row.buttons .button { + margin-right: 0.61805rem; } + form .Row.centered { + justify-content: center; } + form .Row.message { + font-size: 1em; + text-shadow: 1px 1px 3px black; + text-align: center; } + form .Row.message.error { + color: crimson; } + form .Row.message.ok { + color: #0fe851; } + form .Row.separator { + padding-top: 14px; + border-top: 2px solid rgba(255, 255, 255, 0.1); } + form .Row textarea { + display: inline-block; + vertical-align: top; + min-height: 10rem; + flex-grow: 1; + resize: vertical; } + form .Row label { + font-weight: bold; + color: white; + display: inline-block; + width: 160px; + text-align: right; + text-shadow: 1px 1px 3px black; + padding: 8px; + align-self: flex-start; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: nowrap; + word-wrap: normal; } + form .Row input[type="range"] { + width: 200px; } + @media screen and (max-width: 544px) { + form .Row { + flex-direction: column; } + form .Row.buttons, form .Row.centered, form .Row.checkbox { + flex-direction: row; } + form .Row.buttons { + justify-content: center; } + form .Row.buttons :last-child { + margin-right: 0; } + form .Row label { + padding-left: 0; + text-align: left; + width: auto; } + form .Row .checkbox-wrap { + order: 1; + text-align: left; + padding-bottom: 0; + border-radius: .4px; + width: auto; } + form .Row .checkbox-wrap + label { + width: auto; } + form .Row input[type="number"], form .Row input[type="password"], form .Row input[type="text"], form .Row textarea, form .Row input[type="range"], form .Row textarea { + width: 100%; } } + +form span.required { + color: red; } + +.RadioGroup { + display: inline-block; + line-height: 1.5em; + vertical-align: middle; } + .RadioGroup label { + width: auto; + text-align: left; + cursor: pointer; + font-weight: normal; } + .RadioGroup input[type="radio"] { + vertical-align: middle; + margin: 0 0 0 5px; } + #ap-list { column-count: 3; column-gap: 0; @@ -629,6 +852,40 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele #psk-modal form input[type=password] { min-width: 5rem; } +.AP .inner, .AP-preview .wrap { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: 3px; + color: #222; + background: #afafaf; + transition: background-color 0.5s; + display: flex; } + .AP .inner:active, .AP-preview .wrap:active { + left: 0; + top: 1px; } + .AP .inner:hover, .AP-preview .wrap:hover { + background: white; } + .AP .inner .rssi, .AP-preview .wrap .rssi { + min-width: 2.5rem; + flex: 0 0 15%; + text-align: right; } + .AP .inner .rssi:after, .AP-preview .wrap .rssi:after { + padding-left: 0.09018rem; + content: '%'; + font-size: 0.88889em; } + .AP .inner .essid, .AP-preview .wrap .essid { + flex: 1 1 70%; + min-width: 0; + text-overflow: ellipsis; + overflow: hidden; + font-weight: bold; } + .AP .inner .auth, .AP-preview .wrap .auth { + flex: 0 0 15%; } + .AP { break-inside: avoid-column; max-width: 500px; @@ -637,50 +894,55 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele background: #42a6f9 !important; cursor: default; top: 0 !important; } - .AP .inner { - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - position: relative; - border-radius: 3px; - color: #222; - background: #afafaf; - transition: background-color 0.5s; - display: flex; } - .AP .inner:active { - left: 0; - top: 1px; } - .AP .inner:hover { - background: white; } - .AP .inner > * { + .AP .inner > * { + padding: 0.61805rem; + white-space: nowrap; + word-wrap: normal; } + +.AP-preview .wrap { + flex-direction: row; + background: #eee !important; + cursor: default; + top: 0 !important; + overflow: hidden; } + .AP-preview .wrap .inner { + display: flex; + flex-direction: column; } + .AP-preview .wrap .inner > * { padding: 0.61805rem; white-space: nowrap; word-wrap: normal; } - .AP .inner .rssi { - min-width: 2.5rem; - flex: 0 0 15%; - text-align: right; } - .AP .inner .rssi:after { - padding-left: 0.09018rem; - content: '%'; - font-size: 0.88889em; } - .AP .inner .essid { - flex: 1 1 70%; - min-width: 0; - text-overflow: ellipsis; - overflow: hidden; - font-weight: bold; } - .AP .inner .auth { - flex: 0 0 15%; } - -.page-term h1 { + .AP-preview .wrap .forget { + align-self: stretch; + line-height: 100%; + padding: 0.61805rem; + border-left: 1px solid #bbb; + display: flex; + align-items: center; + font-size: 28px; } + .AP-preview .wrap .forget, .AP-preview .wrap .forget:hover { + color: black; + text-decoration: none; } + .AP-preview .wrap .forget:hover { + background: #dc4a6a; + color: white; + border-left: 1px solid #666; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; } + .AP-preview .wrap .forget:active { + position: relative; + padding-top: calc(0.61805rem + 1px); } + .AP-preview .wrap .essid, .AP-preview .wrap .passwd { + padding-bottom: 0; } + .AP-preview .wrap .passwd { + font-family: monospace; } + +body.term h1 { font-size: 1.80203em; } @media screen and (max-width: 544px) { - .page-term h1 { + body.term h1 { font-size: 1.42383em; } } -.page-term #screen { +body.term #screen { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; @@ -692,18 +954,18 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele padding: 6px; display: inline-block; border: 2px solid #3983CD; } - .page-term #screen span { + body.term #screen span { white-space: pre; cursor: pointer; } - .page-term #screen span:hover { + body.term #screen span:hover { outline: 1px solid rgba(255, 255, 255, 0.4); } @media screen and (max-width: 544px) { - .page-term #screen span:hover { + body.term #screen span:hover { outline: 0 none; } } -.page-term #buttons { +body.term #buttons { margin-top: 10px; white-space: nowrap; } - .page-term #buttons button { + body.term #buttons button { margin: 0 3px; padding: 10px 0; width: 18%; @@ -711,6 +973,16 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele min-width: initial; cursor: pointer; font-weight: bold; } +body.term #botnav { + padding-top: 1.5em; + text-align: center; } + body.term #botnav a { + padding: 0 0.38198rem; + text-decoration: underline; } + body.term #botnav a, body.term #botnav a:visited, body.term #botnav a:link { + color: #2e4d6e; } + body.term #botnav a:hover { + color: #5abfff; } #termwrap { text-align: center; } @@ -866,3 +1138,5 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele @media screen and (max-width: 1000px) { .mq-normal-min { display: none; } } + +/*# sourceMappingURL=app.css.map */ diff --git a/html_orig/index.php b/html_orig/index.php new file mode 100644 index 0000000..8402ea6 --- /dev/null +++ b/html_orig/index.php @@ -0,0 +1,64 @@ +label . ' :: ' . APP_NAME); +define('BODYCLASS', $_pages[CUR_PAGE]->bodyclass); + +/** URL (dev or production) */ +function url($name, $root=false) { + global $_pages; + if ($root) return LIVE_ROOT . $_pages[$name]->path; + + if (DEBUG) return "/index.php?page=$name"; + else return $_pages[$name]->path; +} + +/** URL label for a button */ +function label($name) { + global $_pages; + return $_pages[$name]->label; +} + +function e($s) { + return htmlspecialchars($s, ENT_HTML5|ENT_QUOTES); +} + +function tr($key) { + global $_messages; + return $_messages[$key] ?: ('??'.$key.'??'); +} + +/** Like eval, but allows */ +function include_str($code) { + $tmp = tmpfile(); + $tmpf = stream_get_meta_data($tmp); + $tmpf = $tmpf ['uri']; + fwrite($tmp, $code); + $ret = include($tmpf); + fclose($tmp); + return $ret; +} + +require 'pages/_head.php'; +$_pf = 'pages/'.CUR_PAGE.'.php'; +if (file_exists($_pf)) { + $f = file_get_contents($_pf); + $reps = require('_debug_replacements.php'); + $str = str_replace(array_keys($reps), array_values($reps), $f); + include_str($str); +} else { + echo "404"; +} +require 'pages/_tail.php'; diff --git a/html_orig/js/app.js b/html_orig/js/app.js index 7aed10d..055c41f 100644 --- a/html_orig/js/app.js +++ b/html_orig/js/app.js @@ -393,8 +393,9 @@ return cb; }; // Toggle class - cb.toggleClass = function (classes) { - classHelper(classes, 'toggle', nodes); + cb.toggleClass = function (classes, set) { + var method = ((typeof set === 'undefined') ? 'toggle' : (+set ? 'add' : 'remove')); + classHelper(classes, method, nodes); return cb; }; // Has class @@ -795,6 +796,18 @@ String.prototype.format = function () { return out; }; +function e(str) { + return String(str) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); +} + +function undef(x) { + return typeof x == 'undefined'; +} /** Module for toggling a modal overlay */ (function () { var modal = {}; @@ -1088,7 +1101,7 @@ $._loader = function(vis) { console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting..."); setTimeout(function() { init(); - }, 2000); + }, 1000); } function onMessage(evt) { @@ -1211,7 +1224,7 @@ $._loader = function(vis) { // clear the AP list var $list = $('#ap-list'); // remove old APs - $('.AP').remove(); + $('#ap-list .AP').remove(); $list.toggle(done); $('#ap-loader').toggle(!done); @@ -1309,9 +1322,9 @@ $._loader = function(vis) { } $('#modeswitch').html([ - 'Client+AP AP only', - 'Client+AP', - 'Client only AP only' + 'Client+AP AP only', + 'Client+AP', + 'Client only AP only' ][obj.mode-1]); }; diff --git a/html_orig/jssrc/chibi.js b/html_orig/jssrc/chibi.js index 63dfa77..db51e2c 100755 --- a/html_orig/jssrc/chibi.js +++ b/html_orig/jssrc/chibi.js @@ -393,8 +393,9 @@ return cb; }; // Toggle class - cb.toggleClass = function (classes) { - classHelper(classes, 'toggle', nodes); + cb.toggleClass = function (classes, set) { + var method = ((typeof set === 'undefined') ? 'toggle' : (+set ? 'add' : 'remove')); + classHelper(classes, method, nodes); return cb; }; // Has class diff --git a/html_orig/jssrc/utils.js b/html_orig/jssrc/utils.js index 4a7fd0b..9bec8c7 100755 --- a/html_orig/jssrc/utils.js +++ b/html_orig/jssrc/utils.js @@ -93,3 +93,15 @@ String.prototype.format = function () { return out; }; +function e(str) { + return String(str) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); +} + +function undef(x) { + return typeof x == 'undefined'; +} diff --git a/html_orig/jssrc/wifi.js b/html_orig/jssrc/wifi.js index 9fcf4c0..27f9924 100644 --- a/html_orig/jssrc/wifi.js +++ b/html_orig/jssrc/wifi.js @@ -20,7 +20,7 @@ // clear the AP list var $list = $('#ap-list'); // remove old APs - $('.AP').remove(); + $('#ap-list .AP').remove(); $list.toggle(done); $('#ap-loader').toggle(!done); diff --git a/html_orig/messages/en.php b/html_orig/messages/en.php new file mode 100644 index 0000000..90560f4 --- /dev/null +++ b/html_orig/messages/en.php @@ -0,0 +1,35 @@ + 'ESPTerm', + + 'menu.cfg_wifi' => 'WiFi Settings', + 'menu.cfg_network' => 'Network Configuration', + 'menu.cfg_term' => 'Terminal Settings', + 'menu.about' => 'About ESPTerm', + 'menu.help' => 'Help', + 'menu.term' => 'Back to Terminal', + + 'box.ap' => 'Built-in Access Point', + 'box.sta' => 'Client Mode', + + 'wifi.enable' => 'Enabled:', + 'wifi.tpw' => 'Transmit Power:', + 'wifi.ap_channel' => 'Channel:', + 'wifi.ap_ssid' => 'AP SSID:', + 'wifi.ap_password' => 'Password:', + 'wifi.ap_hidden' => 'Hide SSID:', + 'wifi.sta_info' => 'Selected Network:', + + 'wifi.sta_ssid' => 'Network SSID:', + 'wifi.sta_password' => 'Password:', + 'wifi.not_conn' => 'Not connected.', + 'wifi.forget' => '', + + 'wifi.submit' => 'Apply!', + + 'enabled' => 'Enabled', + 'disabled' => 'Disabled', + 'yes' => 'Yes', + 'no' => 'No', +]; diff --git a/html_orig/pages/_cfg_menu.php b/html_orig/pages/_cfg_menu.php new file mode 100644 index 0000000..69b7fe7 --- /dev/null +++ b/html_orig/pages/_cfg_menu.php @@ -0,0 +1,15 @@ + + diff --git a/html_orig/pages/_head.php b/html_orig/pages/_head.php new file mode 100644 index 0000000..f1b3c2e --- /dev/null +++ b/html_orig/pages/_head.php @@ -0,0 +1,26 @@ + + + + + + + <?= PAGE_TITLE ?> + + + + + +
+bodyclass == 'cfg') { + $cfg = true; + require __DIR__ . '/_cfg_menu.php'; +} +?> + +
+Loading… + +

+ diff --git a/html_orig/pages/_tail.php b/html_orig/pages/_tail.php new file mode 100644 index 0000000..560c6a1 --- /dev/null +++ b/html_orig/pages/_tail.php @@ -0,0 +1,5 @@ +
+ +
+ + diff --git a/html_orig/pages/cfg_network.php b/html_orig/pages/cfg_network.php new file mode 100644 index 0000000..e69de29 diff --git a/html_orig/pages/cfg_wifi.php b/html_orig/pages/cfg_wifi.php new file mode 100644 index 0000000..151ec2f --- /dev/null +++ b/html_orig/pages/cfg_wifi.php @@ -0,0 +1,123 @@ +
+

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ +
+ + +
+ +
+ +
+
+ +
+

+ +
+ + +
+ + + + +
+ +
+
+
+
+
+
+
+ × +
+
+
+ +
+ +
+
+ + diff --git a/html_orig/pages/term.php b/html_orig/pages/term.php new file mode 100644 index 0000000..9c6619c --- /dev/null +++ b/html_orig/pages/term.php @@ -0,0 +1,37 @@ + + +

%term_title%

+ +
+
+ +
+ +
+
+ + + + diff --git a/html_orig/sass/_layout.scss b/html_orig/sass/_layout.scss deleted file mode 100644 index ffc2126..0000000 --- a/html_orig/sass/_layout.scss +++ /dev/null @@ -1,178 +0,0 @@ -html { - font-family: Arial, sans-serif; - color: #D0D0D0; - background: #131315; -} - -html, body { - @include naked(); - width: 100%; - height: 100%; - overflow: hidden; -} - -a, a:visited, a:link { - cursor: pointer; - color: #5abfff; - text-decoration: none; -} - -a:hover { - color: #5abfff; - text-decoration: underline; -} - -.Box { - display: block; - max-width: 900px; - - margin-top: dist(0); - padding: dist(-1) dist(0); - - @include media($phone) { - margin-top: dist(-1); - padding: dist(-3) dist(-2); - } - // - //h1 + & { - // margin-top: 0; - //} - // - //h2 { - // margin-top: 0; - //} - - p:first-child { - margin-top:0; - } - - border-radius: 3px; - background-color: rgba(white, .07); - - //&.wide { - // width: initial; - // max-width: initial; - //} - // - //&.medium { - // max-width: 1200px; - //} - // - //.Valfield { - // display: inline-block; - // min-width: 10em; - //} -} - -body { - position: relative; - - padding: dist(0); - @include media($phone) { - padding: dist(-1); - } - - overflow-y: auto; - - & > * { - margin-left: auto; - margin-right: auto; - } -} - -h1,h2 { - @include noselect(); -} - -h1 { - text-align: center; - font-size: fsize(6); - margin-top: 0; - margin-bottom: dist(0); - - @include media($phone) { - font-size: fsize(3); - margin-bottom: dist(-1); - } - - @include media($tablet) { - font-size: fsize(5); - } -} - -h2 { - font-size: fsize(2); - margin-bottom: dist(-1); - //&:first-child{margin-top:0} -} - -td, th { - padding: dist(-2); - white-space: nowrap; - - @include media($phone) { - padding: dist(-3); - } -} - -tbody th { - text-align: right; - width: $form-label-w; - color: $c-form-label-fg; - - @include media($phone) { - width: auto; - } -} - -tbody td { - input[type="text"], input[type="number"] { - width: 10em; - - @include media($phone) { - width: 8em; - } - } -} - -// Loader wheel in top right corner -#loader { - position: absolute; - right: dist(1); - top: dist(1); - - transition: opacity .2s; - opacity: 0; - - @include media($phone) { - top: dist(0); - right: dist(0); - } - - &.show { - opacity:1; - } -} - -ul > * { - padding-top: .1em; - padding-bottom: .1em; -} - -#botnav { - padding-top: 1.5em; - text-align: center; - - a { - padding: 0 dist(-2); - text-decoration: underline; - - &, &:visited, &:link { - color: #2e4d6e; - } - - &:hover { - color: #5abfff; - } - } -} diff --git a/html_orig/sass/app.scss b/html_orig/sass/app.scss index c80c715..b36f320 100755 --- a/html_orig/sass/app.scss +++ b/html_orig/sass/app.scss @@ -6,15 +6,15 @@ @import "utils"; -$form-label-w: 130px; +$form-label-w: 160px; $form-label-gap: 8px; $form-field-w: 250px; $c-form-label-fg: white; -$c-form-field-bg: #303030; +$c-form-field-bg: #3c3c3c; $c-form-field-fg: white; -$c-form-highlight: #214e7a; -$c-form-highlight-a: #2972ba; +$c-form-highlight: #2972ba; +$c-form-highlight-a: #2ea1f9; @function dist($x) { @return modular-scale($x, 1rem, $golden); @@ -24,16 +24,7 @@ $c-form-highlight-a: #2972ba; @return modular-scale($x, 1em, $major-second); } -.hidden { - display: none !important; -} - -[onclick] { - cursor: pointer; -} - -@import "modal"; -@import "layout"; +@import "layout/index"; @import "form/index"; // import all our pages diff --git a/html_orig/sass/form/_form_elements.scss b/html_orig/sass/form/_form_elements.scss index cbc8ef2..eec1261 100755 --- a/html_orig/sass/form/_form_elements.scss +++ b/html_orig/sass/form/_form_elements.scss @@ -16,6 +16,47 @@ } } +.Row.checkbox { + $h: 27px; + line-height: $h; + + .box { + width: $h; + height: $h; + border: 1px solid #808080; + border-radius: 3px; + background: $c-form-field-bg; + display: inline-block; + position: relative; + cursor: pointer; + color: $c-form-highlight-a; + + &::before { + font-weight: bold; + position: absolute; + content: '×'; + left: 0; top: 0; right: 0; bottom: 0; + line-height: $h - 1px; + text-align: center; + font-size: $h; + vertical-align: middle; + display: none; + } + + &.checked::before { + display: block; + } + } +} + +.Row.range { + .display { + margin-left: 1ex; + } + + label .display { font-weight: normal; } +} + //#{$all-text-inputs} { // @include can-select(); //} diff --git a/html_orig/sass/form/_form_layout.scss b/html_orig/sass/form/_form_layout.scss index 73320ab..c6aa39d 100755 --- a/html_orig/sass/form/_form_layout.scss +++ b/html_orig/sass/form/_form_layout.scss @@ -5,13 +5,18 @@ form { @include naked(); } width: $form-field-w; } +input[type="number"] { + width: $form-field-w/2; +} + form .Row { vertical-align: middle; - margin: 14px auto; + margin: 12px auto; text-align: left; display: flex; flex-direction: row; + align-items: center; &:first-child { margin-top: 0; @@ -30,6 +35,7 @@ form .Row { } &.buttons { + margin: 16px auto; input, .button { margin-right: dist(-1); } @@ -80,34 +86,39 @@ form .Row { align-self: flex-start; @include noselect; + @include nowrap; } - .checkbox-wrap { - display: inline-block; - width: $form-label-w; - padding: $form-label-gap; - text-align: right; - align-self: flex-start; - - input[type=checkbox] { - margin: auto; - width: auto; - height: auto; - } - - & + label { - width: $form-field-w; - padding-left: 0; - text-align: left; - cursor: pointer; - } + //.checkbox-wrap { + // display: inline-block; + // width: $form-label-w; + // padding: $form-label-gap; + // text-align: right; + // align-self: flex-start; + // + // input[type=checkbox] { + // margin: auto; + // width: auto; + // height: auto; + // } + // + // & + label { + // width: $form-field-w; + // padding-left: 0; + // text-align: left; + // cursor: pointer; + // } + //} + + input[type="range"] { + width: 200px; } // special phone style @include media($phone) { flex-direction: column; - &.buttons, &.centered { + &.buttons, &.centered, &.checkbox { flex-direction: row; } @@ -139,7 +150,7 @@ form .Row { } } - #{$all-text-inputs}, textarea { + #{$all-text-inputs}, input[type="range"], textarea { width: 100%; } } diff --git a/html_orig/sass/form/_index.scss b/html_orig/sass/form/_index.scss index 7736400..f2e9a7a 100755 --- a/html_orig/sass/form/_index.scss +++ b/html_orig/sass/form/_index.scss @@ -9,5 +9,5 @@ } } -//@import 'form_layout'; +@import 'form_layout'; //@import 'select'; diff --git a/html_orig/sass/layout/_base.scss b/html_orig/sass/layout/_base.scss new file mode 100755 index 0000000..4527f14 --- /dev/null +++ b/html_orig/sass/layout/_base.scss @@ -0,0 +1,31 @@ +html { + font-family: Arial, sans-serif; + color: #D0D0D0; + background: #131315; +} + +html, body { + @include naked(); + width: 100%; + height: 100%; + overflow: hidden; +} + +a, a:visited, a:link { + cursor: pointer; + color: #5abfff; + text-decoration: none; +} + +a:hover { + color: #5abfff; + text-decoration: underline; +} + +.hidden { + display: none !important; +} + +[onclick] { + cursor: pointer; +} diff --git a/html_orig/sass/layout/_box.scss b/html_orig/sass/layout/_box.scss new file mode 100755 index 0000000..1aa3381 --- /dev/null +++ b/html_orig/sass/layout/_box.scss @@ -0,0 +1,91 @@ +.Box { + display: block; + max-width: 900px; + + margin-top: dist(0); + padding: dist(-1) dist(0); + + @include media($phone) { + margin-top: dist(-1); + } + + h1 + & { + margin-top: 0; + } + + h2 { + margin-top: 0; + } + + border-radius: 3px; + background-color: rgba(white, .07); + + &.wide { + width: initial; + max-width: initial; + } + + &.medium { + max-width: 1200px; + } + + //.Valfield { + // display: inline-block; + // min-width: 10em; + //} + + &.str { + position: relative; + + .Row.buttons { + position: absolute; + right: dist(0); + top: 2.7em; + margin: 12px auto; + } + + @include media($tablet-min) { + .Row.buttons { + //position: absolute; + right: 0; + top: 0; + //margin: 12px auto; + } + } + } +} + +@include media($phone) { + .Box.mobcol { + h2 { + position: relative; + cursor: pointer; + + &::after { + position: absolute; + right: 0; + content: '▸'; + + top:50%; + font-size: 120%; + font-weight: bold; + transform: translate(0,-50%) rotate(90deg); + } + + margin-bottom: 0 !important; + } + + &.expanded h2::after { + transform: translate(-25%,-50%) rotate(-90deg); + margin-bottom: dist(0); + } + + .Row { + display: none; + } + + &.expanded .Row { + display: flex; + } + } +} diff --git a/html_orig/sass/layout/_content.scss b/html_orig/sass/layout/_content.scss new file mode 100755 index 0000000..f283350 --- /dev/null +++ b/html_orig/sass/layout/_content.scss @@ -0,0 +1,45 @@ +#content { + flex-grow: 1; + position: relative; + + padding: dist(0); + @include media($phone) { + padding: dist(-1); + } + + overflow-y: auto; + + & > * { + margin-left: auto; + margin-right: auto; + } + + h1 { + text-align: center; + font-size: fsize(7); + margin-top: 0; + margin-bottom: dist(0); + } + + @include media($phone) { + h1 { + font-size: fsize(5); + margin-bottom: dist(-1); + } + } + + h2 { + font-size: fsize(3); + margin-bottom: dist(-1); + } + + td, th { + padding: dist(-2); + } + + tbody th { + text-align: right; + width: $form-label-w; + color: $c-form-label-fg; + } +} diff --git a/html_orig/sass/layout/_espterm_specific_old.scss b/html_orig/sass/layout/_espterm_specific_old.scss new file mode 100644 index 0000000..f2263bd --- /dev/null +++ b/html_orig/sass/layout/_espterm_specific_old.scss @@ -0,0 +1,76 @@ + +ul > * { + padding-top: .1em; + padding-bottom: .1em; +} + +h1,h2 { + @include noselect(); +} + +h1 { + text-align: center; + font-size: fsize(6); + margin-top: 0; + margin-bottom: dist(0); + + @include media($phone) { + font-size: fsize(3); + margin-bottom: dist(-1); + } + + @include media($tablet) { + font-size: fsize(5); + } +} + +h2 { + font-size: fsize(2); + margin-bottom: dist(-1); + //&:first-child{margin-top:0} +} + +td, th { + padding: dist(-2); + white-space: nowrap; + + @include media($phone) { + padding: dist(-3); + } +} + +tbody th { + text-align: right; + width: $form-label-w; + color: $c-form-label-fg; + + @include media($phone) { + width: auto; + } +} + +tbody td { + input[type="text"], input[type="number"] { + width: 10em; + + @include media($phone) { + width: 8em; + } + } +} + +body { + position: relative; + + padding: dist(0); + @include media($phone) { + padding: dist(-1); + } + + overflow-y: auto; + + & > * { + margin-left: auto; + margin-right: auto; + } +} diff --git a/html_orig/sass/layout/_index.scss b/html_orig/sass/layout/_index.scss new file mode 100755 index 0000000..f37ef8d --- /dev/null +++ b/html_orig/sass/layout/_index.scss @@ -0,0 +1,9 @@ +@import "base"; + +@import "outer-wrap"; +@import "menu"; +@import "content"; +@import "loader"; + +@import "box"; +@import "modal"; diff --git a/html_orig/sass/layout/_loader.scss b/html_orig/sass/layout/_loader.scss new file mode 100644 index 0000000..62af4cc --- /dev/null +++ b/html_orig/sass/layout/_loader.scss @@ -0,0 +1,18 @@ +// Loader wheel in top right corner +#loader { + position: absolute; + right: dist(1); + top: dist(1); + + transition: opacity .2s; + opacity: 0; + + @include media($phone) { + top: dist(0); + right: dist(0); + } + + &.show { + opacity:1; + } +} diff --git a/html_orig/sass/layout/_menu.scss b/html_orig/sass/layout/_menu.scss new file mode 100755 index 0000000..766a6ac --- /dev/null +++ b/html_orig/sass/layout/_menu.scss @@ -0,0 +1,98 @@ +#menu { + $menu-bg: #3983CD; + $menu-hl: #5badff; //#1bd886; + $menu-fg: white; + + flex: 0 0 15rem; + background: $menu-bg; + + & > * { + display: block; + text-decoration: none; + padding: dist(-1) dist(0); + + @include nowrap; + @include noselect; + } + + #brand { + color: $menu-fg; + background: darken($menu-bg, 10%); + font-size: 120%; + text-align: center; + position:relative; + transition: none; + font-weight: bold; + + margin-bottom: dist(0); + + @include media($phone) { + background: $menu-bg; + cursor: pointer; + margin-bottom: dist(-2); + + &::after { + position: absolute; + color: rgba(black, .4); + right: dist(0); + content: '▸'; + + top:50%; + font-size: 120%; + font-weight: bold; + transform: translate(0,-50%) rotate(90deg); + } + } + } + &.expanded #brand { + background: darken($menu-bg, 10%); + + @include media($phone) { + &:after { transform: translate(-25%,-50%) rotate(-90deg) } + } + } + + a { + font-size: 130%; + color: $menu-fg; + + transition: background-color 0.2s; + text-shadow: 0 0 5px rgba(black, .4); + + &:hover, &.selected { + background: $menu-hl; + text-shadow: 0 0 5px rgba(black, .6); + } + + &.selected { + position: relative; + box-shadow: 0 0 5px rgba(black, .5); + } + + &::before { + content: "▸"; + padding-right: .5rem; + position: relative; + top: -0.1rem; + } + + @include media($phone) { + display: none; + } + } + + &.expanded a { display:block } + + @include media($tablet) { + #brand { + font-size: 95%; + margin-bottom: dist(-1); + } + + a { font-size: 105%; } + + flex-basis: 10rem; + + & > * { padding: dist(-2) dist(-1); } + } +} diff --git a/html_orig/sass/_modal.scss b/html_orig/sass/layout/_modal.scss similarity index 92% rename from html_orig/sass/_modal.scss rename to html_orig/sass/layout/_modal.scss index c0c72fb..781d833 100755 --- a/html_orig/sass/_modal.scss +++ b/html_orig/sass/layout/_modal.scss @@ -25,8 +25,8 @@ //min-height: 15rem; background: #1c1c1e; - border-left: 6px solid $c-form-highlight-a; - border-right: 6px solid $c-form-highlight-a; + border-left: 6px solid $c-form-highlight; + border-right: 6px solid $c-form-highlight; box-shadow: 0 0 2px 0 #434349, 0 0 6px 0 black; border-radius: 6px; @@ -40,7 +40,6 @@ } } -/* // "toast" .NotifyMsg { position: fixed; @@ -75,4 +74,3 @@ &.visible { opacity: 1 } &.hidden { display: none } } -*/ diff --git a/html_orig/sass/layout/_outer-wrap.scss b/html_orig/sass/layout/_outer-wrap.scss new file mode 100755 index 0000000..c32d3a8 --- /dev/null +++ b/html_orig/sass/layout/_outer-wrap.scss @@ -0,0 +1,22 @@ +/* Main outer container */ +#outer { + display: flex; + + position: absolute; + width: 100%; + height: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; + overflow: hidden; + + flex-direction: row; +} + +@include media($phone) { + #outer { + display: block; + overflow-y: scroll; + } +} diff --git a/html_orig/sass/pages/_term.scss b/html_orig/sass/pages/_term.scss index d642e6d..34b332c 100755 --- a/html_orig/sass/pages/_term.scss +++ b/html_orig/sass/pages/_term.scss @@ -1,4 +1,4 @@ -.page-term { +body.term { h1 { font-size: fsize(5); @include media($phone) { @@ -42,6 +42,24 @@ font-weight: bold; } } + + #botnav { + padding-top: 1.5em; + text-align: center; + + a { + padding: 0 dist(-2); + text-decoration: underline; + + &, &:visited, &:link { + color: #2e4d6e; + } + + &:hover { + color: #5abfff; + } + } + } } #termwrap { diff --git a/html_orig/sass/pages/_wifi.scss b/html_orig/sass/pages/_wifi.scss index 78a52f1..9a392e0 100755 --- a/html_orig/sass/pages/_wifi.scss +++ b/html_orig/sass/pages/_wifi.scss @@ -43,6 +43,50 @@ @extend %form-row-spacing; } +%ap-inner { + cursor: pointer; + @include noselect; + + position: relative; + &:active { + left: 0; + top: 1px; + } + + border-radius: 3px; + color: #222; + + background: #afafaf; + transition: background-color 0.5s; + &:hover { background: white } + + display: flex; + + .rssi { + min-width: 2.5rem; + flex: 0 0 15%; + text-align: right; + + &:after { + padding-left: dist(-5); + content: '%'; + font-size: fsize(-1); + } + } + + .essid { + flex: 1 1 70%; + min-width: 0; + text-overflow: ellipsis; + overflow: hidden; + font-weight: bold; + } + + .auth { + flex: 0 0 15%; + } +} + .AP { // can't use margins inside a column @@ -56,53 +100,70 @@ top: 0 !important; // no click effect } - // the actual silver box .inner { - cursor: pointer; - @include noselect; + @extend %ap-inner; - position: relative; - &:active { - left: 0; - top: 1px; + & > * { + padding: dist(-1); + @include nowrap; } + } +} - border-radius: 3px; - color: #222; +.AP-preview { + .wrap { + @extend %ap-inner; - background: #afafaf; - transition: background-color 0.5s; - &:hover { background: white } + flex-direction: row; + background: #eee !important; // override the hover effect #43de81 + cursor: default; + top: 0 !important; // no click effect + overflow: hidden; - display: flex; + .inner { + display: flex; + flex-direction: column; - & > * { - padding: dist(-1); - @include nowrap; + & > * { + padding: dist(-1); + @include nowrap; + } } + .forget { + align-self: stretch; + line-height: 100%; + padding: dist(-1); + border-left: 1px solid #bbb; + display: flex; + align-items: center; - .rssi { - min-width: 2.5rem; - flex: 0 0 15%; - text-align: right; + &, &:hover { + color: black; + text-decoration: none; + } + + font-size: 28px; + + &:hover { + background: #dc4a6a; + color: white; + border-left: 1px solid #666; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; + } - &:after { - padding-left: dist(-5); - content: '%'; - font-size: fsize(-1); + &:active { + position: relative; + padding-top: calc(#{dist(-1)} + 1px); } } - .essid { - flex: 1 1 70%; - min-width: 0; - text-overflow: ellipsis; - overflow: hidden; - font-weight: bold; + .essid, .passwd { + padding-bottom: 0; } - .auth { - flex: 0 0 15%; + .passwd { + font-family: monospace; } } } diff --git a/html_orig/sass/utils/_background-tiling.scss b/html_orig/sass/utils/_background-tiling.scss new file mode 100755 index 0000000..c1c5916 --- /dev/null +++ b/html_orig/sass/utils/_background-tiling.scss @@ -0,0 +1,68 @@ + +// Utilities for background tiling + +// Use a tile as background (w, h - size of time) +@mixin tile_xy($w, $h, $x, $y) { + background-position: (-$x*$w) (-$y*$h); +} + + +// Use a square tile as background (size - w & h of time) +@mixin tile($size, $x, $y) { + @include tile_xy($size, $size, $x, $y); +} + + +// Button with sprite-sheet +// A B +// B:hover B:hover +@mixin tile_btn_h($w, $h, $x) { + @include tile_xy($w, $h, $x, 0); + &:hover { + @include tile_xy($w, $h, $x, 1); + } +} + +// active the same as hover +@mixin tile_btn_h_act($w, $h, $x) { + @include tile_xy($w, $h, $x, 0); + &:hover, &.active { + @include tile_xy($w, $h, $x, 1); + } +} + + + +// Button with sprite-sheet +// A A:hover +// B B:hover +@mixin tile_btn_v($w, $h, $y) { + @include tile_xy($w, $h, 0, $y); + &:hover { + @include tile_xy($w, $h, 1, $y); + } +} + +// active the same as hover +@mixin tile_btn_v_act($w, $h, $y) { + @include tile_xy($w, $h, 0, $y); + &:hover, &.active { + @include tile_xy($w, $h, 1, $y); + } +} + +@mixin inset-shadow-top($w, $c) { + box-shadow: inset 0 $w ($w*2) (-$w) $c; +} + +@mixin inset-shadow-bottom($w, $c) { + box-shadow: inset 0 (-$w) ($w*2) (-$w) $c; +} + +@mixin inset-shadow-left($w, $c) { + box-shadow: inset $w 0 ($w*2) (-$w) $c; +} + +@mixin inset-shadow-right($w, $c) { + box-shadow: inset (-$w) 0 ($w*2) (-$w) $c; +} diff --git a/html_orig/sass/utils/_index.scss b/html_orig/sass/utils/_index.scss new file mode 100755 index 0000000..4e98733 --- /dev/null +++ b/html_orig/sass/utils/_index.scss @@ -0,0 +1,3 @@ +@import "background-tiling"; +@import "pointer"; +@import "misc"; diff --git a/html_orig/sass/utils/_misc.scss b/html_orig/sass/utils/_misc.scss new file mode 100755 index 0000000..91c0d77 --- /dev/null +++ b/html_orig/sass/utils/_misc.scss @@ -0,0 +1,34 @@ +// Add a highlight for debugging +@mixin highlight($color) { + outline: 1px solid $color; + background: rgba($color, .05); + box-shadow: 0 0 2px 2px rgba($color, .2), inset 0 0 2px 2px rgba($color, .2); +} + +// Ellipsis, but for block elements +@mixin block-ellipsis($width: 100%) { + display: block; + max-width: $width; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-wrap: normal; +} + +// No margins, padding, borders +@mixin naked() { + border: 0 none; + margin: 0; + padding: 0; + text-decoration: none; +} + +@mixin translate($x, $y) { + @include transform(translate($x, $y)); +} + +// Disallow wrapping +@mixin nowrap() { + white-space: nowrap; + word-wrap: normal; +} diff --git a/html_orig/sass/utils/_pointer.scss b/html_orig/sass/utils/_pointer.scss new file mode 100755 index 0000000..c6a9179 --- /dev/null +++ b/html_orig/sass/utils/_pointer.scss @@ -0,0 +1,26 @@ + +@mixin click-through() { + pointer-events: none; +} + + +// Disallow text selection +@mixin noselect() { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + + +// Allow text selection +@mixin can-select() { + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + + cursor: text; +} diff --git a/html_orig/server.sh b/html_orig/server.sh index 4b0b817..467ae0b 100755 --- a/html_orig/server.sh +++ b/html_orig/server.sh @@ -1,3 +1,3 @@ #!/bin/bash -xterm -e "php -S localhost:2000" +xterm -e "php -S 0.0.0.0:2000" diff --git a/user/cgi_wifi.c b/user/cgi_wifi.c index 6347325..2ec3306 100644 --- a/user/cgi_wifi.c +++ b/user/cgi_wifi.c @@ -444,14 +444,38 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) } } + if (GET_ARG("ap_enable")) { + dbg("Enable AP: %s", buff); + int enable = atoi(buff); + + if (enable) { + wificonf->opmode |= SOFTAP_MODE; + } else { + wificonf->opmode &= ~SOFTAP_MODE; + } + } + + if (GET_ARG("sta_enable")) { + dbg("Enable STA: %s", buff); + int enable = atoi(buff); + + if (enable) { + wificonf->opmode |= STATION_MODE; + } else { + wificonf->opmode &= ~STATION_MODE; + } + } + // ---- AP transmit power ---- if (GET_ARG("tpw")) { dbg("Setting AP power to: %s", buff); int tpw = atoi(buff); if (tpw >= 0 && tpw <= 82) { // 0 actually isn't 0 but quite low. 82 is very strong - wificonf->tpw = (u8) tpw; - wifi_change_flags.ap = true; + if (wificonf->tpw != tpw) { + wificonf->tpw = (u8) tpw; + wifi_change_flags.ap = true; + } } else { warn("tpw %s out of allowed range 0-82.", buff); redir_url += sprintf(redir_url, "tpw,"); @@ -464,8 +488,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) info("ap_channel = %s", buff); int channel = atoi(buff); if (channel > 0 && channel < 15) { - wificonf->ap_channel = (u8) channel; - wifi_change_flags.ap = true; + if (wificonf->ap_channel != channel) { + wificonf->ap_channel = (u8) channel; + wifi_change_flags.ap = true; + } } else { warn("Bad channel value \"%s\", allowed 1-14", buff); redir_url += sprintf(redir_url, "ap_channel,"); @@ -485,9 +511,11 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) buff[i] = 0; if (strlen(buff) > 0) { - info("Setting SSID to \"%s\"", buff); - strncpy_safe(wificonf->ap_ssid, buff, SSID_LEN); - wifi_change_flags.ap = true; + if (!streq(wificonf->ap_ssid, buff)) { + info("Setting SSID to \"%s\"", buff); + strncpy_safe(wificonf->ap_ssid, buff, SSID_LEN); + wifi_change_flags.ap = true; + } } else { warn("Bad SSID len."); redir_url += sprintf(redir_url, "ap_ssid,"); @@ -500,9 +528,11 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) // Users are free to use any stupid shit in ther password, // but it may lock them out. if (strlen(buff) == 0 || (strlen(buff) >= 8 && strlen(buff) < PASSWORD_LEN-1)) { - info("Setting AP password to \"%s\"", buff); - strncpy_safe(wificonf->ap_password, buff, PASSWORD_LEN); - wifi_change_flags.ap = true; + if (!streq(wificonf->ap_password, buff)) { + info("Setting AP password to \"%s\"", buff); + strncpy_safe(wificonf->ap_password, buff, PASSWORD_LEN); + wifi_change_flags.ap = true; + } } else { warn("Bad password len."); redir_url += sprintf(redir_url, "ap_password,"); @@ -514,8 +544,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) if (GET_ARG("ap_hidden")) { dbg("AP hidden = %s", buff); int hidden = atoi(buff); - wificonf->ap_hidden = (hidden != 0); - wifi_change_flags.ap = true; + if (hidden != wificonf->ap_hidden) { + wificonf->ap_hidden = (hidden != 0); + wifi_change_flags.ap = true; + } } // ---- AP DHCP server lease time ---- @@ -524,8 +556,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) dbg("Setting DHCP lease time to: %s min.", buff); int min = atoi(buff); if (min >= 1 && min <= 2880) { - wificonf->ap_dhcp_time = (u16) min; - wifi_change_flags.ap = true; + if (wificonf->ap_dhcp_time != min) { + wificonf->ap_dhcp_time = (u16) min; + wifi_change_flags.ap = true; + } } else { warn("Lease time %s out of allowed range 1-2880.", buff); redir_url += sprintf(redir_url, "ap_dhcp_time,"); @@ -534,27 +568,31 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) // ---- AP DHCP start and end IP ---- - if (GET_ARG("ap_dhcp_range_start")) { + if (GET_ARG("ap_dhcp_start")) { dbg("Setting DHCP range start IP to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0) { - wificonf->ap_dhcp_range.start_ip.addr = ip; - wifi_change_flags.ap = true; + if (wificonf->ap_dhcp_range.start_ip.addr != ip) { + wificonf->ap_dhcp_range.start_ip.addr = ip; + wifi_change_flags.ap = true; + } } else { warn("Bad IP: %s", buff); - redir_url += sprintf(redir_url, "ap_dhcp_range_start,"); + redir_url += sprintf(redir_url, "ap_dhcp_start,"); } } - if (GET_ARG("ap_dhcp_range_end")) { + if (GET_ARG("ap_dhcp_end")) { dbg("Setting DHCP range end IP to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0) { - wificonf->ap_dhcp_range.end_ip.addr = ip; - wifi_change_flags.ap = true; + if (wificonf->ap_dhcp_range.end_ip.addr != ip) { + wificonf->ap_dhcp_range.end_ip.addr = ip; + wifi_change_flags.ap = true; + } } else { warn("Bad IP: %s", buff); - redir_url += sprintf(redir_url, "ap_dhcp_range_end,"); + redir_url += sprintf(redir_url, "ap_dhcp_end,"); } } @@ -564,9 +602,11 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) dbg("Setting AP local IP to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0) { - wificonf->ap_addr.ip.addr = ip; - wificonf->ap_addr.gw.addr = ip; // always the same, we're the router here - wifi_change_flags.ap = true; + if (wificonf->ap_addr.ip.addr != ip) { + wificonf->ap_addr.ip.addr = ip; + wificonf->ap_addr.gw.addr = ip; // always the same, we're the router here + wifi_change_flags.ap = true; + } } else { warn("Bad IP: %s", buff); redir_url += sprintf(redir_url, "ap_addr_ip,"); @@ -577,10 +617,12 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) dbg("Setting AP local IP netmask to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0) { - // ideally this should be checked to match the IP. - // Let's hope users know what they're doing - wificonf->ap_addr.netmask.addr = ip; - wifi_change_flags.ap = true; + if (wificonf->ap_addr.netmask.addr != ip) { + // ideally this should be checked to match the IP. + // Let's hope users know what they're doing + wificonf->ap_addr.netmask.addr = ip; + wifi_change_flags.ap = true; + } } else { warn("Bad IP mask: %s", buff); redir_url += sprintf(redir_url, "ap_addr_mask,"); @@ -590,19 +632,23 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) // ---- Station SSID (to connect to) ---- if (GET_ARG("sta_ssid")) { - // No verification needed, at worst it fails to connect - info("Setting station SSID to: \"%s\"", buff); - strncpy_safe(wificonf->sta_ssid, buff, SSID_LEN); - wifi_change_flags.sta = true; + if (!streq(wificonf->sta_ssid, buff)) { + // No verification needed, at worst it fails to connect + info("Setting station SSID to: \"%s\"", buff); + strncpy_safe(wificonf->sta_ssid, buff, SSID_LEN); + wifi_change_flags.sta = true; + } } // ---- Station password (empty for none is allowed) ---- if (GET_ARG("sta_password")) { - // No verification needed, at worst it fails to connect - info("Setting station password to: \"%s\"", buff); - strncpy_safe(wificonf->sta_password, buff, PASSWORD_LEN); - wifi_change_flags.sta = true; + if (!streq(wificonf->sta_password, buff)) { + // No verification needed, at worst it fails to connect + info("Setting station password to: \"%s\"", buff); + strncpy_safe(wificonf->sta_password, buff, PASSWORD_LEN); + wifi_change_flags.sta = true; + } } // ---- Station enable/disable DHCP ---- @@ -611,8 +657,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) if (GET_ARG("sta_dhcp_enable")) { dbg("DHCP enable = %s", buff); int enable = atoi(buff); - wificonf->sta_dhcp_enable = (enable != 0); - wifi_change_flags.sta = true; + if (wificonf->sta_dhcp_enable != enable) { + wificonf->sta_dhcp_enable = (bool)enable; + wifi_change_flags.sta = true; + } } // ---- Station IP config (Static IP) ---- @@ -621,8 +669,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) dbg("Setting Station mode static IP to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0) { - wificonf->sta_addr.ip.addr = ip; - wifi_change_flags.sta = true; + if (wificonf->sta_addr.ip.addr != ip) { + wificonf->sta_addr.ip.addr = ip; + wifi_change_flags.sta = true; + } } else { warn("Bad IP: %s", buff); redir_url += sprintf(redir_url, "sta_addr_ip,"); @@ -633,8 +683,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) dbg("Setting Station mode static IP netmask to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0 && ip != 0xFFFFFFFFUL) { - wificonf->sta_addr.netmask.addr = ip; - wifi_change_flags.sta = true; + if (wificonf->sta_addr.netmask.addr != ip) { + wificonf->sta_addr.netmask.addr = ip; + wifi_change_flags.sta = true; + } } else { warn("Bad IP mask: %s", buff); redir_url += sprintf(redir_url, "sta_addr_mask,"); @@ -645,8 +697,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) dbg("Setting Station mode static IP default gateway to: \"%s\"", buff); u32 ip = ipaddr_addr(buff); if (ip != 0) { - wificonf->sta_addr.gw.addr = ip; - wifi_change_flags.sta = true; + if (wificonf->sta_addr.gw.addr != ip) { + wificonf->sta_addr.gw.addr = ip; + wifi_change_flags.sta = true; + } } else { warn("Bad gw IP: %s", buff); redir_url += sprintf(redir_url, "sta_addr_gw,"); @@ -700,6 +754,12 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, else if (streq(token, "opmode")) { sprintf(buff, "%d", wificonf->opmode); } + else if (streq(token, "sta_enable")) { + sprintf(buff, "%d", (wificonf->opmode & STATION_MODE) != 0); + } + else if (streq(token, "ap_enable")) { + sprintf(buff, "%d", (wificonf->opmode & SOFTAP_MODE) != 0); + } else if (streq(token, "tpw")) { sprintf(buff, "%d", wificonf->tpw); } @@ -718,10 +778,10 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, else if (streq(token, "ap_dhcp_time")) { sprintf(buff, "%d", wificonf->ap_dhcp_time); } - else if (streq(token, "ap_dhcp_range_start")) { + else if (streq(token, "ap_dhcp_start")) { sprintf(buff, IPSTR, GOOD_IP2STR(wificonf->ap_dhcp_range.start_ip.addr)); } - else if (streq(token, "ap_dhcp_range_end")) { + else if (streq(token, "ap_dhcp_end")) { sprintf(buff, IPSTR, GOOD_IP2STR(wificonf->ap_dhcp_range.end_ip.addr)); } else if (streq(token, "ap_addr_ip")) {