mirror of
https://github.com/mfactory-osaka/ESPTimeCast.git
synced 2026-02-19 11:54:56 -05:00
430 lines
32 KiB
HTML
430 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>ESPTimeCast Settings</title>
|
||
<style>
|
||
* { box-sizing: border-box; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||
margin: 0; padding: 2rem 1rem;
|
||
background-color: #121212; color: #FFFFFF;
|
||
}
|
||
body.modal-open {
|
||
overflow: hidden;
|
||
}
|
||
h1 {
|
||
text-align: center;
|
||
font-size: 1.5rem;
|
||
margin-bottom: 1.5rem;
|
||
color: #ffffff;
|
||
}
|
||
h2{
|
||
margin-top: 3rem;
|
||
margin-bottom: 0;
|
||
}
|
||
.logo svg{
|
||
filter: drop-shadow(0px 0px 0.5rem gray);
|
||
}
|
||
form {
|
||
display: flex; flex-direction: column;
|
||
max-width: 500px; margin: 0 auto;
|
||
background-color: #1e1e1e; padding: 1.5rem;
|
||
border-radius: 12px;
|
||
box-shadow: 0 0 10px rgba(0,0,0,0.4);
|
||
}
|
||
label {
|
||
font-size: 0.9rem;
|
||
color: #bbb;
|
||
margin-bottom: 0.25rem;
|
||
display: block;
|
||
margin-top: 0.75rem;
|
||
}
|
||
input[type="text"],
|
||
input[type="password"],
|
||
input[type="number"], select {
|
||
width: 100%; padding: 0.75rem;
|
||
border: none; border-radius: 8px;
|
||
background-color: #2c2c2c; color: #ffffff;
|
||
font-size: 1rem; appearance: none;
|
||
}
|
||
input[type="submit"] {
|
||
background-color: #007aff; color: white;
|
||
padding: 0.9rem; font-size: 1rem;
|
||
border: none; border-radius: 8px;
|
||
cursor: pointer; transition: background-color 0.2s ease-in-out;
|
||
}
|
||
input[type="submit"]:hover {
|
||
background-color: #005ecb;
|
||
}
|
||
.form-row {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.form-row.two-col {
|
||
flex-direction: column;
|
||
}
|
||
.form-row.two-col > div {
|
||
flex: 1;
|
||
}
|
||
.primary-button {
|
||
background: linear-gradient(135deg, #007aff, #005ecb); color: white;
|
||
padding: 0.9rem; font-size: 1rem; font-weight: 600;
|
||
border: none; border-radius: 8px;
|
||
cursor: pointer; text-align: center;
|
||
transition: background 0.25s, transform 0.15s ease-in-out;
|
||
}
|
||
.primary-button:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 6px 16px rgba(0, 122, 255, 0.35);
|
||
}
|
||
.primary-button:active {
|
||
transform: scale(0.97);
|
||
}
|
||
.note {
|
||
font-size: 0.85rem;
|
||
text-align: center;
|
||
color: #888;
|
||
margin-top: 1rem;
|
||
}
|
||
#savingModal {
|
||
backdrop-filter: blur(5px);
|
||
position: fixed; top: 0; left: 0;
|
||
width: 100%; height: 100%;
|
||
background-color: rgba(18, 18, 18, 0.85);
|
||
display: none; justify-content: center; align-items: center;
|
||
z-index: 1000;
|
||
}
|
||
#savingModalContent {
|
||
margin: 1.5rem; background-color: #1e1e1e;
|
||
padding: 2rem 2.5rem; border-radius: 12px;
|
||
text-align: center; color: white;
|
||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.6);
|
||
}
|
||
.spinner {
|
||
border: 4px solid rgba(255, 255, 255, 0.2);
|
||
border-top: 4px solid #007aff;
|
||
border-radius: 50%;
|
||
width: 36px; height: 36px;
|
||
animation: spin 1s linear infinite;
|
||
margin: 0 auto 1rem;
|
||
}
|
||
.footer{
|
||
font-size: 0.8rem;
|
||
text-align: center;
|
||
color: #aaa;
|
||
margin-top: 1rem;
|
||
}
|
||
a{
|
||
color: white;
|
||
}
|
||
@keyframes spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
@media (min-width: 320px) {
|
||
.form-row.two-col {
|
||
flex-direction: row;
|
||
gap: 1rem; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<form id="configForm" onsubmit="submitConfig(event)">
|
||
<div class="logo">
|
||
<svg viewBox="0 0 132.291 14.322" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:currentColor; stroke-width:1" d="M326.491 337.688c-.233.003-.476.121-.657.38-.333.475-.326.56.074.96.603.604 1.332.33 1.332-.499 0-.529-.36-.846-.749-.841m4.23.009c-.698 0-1.057.903-.557 1.403.144.143.4.261.57.261.38 0 .832-.43.832-.79 0-.368-.49-.874-.845-.874m35.71 0c-.697 0-1.055.903-.556 1.403.144.143.4.261.57.261.38 0 .833-.43.833-.79 0-.368-.49-.874-.846-.874m-118.103.008a.7.7 0 0 0-.504.192c-.28.28-.248.892.062 1.203.337.337.716.332 1.098-.014.378-.342.387-.69.03-1.085a.93.93 0 0 0-.686-.296m22.402 0a.7.7 0 0 0-.505.192c-.28.28-.248.892.062 1.203.337.337.716.332 1.099-.014.377-.342.386-.69.028-1.085a.93.93 0 0 0-.684-.296m15.342 0a.7.7 0 0 0-.504.192c-.28.28-.248.892.062 1.203.337.336.717.332 1.099-.014.377-.342.387-.69.029-1.085a.93.93 0 0 0-.686-.296m-28.564 0c-.248-.009-.496.112-.672.362-.333.476-.326.56.074.961.45.45.935.419 1.264-.083.252-.385.252-.447 0-.832-.172-.262-.419-.399-.666-.408m15.445 0c-.248-.009-.496.112-.671.362-.334.476-.327.56.073.961.451.45.935.419 1.264-.083.252-.385.252-.447 0-.832-.172-.262-.419-.399-.666-.408m-30.884.001a.76.76 0 0 0-.663.343c-.27.386-.199.783.2 1.104.403.325.827.246 1.125-.208.252-.385.252-.447 0-.832-.17-.258-.416-.395-.662-.407m37.744 0a.76.76 0 0 0-.663.343c-.27.386-.199.783.2 1.104.402.325.827.246 1.125-.208.252-.385.252-.447 0-.832-.17-.258-.416-.395-.662-.407m-39.949.002c-.232.003-.445.108-.554.31-.242.452-.215.778.089 1.082.337.336.716.332 1.098-.014.378-.342.387-.69.03-1.085a.9.9 0 0 0-.663-.293m15.444 0c-.232.003-.447.108-.555.31-.242.452-.215.778.09 1.082.336.337.715.332 1.097-.014.378-.342.387-.69.03-1.085a.9.9 0 0 0-.662-.293m73.302.001q-.279.004-.567.263c-.377.342-.387.69-.029 1.085.152.167.409.304.57.304.698 0 1.057-.903.558-1.402q-.255-.253-.532-.25m-40.331.005a.75.75 0 0 0-.648.343c-.341.488-.335.569.078.982.436.436 1.004.358 1.269-.176.298-.6-.186-1.133-.699-1.149m-42.007.01a.8.8 0 0 0-.55.235c-.336.337-.331.716.015 1.098.494.546 1.389.206 1.389-.528 0-.488-.425-.813-.854-.805m22.4 0a.8.8 0 0 0-.548.235c-.337.337-.332.716.014 1.098.494.546 1.388.206 1.388-.528 0-.488-.424-.813-.853-.805m15.344 0a.8.8 0 0 0-.55.235c-.336.337-.331.716.015 1.098.494.546 1.388.206 1.388-.528 0-.488-.424-.813-.853-.805m-39.875.001a.8.8 0 0 0-.505.217c-.41.37-.43.71-.063 1.115.554.611 1.456.203 1.362-.616-.053-.458-.413-.733-.794-.716m15.443 0a.8.8 0 0 0-.505.217c-.41.37-.429.71-.063 1.115.554.611 1.456.203 1.362-.616-.053-.458-.413-.733-.794-.716m6.958 0a.8.8 0 0 0-.505.217c-.41.37-.429.71-.063 1.115.554.611 1.455.203 1.362-.616-.053-.458-.414-.733-.794-.716m15.343 0a.8.8 0 0 0-.505.217c-.41.37-.43.71-.063 1.115.554.611 1.456.203 1.362-.616-.053-.458-.413-.733-.794-.716m11.157 0a.8.8 0 0 0-.504.217c-.41.37-.43.71-.063 1.115.553.611 1.455.203 1.361-.616-.052-.458-.413-.733-.794-.716m-53.124 2.112c-.608-.001-1.077.752-.505 1.383.355.393.643.385 1.056-.028.4-.401.422-.72.071-1.07-.2-.2-.419-.285-.622-.285m126.508.01a.8.8 0 0 0-.464.13c-.43.27-.424.976.012 1.282.476.334.52.332.978-.04.613-.496.123-1.348-.526-1.372m-42.091.013c-.728 0-1.005.782-.481 1.36.151.168.376.304.5.304.275 0 .889-.594.889-.86 0-.332-.533-.804-.908-.804m8.487 0c-.728 0-1.004.782-.48 1.36.15.168.375.304.498.304.276 0 .89-.594.89-.86 0-.332-.533-.804-.908-.804m-66.164.008a.97.97 0 0 0-.698.253c-.35.351-.33.67.072 1.07.4.4.719.422 1.07.071.31-.31.341-.923.061-1.203a.74.74 0 0 0-.505-.19m8.487 0c-.253-.008-.523.079-.697.253-.35.351-.33.67.07 1.07.402.4.72.422 1.07.071.311-.31.343-.923.063-1.203a.75.75 0 0 0-.506-.19m-21.896.075c-.482 0-.601.077-.741.475-.144.41-.113.52.222.79.496.403.726.398 1.106-.022.242-.268.273-.432.147-.79-.132-.375-.259-.453-.734-.453m8.487 0c-.481 0-.601.077-.741.475-.144.41-.113.52.222.79.497.403.726.398 1.106-.022.243-.268.273-.432.147-.79-.132-.375-.259-.453-.734-.453m22.301 0c-.481 0-.6.077-.741.475-.144.41-.113.52.222.79.497.403.726.398 1.106-.022.243-.268.273-.432.147-.79-.132-.375-.258-.453-.734-.453m-17.528 1.934c-.14-.001-.265.1-.477.313-.401.4-.422.719-.072 1.07.31.31.923.341 1.203.061.318-.318.232-.923-.17-1.205-.223-.156-.36-.238-.484-.24m8.487 0c-.14-.001-.264.1-.477.313-.4.4-.422.719-.071 1.07.31.31.923.341 1.203.061.317-.318.232-.923-.17-1.205-.224-.156-.361-.238-.485-.24m18.014 0c-.141-.001-.265.1-.478.313-.4.4-.421.719-.07 1.07.31.31.922.341 1.202.061.318-.318.232-.923-.17-1.205-.223-.156-.36-.238-.484-.24m4.794 0c-.14-.001-.264.1-.477.313-.4.4-.422.719-.072 1.07.31.31.923.341 1.203.061.318-.318.233-.923-.17-1.205-.223-.156-.36-.238-.484-.24m15.452 0c-.14-.001-.265.1-.477.313-.401.4-.422.719-.072 1.07.31.31.923.341 1.203.061.318-.317.232-.923-.17-1.205-.223-.156-.36-.238-.484-.24m51.004 0c-.14-.001-.264.1-.477.313-.4.4-.422.719-.071 1.07.31.31.923.341 1.203.061.317-.317.232-.923-.17-1.205-.224-.156-.36-.238-.485-.24m-111.01.025c-.113 0-.224.063-.417.19-.446.291-.552.894-.216 1.229.11.11.394.2.632.2.877 0 1.153-.947.416-1.43-.193-.126-.304-.19-.416-.19m30.787 0c-.111 0-.223.063-.416.19-.445.291-.552.894-.216 1.229.11.11.394.2.632.2.878 0 1.153-.947.416-1.43-.192-.126-.304-.19-.416-.19m18.121.01c-.111 0-.223.063-.416.19-.446.292-.551.894-.216 1.23.257.257 1.007.257 1.265 0 .335-.336.229-.938-.217-1.23-.192-.127-.304-.19-.416-.19m44.047.003c-.275-.001-.55.175-.712.53-.138.303-.122.474.068.745.135.194.425.352.643.352.56 0 .944-.588.714-1.092-.162-.355-.437-.534-.713-.535m-42.108.012c-.525.016-.892.648-.53 1.202.326.496.979.513 1.314.034.289-.411.132-.855-.402-1.141a.75.75 0 0 0-.382-.095m37.717 0c-.525.016-.892.648-.53 1.202.326.496.979.513 1.315.034.288-.411.131-.855-.403-1.141a.76.76 0 0 0-.382-.095m15.462.005a.6.6 0 0 0-.267.075c-.47.252-.574.672-.28 1.122.278.423.888.52 1.215.193.5-.5-.049-1.421-.668-1.39m2.217.002h-.059a.64.64 0 0 0-.27.078.854.854 0 0 0-.358 1.17c.204.382.977.465 1.302.14.488-.488-.015-1.366-.615-1.388m-119.55 0c-.595.03-1.092.902-.606 1.388.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m77.636 0c-.596.03-1.092.902-.607 1.388.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m6.806 0c-.597.03-1.093.902-.607 1.388.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m15.46 0c-.597.03-1.093.902-.607 1.388.11.11.406.2.66.2.833 0 1.04-1.105.282-1.51a.64.64 0 0 0-.336-.078m4.211 0a.63.63 0 0 0-.336.078.854.854 0 0 0-.359 1.17c.204.382.977.465 1.302.14.486-.486-.01-1.357-.607-1.388m9.07 0c-.597.03-1.093.902-.607 1.388.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m2.163 0c-.596.03-1.093.902-.607 1.388.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m11.131 0c-.596.03-1.093.902-.607 1.388.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m2.164 0c-.597.03-1.093.902-.607 1.388.11.11.406.2.66.2.832 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m2.009.001a.6.6 0 0 0-.29.072c-.632.338-.582 1.112.097 1.497.398.226.94-.15 1.007-.699.055-.458-.386-.871-.814-.87m-70.624.002c-.602.027-1.102.894-.612 1.385.278.278 1.05.25 1.296-.048.275-.33.084-1.028-.344-1.257a.65.65 0 0 0-.34-.08m15.452 0c-.603.027-1.103.894-.612 1.385.278.278 1.05.25 1.296-.048.275-.33.084-1.028-.344-1.257a.65.65 0 0 0-.34-.08m-60.08 2.084c-.61 0-1.002 1.023-.56 1.464s1.464.05 1.464-.56c0-.308-.596-.904-.904-.904m15.445 0c-.61 0-1.002 1.023-.56 1.464s1.464.05 1.464-.56c0-.308-.596-.904-.904-.904m31.295 0c-.61 0-1.002 1.023-.56 1.464.42.42 1.464.011 1.464-.575 0-.296-.603-.89-.904-.89m22.258 0c-.61 0-1.002 1.023-.56 1.464.42.42 1.464.011 1.464-.575 0-.296-.603-.89-.904-.89m21.884 0c-.357 0-.861.496-.861.846 0 .162.117.412.261.556s.4.262.57.262c.38 0 .833-.43.833-.79 0-.348-.483-.874-.803-.874m20.252 0c-.357 0-.861.496-.861.846 0 .162.117.412.261.556s.4.262.57.262c.38 0 .833-.43.833-.79 0-.348-.483-.874-.803-.874m-28.696.01c-.232.001-.476.12-.66.383-.333.476-.327.56.074.962.562.562 1.331.289 1.331-.472 0-.545-.357-.874-.745-.872m-97.915.005c-.159 0-.3.082-.465.247-.349.348-.332 1.012.03 1.223.964.561 1.908-.592 1.003-1.226-.234-.163-.41-.245-.568-.244m6.472 0c-.182-.01-.368.077-.57.26-.377.341-.39.78-.034 1.137.718.718 1.83-.321 1.148-1.074-.185-.205-.363-.312-.544-.322m22.4 0c-.181-.01-.367.077-.57.26-.376.341-.389.78-.033 1.137.718.718 1.83-.321 1.148-1.074-.185-.205-.363-.312-.545-.322m15.344 0c-.182-.01-.368.077-.57.26-.377.341-.39.78-.034 1.137.718.718 1.83-.321 1.148-1.074-.185-.205-.363-.312-.544-.322m27.088.028c-.583.002-1.021.64-.644 1.216.329.502.982.532 1.312.062.292-.418.181-.939-.25-1.17a.9.9 0 0 0-.418-.108m-4.882.007a.76.76 0 0 0-.479.206c-.4.362-.414.702-.043 1.112.33.365 1.02.337 1.264-.053.384-.612-.16-1.292-.742-1.265m44.674 0a.76.76 0 0 0-.478.206c-.4.362-.414.702-.044 1.112.331.365 1.022.337 1.265-.053.384-.612-.16-1.292-.743-1.265m-106.757.003c-.267.003-.547.153-.728.476-.228.408-.222.477.062.79.557.616 1.425.356 1.425-.425 0-.538-.367-.846-.758-.84m15.443 0c-.268.003-.547.153-.727.476-.228.408-.223.477.061.79.557.616 1.425.356 1.425-.425 0-.538-.367-.846-.759-.84m6.958 0c-.268.003-.547.153-.728.476-.228.408-.222.477.062.79.557.616 1.425.356 1.425-.425 0-.538-.367-.846-.759-.84m26.501 0c-.268.003-.547.153-.728.476-.228.408-.223.477.062.79.556.616 1.425.356 1.425-.425 0-.538-.367-.846-.759-.84m4.795 0c-.268.003-.548.153-.728.476-.228.408-.223.477.061.79.557.616 1.425.356 1.425-.425 0-.538-.367-.846-.758-.84m21.806 0a.85.85 0 0 0-.782.468c-.136.254-.115.43.087.738.485.74 1.423.44 1.423-.454 0-.469-.35-.74-.728-.752m-77.674 0c-.603-.007-1.03.684-.62 1.267.132.19.42.344.638.344.84 0 1.096-1.18.33-1.529a.9.9 0 0 0-.348-.081m15.443 0c-.603-.007-1.029.684-.62 1.267.132.19.42.344.638.344.84 0 1.096-1.18.33-1.529a.9.9 0 0 0-.348-.081m15.445 0c-.603-.007-1.029.684-.62 1.267.133.19.42.344.638.344.84 0 1.096-1.18.33-1.529a.9.9 0 0 0-.348-.081m38.282 2.098c-.233 0-.477.12-.66.382-.334.476-.327.56.073.962.562.562 1.331.289 1.331-.472 0-.545-.357-.874-.744-.872m8.487 0c-.233 0-.476.12-.66.382-.334.476-.327.56.073.962.563.562 1.332.289 1.332-.472 0-.545-.358-.874-.745-.872m37.71 0c-.233 0-.476.12-.66.382-.334.476-.327.56.074.962.562.562 1.33.289 1.33-.472 0-.545-.356-.874-.744-.872m-39.967.015a.68.68 0 0 0-.46.197c-.299.3-.243 1.09.092 1.285.48.28.85.203 1.138-.237.253-.385.253-.446 0-.832a.9.9 0 0 0-.77-.413m20.118 0a.68.68 0 0 0-.46.197c-.3.3-.243 1.09.091 1.285.481.28.85.203 1.139-.237.252-.385.252-.446 0-.832a.9.9 0 0 0-.77-.413m17.592 0a.68.68 0 0 0-.46.197c-.3.3-.243 1.09.092 1.285.48.28.85.203 1.139-.237.252-.385.252-.446 0-.832a.9.9 0 0 0-.771-.413m-115.3.004a.7.7 0 0 0-.505.192c-.28.28-.249.893.062 1.203.337.337.716.332 1.098-.014.378-.342.387-.689.03-1.084a.93.93 0 0 0-.686-.297m66.51.004q-.278.004-.566.263c-.378.342-.387.69-.03 1.085.152.167.409.304.571.304.698 0 1.056-.903.557-1.403q-.255-.251-.532-.249m6.964 0q-.278.004-.566.263c-.377.342-.387.69-.029 1.085.152.167.408.304.57.304.698 0 1.057-.903.558-1.403q-.255-.251-.532-.249m-11.356.008a.67.67 0 0 0-.399.154c-.336.28-.304 1.104.051 1.31.45.262.793.213 1.134-.164.284-.314.29-.383.062-.79-.19-.34-.532-.526-.848-.51m22.257 0a.67.67 0 0 0-.398.154c-.336.28-.304 1.104.05 1.31.45.262.794.213 1.134-.164.285-.314.29-.383.062-.79-.19-.34-.532-.526-.848-.51m-57.727.005c-.16 0-.286.069-.453.22-.441.4-.43.837.032 1.16.45.316.643.324 1.027.043.46-.336.297-1.153-.269-1.35a1 1 0 0 0-.337-.073m86.64.002a.8.8 0 0 0-.55.235c-.336.337-.331.716.015 1.098.494.546 1.388.206 1.388-.527 0-.489-.424-.814-.853-.806m-91.415 0a.8.8 0 0 0-.55.235c-.336.337-.331.716.015 1.098.494.546 1.388.206 1.388-.527 0-.489-.424-.814-.853-.805m22.3 0a.8.8 0 0 0-.548.235c-.337.337-.332.716.014 1.098.494.546 1.388.206 1.388-.527 0-.489-.424-.814-.853-.805m31.405 0a.8.8 0 0 0-.55.235c-.336.337-.331.716.015 1.098.494.546 1.388.206 1.388-.527 0-.489-.424-.814-.853-.805m-22.378.002a.8.8 0 0 0-.504.217c-.41.37-.43.71-.063 1.114.553.612 1.455.204 1.361-.616-.052-.458-.413-.733-.794-.715m4.804.004a.76.76 0 0 0-.514.212c-.41.371-.429.71-.063 1.115.341.377.78.39 1.137.034.56-.562.05-1.362-.56-1.361m48.345 0c-.602-.026-1.104.72-.574 1.305.357.394.794.418 1.147.065.354-.354.33-.79-.064-1.147a.8.8 0 0 0-.51-.223m20.252 0c-.603-.026-1.104.72-.573 1.305.356.394.793.418 1.146.065.354-.354.33-.79-.064-1.147a.8.8 0 0 0-.51-.223m-113.172 2.13a.81.81 0 0 0-.764.56c-.143.407-.112.518.223.79.214.173.44.315.5.315.318 0 .851-.567.851-.904 0-.5-.404-.771-.81-.76m84.414 0c-.406-.01-.81.26-.81.76 0 .213.166.503.37.646.467.327.51.325.98-.057.335-.27.367-.382.224-.79a.81.81 0 0 0-.764-.559m8.487 0c-.406-.01-.81.26-.81.76 0 .213.166.503.37.646.467.327.51.325.98-.057.336-.27.367-.382.224-.79a.81.81 0 0 0-.764-.559m20.252 0c-.406-.01-.81.26-.81.76 0 .213.166.503.37.646.467.327.51.325.98-.057.336-.27.367-.382.224-.79a.81.81 0 0 0-.764-.559m-68.625 0c-.762 0-1.034.77-.472 1.332.405.405.63.417 1.027.057.615-.556.282-1.388-.555-1.388m4.278 0c-.778 0-1.038.949-.386 1.406.203.142.428.259.499.259.201 0 .795-.643.795-.86 0-.333-.533-.804-.908-.804m4.209 0c-.762 0-1.034.77-.472 1.332.405.405.63.417 1.027.057.615-.556.282-1.388-.555-1.388m4.912 0c-.777 0-1.067.955-.444 1.457.142.114.341.208.444.208.262 0 .685-.366.796-.688.137-.397-.336-.976-.796-.976m13.137 0c-.778 0-1.039.949-.387 1.406.204.142.428.259.5.259.2 0 .795-.643.795-.86 0-.333-.533-.804-.908-.804m8.487 0c-.778 0-1.039.949-.386 1.406.203.142.428.259.499.259.2 0 .795-.643.795-.86 0-.333-.533-.804-.908-.804m26.626 0c-.762 0-1.034.77-.472 1.332.4.4.485.407.961.074.7-.49.382-1.405-.49-1.405m-92.79.009a.97.97 0 0 0-.698.253c-.35.35-.33.67.072 1.07.404.405.629.417 1.027.057.347-.314.398-.895.104-1.189-.122-.122-.308-.185-.505-.191m26.5 0a.97.97 0 0 0-.697.253c-.35.35-.33.67.071 1.07.405.405.63.417 1.027.057.348-.314.4-.895.105-1.189-.122-.122-.309-.185-.505-.191m-53.286.003a.7.7 0 0 0-.535.188c-.318.318-.232.924.17 1.206.204.142.429.259.5.259.22 0 .795-.653.795-.903 0-.42-.484-.737-.93-.75m104.176.015h-.059a.64.64 0 0 0-.27.078.854.854 0 0 0-.358 1.17c.204.382.977.465 1.302.14.488-.488-.015-1.365-.615-1.388m-82.312.057c-.481 0-.601.077-.741.475-.144.409-.113.52.222.79.214.174.448.316.52.316.07 0 .304-.142.518-.315.336-.272.367-.382.223-.79-.14-.4-.26-.476-.742-.476m22.301 0c-.481 0-.6.077-.741.475-.144.409-.113.52.222.79.215.174.448.316.52.316.07 0 .304-.142.518-.315.336-.272.367-.382.223-.79-.14-.4-.26-.476-.742-.476m-39.93 1.933c-.14 0-.263.1-.476.313-.4.401-.422.72-.072 1.07.31.31.923.342 1.203.062.318-.317.233-.923-.17-1.205-.223-.157-.36-.238-.484-.24m15.444 0c-.14 0-.264.1-.477.313-.401.401-.422.72-.072 1.07.31.31.923.342 1.203.062.318-.317.232-.923-.17-1.205-.223-.157-.36-.238-.484-.24m6.958 0c-.14 0-.265.1-.477.313-.401.401-.422.72-.072 1.07.31.31.923.342 1.203.062.318-.317.232-.923-.17-1.205-.223-.157-.36-.238-.484-.24m26.5 0c-.14 0-.264.1-.477.313-.4.401-.421.72-.07 1.07.31.31.922.342 1.202.062.318-.317.232-.923-.17-1.205-.223-.157-.36-.238-.484-.24m-50.958.017c-.276 0-.55.175-.712.53-.138.303-.123.474.067.745.136.194.425.352.644.352.56 0 .943-.587.714-1.091-.162-.356-.438-.535-.713-.536m15.443 0c-.276 0-.551.175-.712.53-.139.303-.123.474.067.745.136.194.425.352.644.352.559 0 .943-.587.714-1.091-.162-.356-.438-.535-.713-.536m68.972.004q-.09 0-.193.033c-.578.183-.773.702-.45 1.196.333.507 1.015.485 1.364-.044.211-.32.195-.403-.157-.812-.223-.26-.382-.37-.564-.373m15.46 0q-.09 0-.194.033c-.578.183-.773.702-.449 1.196.333.508 1.014.485 1.364-.044.21-.32.194-.403-.158-.812-.223-.26-.381-.37-.564-.373m15.444 0q-.09 0-.193.033c-.578.183-.773.702-.449 1.196.332.508 1.014.485 1.363-.044.211-.32.195-.403-.157-.812-.223-.26-.382-.37-.564-.373m-111.077.004c-.111 0-.223.064-.416.19-.445.292-.552.895-.216 1.23.257.258 1.007.258 1.265 0 .335-.335.23-.938-.217-1.23-.192-.126-.304-.19-.416-.19m37.744 0c-.111 0-.223.064-.416.19-.445.292-.552.895-.216 1.23.257.258 1.007.258 1.265 0 .335-.335.23-.938-.217-1.23-.192-.126-.304-.19-.416-.19m31.404 0c-.111 0-.223.064-.416.19-.446.292-.551.895-.216 1.23.316.317 1.097.243 1.292-.122.272-.508.205-.814-.244-1.108-.192-.126-.304-.19-.416-.19m55.202.006a.6.6 0 0 0-.192.03c-.554.175-.749.701-.435 1.18.285.434.89.536 1.222.204.471-.47.01-1.406-.595-1.414m-68.54.007a.7.7 0 0 0-.449.191c-.373.338-.436.913-.134 1.216.325.324 1.098.242 1.302-.14.33-.617-.174-1.283-.718-1.267m15.453 0a.7.7 0 0 0-.45.191c-.373.338-.436.913-.134 1.216.325.324 1.098.242 1.302-.14.33-.617-.174-1.283-.718-1.267m22.265 0a.7.7 0 0 0-.45.191c-.373.338-.436.913-.133 1.216.324.324 1.097.242 1.301-.14.33-.617-.174-1.283-.718-1.267m15.444 0a.7.7 0 0 0-.449.191c-.373.338-.436.913-.134 1.216.325.324 1.098.242 1.302-.14.33-.617-.174-1.283-.719-1.267m13.295 0a.7.7 0 0 0-.45.191c-.373.338-.436.913-.133 1.216.324.324 1.097.242 1.301-.14.33-.617-.174-1.283-.718-1.267m-128.616.02c-.596.03-1.093.9-.607 1.387.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m8.487 0c-.596.03-1.093.9-.607 1.387.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m6.956 0c-.596.03-1.093.9-.607 1.387.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m42.465 0a.63.63 0 0 0-.336.077.854.854 0 0 0-.359 1.17c.204.382.977.465 1.301.14.486-.486-.01-1.357-.606-1.388m8.487 0a.63.63 0 0 0-.336.077.854.854 0 0 0-.359 1.17c.205.382.977.465 1.302.14.485-.486-.01-1.357-.607-1.388m6.964 0a.63.63 0 0 0-.336.077.854.854 0 0 0-.358 1.17c.204.382.977.465 1.301.14.486-.486-.01-1.357-.607-1.388m15.294 0a.63.63 0 0 0-.337.077.854.854 0 0 0-.358 1.17c.204.382.977.465 1.301.14.486-.486-.01-1.357-.606-1.388m2.112 0c-.597.03-1.093.9-.607 1.387.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078m15.46 0c-.597.03-1.093.9-.607 1.387.11.11.406.2.66.2.832 0 1.04-1.105.282-1.51a.64.64 0 0 0-.336-.078m4.845 0a.63.63 0 0 0-.336.077.854.854 0 0 0-.359 1.17c.204.382.977.465 1.301.14.486-.486-.01-1.357-.606-1.388m2.112 0c-.597.03-1.093.9-.607 1.387.11.11.407.2.66.2.833 0 1.04-1.105.283-1.51a.64.64 0 0 0-.336-.078" transform="translate(-239.14 -337.688)"/></svg>
|
||
</div>
|
||
<h2>WiFi Settings</h2>
|
||
<label for="ssid">SSID</label>
|
||
<input type="text" id="ssid" name="ssid" required />
|
||
<label for="password">Password</label>
|
||
<div style="position: relative;">
|
||
<input type="password" id="password" name="password" required />
|
||
<label style="display: block; font-size: 0.8rem; color: #aaa; margin-top: 0.25rem;">
|
||
<input type="checkbox" id="togglePassword" style="margin-right: 0.3rem;" />
|
||
Show Password
|
||
</label>
|
||
</div>
|
||
<h2>Weather Settings</h2>
|
||
<label for="openWeatherApiKey">OpenWeather API Key</label>
|
||
<input type="text" id="openWeatherApiKey" name="openWeatherApiKey" />
|
||
<div class="form-row two-col">
|
||
<div>
|
||
<label for="openWeatherCity">City</label>
|
||
<input type="text" id="openWeatherCity" name="openWeatherCity" />
|
||
</div>
|
||
<div>
|
||
<label for="openWeatherCountry">Country Code</label>
|
||
<input type="text" id="openWeatherCountry" name="openWeatherCountry" maxlength="2" />
|
||
</div>
|
||
</div>
|
||
<label for="weatherUnits">Temperature Units</label>
|
||
<select id="weatherUnits" name="weatherUnits">
|
||
<option value="metric">Metric (°C)</option>
|
||
<option value="imperial">Imperial (°F)</option>
|
||
<option value="standard">Standard (K)</option>
|
||
</select>
|
||
|
||
<h2>Clock Settings</h2>
|
||
<label for="utcOffsetInHours">UTC Offset (default +09:00 for Japan)</label>
|
||
<select id="utcOffsetInHours" name="utcOffsetInHours" required>
|
||
<option value="-12">−12:00 United States (Baker Island)</option>
|
||
<option value="-11">−11:00 American Samoa, Niue</option>
|
||
<option value="-10">−10:00 United States (Hawaii), French Polynesia</option>
|
||
<option value="-9.5">−09:30 French Polynesia (Marquesas Islands)</option>
|
||
<option value="-9">−09:00 United States (Alaska)</option>
|
||
<option value="-8">−08:00 United States (California), Canada (British Columbia)</option>
|
||
<option value="-7">−07:00 United States (Arizona), Mexico</option>
|
||
<option value="-6">−06:00 United States (Central), Guatemala, Honduras</option>
|
||
<option value="-5">−05:00 United States (Eastern), Colombia, Peru, Cuba</option>
|
||
<option value="-4.5">−04:30 Venezuela</option>
|
||
<option value="-4">−04:00 Bolivia, Paraguay, Canada (Atlantic)</option>
|
||
<option value="-3.5">−03:30 Canada (Newfoundland)</option>
|
||
<option value="-3">−03:00 Argentina, Brazil (East), Uruguay</option>
|
||
<option value="-2">−02:00 South Georgia & South Sandwich Islands</option>
|
||
<option value="-1">−01:00 Cape Verde, Azores (Portugal)</option>
|
||
<option value="0">±00:00 United Kingdom, Ireland, Portugal</option>
|
||
<option value="1">+01:00 Germany, France, Spain, Nigeria</option>
|
||
<option value="2">+02:00 South Africa, Egypt, Greece</option>
|
||
<option value="3">+03:00 Russia (West), Saudi Arabia, Kenya</option>
|
||
<option value="3.5">+03:30 Iran</option>
|
||
<option value="4">+04:00 United Arab Emirates, Azerbaijan</option>
|
||
<option value="4.5">+04:30 Afghanistan</option>
|
||
<option value="5">+05:00 Pakistan, Uzbekistan</option>
|
||
<option value="5.5">+05:30 India, Sri Lanka</option>
|
||
<option value="5.75">+05:45 Nepal</option>
|
||
<option value="6">+06:00 Bangladesh, Kazakhstan (East)</option>
|
||
<option value="6.5">+06:30 Myanmar</option>
|
||
<option value="7">+07:00 Thailand, Vietnam, Indonesia (West)</option>
|
||
<option value="8">+08:00 China, Malaysia, Singapore, Australia (West)</option>
|
||
<option value="8.75">+08:45 Australia (Eucla)</option>
|
||
<option value="9">+09:00 Japan, South Korea</option>
|
||
<option value="9.5">+09:30 Australia (Northern Territory, South Australia)</option>
|
||
<option value="10">+10:00 Australia (Queensland, New South Wales), Papua New Guinea</option>
|
||
<option value="10.5">+10:30 Australia (Lord Howe Island)</option>
|
||
<option value="11">+11:00 Solomon Islands, New Caledonia</option>
|
||
<option value="12">+12:00 New Zealand, Fiji</option>
|
||
<option value="12.75">+12:45 New Zealand (Chatham Islands)</option>
|
||
<option value="13">+13:00 Tonga, Samoa</option>
|
||
<option value="14">+14:00 Kiribati (Line Islands)</option>
|
||
</select>
|
||
|
||
|
||
|
||
<div class="form-row two-col">
|
||
<div>
|
||
<label for="clockDuration">Clock Duration</label>
|
||
<input type="number" id="clockDuration" name="clockDuration" min="1" required />
|
||
<label style="display: block; font-size: 0.8rem; color: #aaa; margin-top: 0.25rem;">(Seconds)</label>
|
||
</div>
|
||
<div>
|
||
<label for="weatherDuration">Weather Duration</label>
|
||
<input type="number" id="weatherDuration" name="weatherDuration" min="1" required />
|
||
<label style="display: block; font-size: 0.8rem; color: #aaa; margin-top: 0.25rem;">(Seconds)</label>
|
||
</div>
|
||
</div>
|
||
<br><br><br>
|
||
<input type="submit" class="primary-button" value="Save Settings">
|
||
</form>
|
||
|
||
<div class="footer">
|
||
Project by: <a href="https://www.instagram.com/mfactory.osaka" target="_blank" rel="noopener noreferrer">M-Factory</a>
|
||
</div>
|
||
|
||
<div id="savingMessage"></div>
|
||
|
||
<script>
|
||
let isSaving = false;
|
||
let isAPMode = false;
|
||
|
||
window.onbeforeunload = function () {
|
||
if (isSaving) {
|
||
return "Settings are being saved. Leaving now may interrupt the process.";
|
||
}
|
||
};
|
||
|
||
window.onload = function () {
|
||
fetch('/config.json')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
isAPMode = (data.mode === "ap");
|
||
// console.log("✅ Config data:", data);
|
||
if (isAPMode) {
|
||
document.querySelector('.footer').style.display = 'none';
|
||
}
|
||
|
||
document.getElementById('ssid').value = data.ssid || '';
|
||
document.getElementById('password').value = data.password || '';
|
||
document.getElementById('openWeatherApiKey').value = data.openWeatherApiKey || '';
|
||
document.getElementById('openWeatherCity').value = data.openWeatherCity || '';
|
||
document.getElementById('openWeatherCountry').value = data.openWeatherCountry || '';
|
||
document.getElementById('weatherUnits').value = data.weatherUnits || 'metric';
|
||
document.getElementById('clockDuration').value = (data.clockDuration || 10000) / 1000;
|
||
document.getElementById('weatherDuration').value = (data.weatherDuration || 5000) / 1000;
|
||
document.getElementById('utcOffsetInHours').value = (data.utcOffsetInSeconds || 0) / 3600;
|
||
|
||
})
|
||
.catch(err => {
|
||
console.error('Failed to load config:', err);
|
||
showSavingModal("");
|
||
updateSavingModal("⚠️ Failed to load configuration.", false);
|
||
document.getElementById('restoreButton').style.display = 'inline-block';
|
||
});
|
||
};
|
||
|
||
function submitConfig(event) {
|
||
event.preventDefault();
|
||
isSaving = true;
|
||
|
||
const form = document.getElementById('configForm');
|
||
const formData = new FormData(form);
|
||
|
||
const clockDuration = parseInt(formData.get('clockDuration')) * 1000;
|
||
const weatherDuration = parseInt(formData.get('weatherDuration')) * 1000;
|
||
formData.set('clockDuration', clockDuration);
|
||
formData.set('weatherDuration', weatherDuration);
|
||
|
||
const utcOffsetInHours = parseFloat(formData.get('utcOffsetInHours')) || 0;
|
||
formData.set('utcOffsetInSeconds', Math.round(utcOffsetInHours * 3600));
|
||
formData.delete('utcOffsetInHours'); // backend expects only utcOffsetInSeconds
|
||
|
||
const params = new URLSearchParams();
|
||
for (const pair of formData.entries()) {
|
||
params.append(pair[0], pair[1]);
|
||
}
|
||
|
||
showSavingModal("Saving...");
|
||
|
||
fetch('/save', {
|
||
method: 'POST',
|
||
body: params
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
return response.json().then(json => {
|
||
throw new Error(`Server error ${response.status}: ${json.error}`);
|
||
});
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(json => {
|
||
isSaving = false;
|
||
if (isAPMode) {
|
||
updateSavingModal("✅ Settings saved successfully!<br><br><br>Rebooting the device now... ", false);
|
||
|
||
setTimeout(() => {
|
||
document.getElementById('configForm').style.display = 'none';
|
||
// Optionally update modal text:
|
||
updateSavingModal("✅ All done!<br><br><br>You can now close this tab safely.", false);
|
||
}, 5000);
|
||
return;
|
||
|
||
} else {
|
||
updateSavingModal("✅ Configuration saved successfully.<br><br><br>Device will reboot", false);
|
||
setTimeout(() => location.reload(), 3000);
|
||
}
|
||
})
|
||
.catch(err => {
|
||
isSaving = false;
|
||
|
||
if (isAPMode && err.message.includes("Failed to fetch")) {
|
||
console.warn("Expected disconnect in AP mode after reboot.");
|
||
|
||
// Ensure modal is visible
|
||
showSavingModal(""); // Create or show modal if needed
|
||
updateSavingModal("✅ Settings saved successfully!<br><br><br>Rebooting the device now... ", false);
|
||
|
||
setTimeout(() => {
|
||
document.getElementById('configForm').style.display = 'none';
|
||
// Optionally update modal text:
|
||
updateSavingModal("✅ All done!<br><br><br>You can now close this tab safely.", false);
|
||
}, 5000);
|
||
return;
|
||
}
|
||
|
||
console.error('Save error:', err);
|
||
let friendlyMessage = "Something went wrong while saving the configuration.";
|
||
if (err.message.includes("Failed to fetch")) {
|
||
friendlyMessage = "⚠️ Cannot connect to the device.<br>Is it powered on and connected?";
|
||
}
|
||
|
||
updateSavingModal(`${friendlyMessage}<br><br>Details: ${err.message}`, false);
|
||
const restoreBtn = document.getElementById('restoreButton');
|
||
restoreBtn.textContent = "Reload Page";
|
||
restoreBtn.onclick = () => location.reload();
|
||
restoreBtn.style.display = 'inline-block';
|
||
});
|
||
|
||
|
||
|
||
}
|
||
|
||
function showSavingModal(message) {
|
||
let modal = document.getElementById('savingModal');
|
||
if (!modal) {
|
||
modal = document.createElement('div');
|
||
modal.id = 'savingModal';
|
||
modal.innerHTML = `
|
||
<div id="savingModalContent">
|
||
<div class="spinner"></div>
|
||
<div id="savingModalText">${message}</div>
|
||
</div>
|
||
`;
|
||
document.body.appendChild(modal);
|
||
} else {
|
||
document.getElementById('savingModalText').innerHTML = message;
|
||
document.querySelector('#savingModal .spinner').style.display = 'block';
|
||
}
|
||
modal.style.display = 'flex';
|
||
document.body.classList.add('modal-open');
|
||
}
|
||
|
||
function updateSavingModal(message, showSpinner = false) {
|
||
document.getElementById('savingModalText').innerHTML = message;
|
||
document.querySelector('#savingModal .spinner').style.display = showSpinner ? 'block' : 'none';
|
||
}
|
||
|
||
function restoreBackupConfig() {
|
||
showSavingModal("Restoring backup...");
|
||
document.getElementById('restoreButton').remove();
|
||
|
||
fetch('/restore', { method: 'POST' })
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error("Server returned an error");
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
updateSavingModal("✅ Backup restored! Reloading...");
|
||
setTimeout(() => location.reload(), 1500);
|
||
})
|
||
.catch(err => {
|
||
console.error("Restore error:", err);
|
||
updateSavingModal(`❌ Failed to restore backup: ${err.message}`, false);
|
||
});
|
||
}
|
||
|
||
// Show/hide password toggle
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
const passwordInput = document.getElementById("password");
|
||
const toggleCheckbox = document.getElementById("togglePassword");
|
||
|
||
toggleCheckbox.addEventListener("change", function () {
|
||
passwordInput.type = this.checked ? "text" : "password";
|
||
});
|
||
});
|
||
|
||
function hideSavingModal() {
|
||
const modal = document.getElementById('savingModal');
|
||
if (modal) {
|
||
modal.style.display = 'none';
|
||
document.body.classList.remove('modal-open');
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|