import "./style.css";
import { initMenus } from "./menu";
let isConsoleExpanded = false;
let isAutoScroll = true;
let consoleContentList = [];
let consoleContent;
let isFileSystemExpanded = true;
let isFirmwareUpdateExpanded = false;
let consolePanel;
let fileSystem;
let firmware;
let consoleHeader;
let consoleBody;
let fileSystemHeader;
let fileSystemBody;
let filecontentFooter;
let firmwareHeader;
let firmwareBody;
let filesInput;
let fwInput;
let filesButton;
let firmwareButton;
let refreshButton;
let createDirButton;
let message;
let messageLimited;
let websocketStarted = false;
let wsSource;
let wsMsg = "";
let logOff = false;
let pageId = "";
let currentPath = "/";
const version = "3.0.0.a5";
let xmlhttpupload;
let prgfiletext;
let prgfile;
let uploadType = 0;
let restartTime;
let loginLink;
let loginModal;
let loginUser = "";
let loginMsg;
let fspath="/files";
let hostpath="/";
window.onload = function () {
consolePanel = document.getElementById("consolePanel");
fileSystem = document.getElementById("fileSystem");
firmware = document.getElementById("firmware");
consoleHeader = document.getElementById("consoleHeader");
consoleBody = document.getElementById("consoleBody");
fileSystemHeader = document.getElementById("fileSystemHeader");
fileSystemBody = document.getElementById("fileSystemBody");
filecontentFooter = document.getElementById("filecontentFooter");
firmwareHeader = document.getElementById("firmwareHeader");
firmwareBody = document.getElementById("firmwareBody");
consoleContent = document.getElementById("consoleContent");
fwInput = document.getElementById("filefw");
filesInput = document.getElementById("files");
message = document.getElementById("MSG");
messageLimited = document.getElementById("MSGLimited");
prgfiletext = document.getElementById("prgfiletext");
prgfile = document.getElementById("prgfile");
document.getElementById("cmdBtn").addEventListener("click", function () {
let input = document.getElementById("customCmdTxt");
if (input.value.trim().length == 0) return;
let url = new URL("http://" + window.location.host + "/command");
url.searchParams.append("cmd", input.value.trim());
httpGet(url, processCmdJson);
consoleContentUpdate(
"" + input.value.trim() + "\n"
);
input.value = "";
});
document
.getElementById("loginInput")
.addEventListener("keydown", function (event) {
if (event.keyCode === 13) {
document.getElementById("passwordInput").focus();
}
});
document
.getElementById("passwordInput")
.addEventListener("keydown", function (event) {
if (event.keyCode === 13) {
document.getElementById("loginbutton").click();
}
});
document
.getElementById("customCmdTxt")
.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
document.getElementById("cmdBtn").click();
}
});
consoleHeader.addEventListener("click", function () {
isConsoleExpanded = !isConsoleExpanded;
if (isConsoleExpanded) consoleBody.style.display = "block";
else consoleBody.style.display = "none";
});
loginMsg = document.getElementById("loginMsg");
loginLink = document.getElementById("loginLink");
loginModal = document.getElementById("loginpage");
loginLink.addEventListener("click", function () {
loginModal.classList.remove("hide");
});
document
.getElementById("disconnectbutton")
.addEventListener("click", function () {
document.getElementById("loginInput").value = "";
document.getElementById("loginbutton").click();
});
document.getElementById("loginbutton").addEventListener("click", function () {
loginModal.classList.add("hide");
let user = document.getElementById("loginInput").value.trim();
loginUser = user;
let password = document.getElementById("passwordInput").value.trim();
let url = new URL("http://" + window.location.host + "/login");
url.searchParams.append("USER", user);
url.searchParams.append("PASSWORD", password);
url.searchParams.append("SUBMIT", "yes");
let xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status != 200) {
if (xmlhttp.status == 401) {
handle401();
} else {
console.log(xmlhttp.status);
ErrorMSG(
"Error: board does not answered properly " + xmlhttp.status
);
}
} else {
getFWData();
}
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
document.getElementById("passwordInput").value = "";
});
refreshButton = document.getElementById("refresh");
refreshButton.addEventListener("click", function () {
SendFileCommand("list", "all");
});
firmwareButton = document.getElementById("uploapFW");
firmwareButton.addEventListener("click", function () {
prgupdatetext.innerHTML = "";
fwInput.click();
});
filesButton = document.getElementById("uploadFiles");
filesButton.innerHTML = fileIcon(true);
filesButton.addEventListener("click", function () {
filesInput.click();
});
fwInput.addEventListener("change", function () {
if (fwInput.value) {
if (!confirm("Confirm Firmware Update ?")) {
console.log("abort");
fwInput.value = "";
return;
}
uploadFirmware();
}
});
filesInput.addEventListener("change", function () {
console.log("upload");
if (filesInput.value) {
uploadFiles();
}
});
document
.getElementById("monitor_enable_autoscroll")
.addEventListener("click", function () {
if (document.getElementById("monitor_enable_autoscroll").checked) {
isAutoScroll = true;
autoscroll();
} else {
isAutoScroll = false;
}
});
consoleBody.style.display = "none";
fileSystemHeader.addEventListener("click", function () {
isFileSystemExpanded = !isFileSystemExpanded;
if (isFileSystemExpanded) {
fileSystemBody.style.display = "block";
fileSystemBody.scrollIntoView();
} else {
fileSystemBody.style.display = "none";
}
});
firmwareHeader.addEventListener("click", function () {
isFirmwareUpdateExpanded = !isFirmwareUpdateExpanded;
if (isFirmwareUpdateExpanded) {
firmwareBody.style.display = "block";
firmwareBody.scrollIntoView();
} else firmwareBody.style.display = "none";
});
firmwareBody.style.display = "none";
createDirButton = document.getElementById("createdir");
createDirButton.innerHTML = dirIcon(true);
createDirButton.addEventListener("click", function () {
let filename = prompt("Directory name", "");
if (filename != null && filename.trim().length > 0) {
SendFileCommand("createdir", filename.trim());
}
});
getFWData();
initMenus();
};
function handle401() {
loginModal.classList.remove("hide");
loginLink.classList.remove("hide");
if (loginUser.length > 0) {
loginMsg.classList.remove("hide");
} else {
loginMsg.classList.add("hide");
}
firmware.classList.add("hide");
fileSystem.classList.add("hide");
consolePanel.classList.add("hide");
}
function padNumber(num, size) {
let s = num.toString().padStart(size, "0");
return s;
}
function getPCTime() {
let d = new Date();
return (
d.getFullYear() +
"-" +
padNumber(d.getMonth() + 1, 2) +
"-" +
padNumber(d.getDate(), 2) +
"-" +
padNumber(d.getHours(), 2) +
"-" +
padNumber(d.getMinutes(), 2) +
"-" +
padNumber(d.getSeconds(), 2)
);
}
function isLimitedEnvironment(wifiMode) {
let sitesList = [
"clients3.google.com", //Android Captive Portal Detection
"connectivitycheck.",
//Apple iPhone, iPad with iOS 6 Captive Portal Detection
"apple.com",
".akamaitechnologies.com",
//Apple iPhone, iPad with iOS 7, 8, 9 and recent versions of OS X
"www.appleiphonecell.com",
"www.itools.info",
"www.ibook.info",
"www.airport.us",
"www.thinkdifferent.us",
".akamaiedge.net",
//Windows
".msftncsi.com",
"microsoft.com",
];
if (wifiMode != "AP") return false;
for (let i = 0; i < sitesList.length; i++) {
if (document.location.host.indexOf(sitesList[i]) != -1) return true;
}
return false;
}
function autoscroll() {
if (isAutoScroll) consoleContent.scrollTop = consoleContent.scrollHeight;
}
function consoleContentUpdate(message) {
if (message) {
consoleContentList = consoleContentList.concat(message);
consoleContentList = consoleContentList.slice(-300);
let output = "";
for (let i = 0; i < consoleContentList.length; i++) {
output += consoleContentList[i];
}
document.getElementById("consoleContent").innerHTML = output;
autoscroll();
}
}
function processCmdJson(text) {
let json;
try {
json = JSON.parse(text);
consoleContentUpdate(JSON.stringify(json, null, " ") + "\n");
} catch (e) {
consoleContentUpdate(text + "\n");
}
}
function processFWJson(text) {
let json;
try {
json = JSON.parse(text);
} catch (e) {
ErrorMSG("Error: json data are incorrect!
" + text);
consoleContentUpdate(text);
return;
}
if (!json.status || !json.cmd || !json.data) {
ErrorMSG("Wrong version of webUI");
consoleContentUpdate(text);
return;
}
json = json.data;
if (json.FWVersion) {
let verLink = document.getElementById("verLink");
verLink.innerHTML = "v" + json.FWVersion;
verLink.addEventListener("click", function () {
let url = new URL("http://" + window.location.host + "/config");
window.open(url, "_blank");
});
} else {
ErrorMSG(
"Error: json data are incorrect!
" +
JSON.stringify(json, null, "
")
);
return;
}
document.getElementById("espLink").addEventListener("click", function () {
let url = new URL("http://" + window.location.host);
window.open(url);
});
consolePanel.classList.remove("hide");
if ((json.FlashFileSystem && json.FlashFileSystem != "none")||(json.SDConnection && json.SDConnection != "none")){
fileSystem.classList.remove("hide");
if (json.FlashFileSystem && json.FlashFileSystem == "none"){
fspath="/sdfiles";
}
}
if (json.WebUpdate == "Enabled") firmware.classList.remove("hide");
hostpath = json.HostPath;
if (json.WiFiMode && json.WebSocketIP) {
if (isLimitedEnvironment(json.WiFiMode)) {
let address =
"http://" +
json.WebSocketIP +
(window.location.port == 80 ? "" : ":" + window.location.port);
InfoMSGLimited(
"It seems you are in limited environment,
please open a browser using
" +
address +
"
to get all features working"
);
}
}
if (json.Hostname) document.title = json.Hostname;
startSocket(json.WebSocketIP, json.WebSocketPort, json.WebCommunication, json.WebSocketSubProtocol);
SendFileCommand("list", "all");
}
function startSocket(ip, port, sync, protocol) {
if (websocketStarted) {
wsSource.close();
}
wsSource = new WebSocket(
"ws://" + ip + ":" + port + (sync == "Asynchronous" ? "/ws" : ""),
[protocol]
);
wsSource.binaryType = "arraybuffer";
wsSource.onopen = function (e) {
websocketStarted = true;
};
wsSource.onclose = function (e) {
websocketStarted = false;
//seems sometimes it disconnect so wait 3s and reconnect
//if it is not a log off
if (!logOff)
setTimeout(() => {
startSocket(ip, port, sync, protocol);
}, 3000);
};
wsSource.onerror = function (e) {
ErrorMSG("Error: websocket error!
" );
console.log("Error: websocket error!");
};
wsSource.onmessage = function (e) {
let msg = "";
//bin
if (e.data instanceof ArrayBuffer) {
let bytes = new Uint8Array(e.data);
for (let i = 0; i < bytes.length; i++) {
msg += String.fromCharCode(bytes[i]);
if (bytes[i] == 10 || bytes[i] == 13) {
wsMsg += msg;
consoleContentUpdate(wsMsg);
wsMsg = "";
msg = "";
}
}
wsMsg += msg;
} else {
msg = e.data;
let tval = msg.split(":");
if (tval.length >= 2) {
if (tval[0] == "currentID") {
pageId = tval[1];
}
if (tval[0] == "activeID") {
if (pageId != tval[1]) {
logOff = true;
wsSource.close();
InfoMSG(
"
It seems you are connect from another location, you are now disconnected."
);
document.title = document.title + "(disconnected)";
consolePanel.classList.add("hide");
firmware.classList.add("hide");
fileSystem.classList.add("hide");
document.getElementById("verLink").classList.add("disabled");
loginModal.classList.add("hide");
loginUser = "";
document.getElementById("loginInput").value = "";
document.getElementById("passwordInput").value = "";
document.cookie = "";
}
}
if (tval[0] == "ERROR") {
xmlhttpupload.abort();
uploadError(tval[2], tval[1]);
}
}
}
};
}
function uploadError(msg, nb) {
let status = "Upload failed";
if (nb != 0 && typeof nb != "undefined") {
status = msg + "(" + nb + ")";
}
alert(status + "!");
if (uploadType == 1) {
let currentstatus = filecontentFooter.innerHTML;
if (currentstatus.length > 0) {
filecontentFooter.innerHTML =
"Status: " +
status +
"  " +
currentstatus.substring(currentstatus.indexOf("|"));
} else {
filecontentFooter.innerHTML = status;
}
} else if (uploadType == 2) {
prgupdatetext.innerHTML = status;
}
//location.reload();
}
function ErrorMSG(msg) {
message.innerHTML = msg;
message.className = "text-error";
}
function InfoMSGLimited(msg) {
messageLimited.innerHTML = msg;
messageLimited.className = "text-error";
}
function InfoMSG(msg) {
message.innerHTML = msg;
message.className = "text-primary";
}
function getFWData() {
let url = new URL("http://" + window.location.host + "/command");
url.searchParams.append("cmd", "[ESP800]json=YES version="+version+" time=" + getPCTime());
httpGet(url, processFWJson);
}
function SendFileCommand(action, filename) {
let url = new URL("http://" + window.location.host + fspath);
url.searchParams.append("action", action);
url.searchParams.append("filename", filename);
url.searchParams.append("path", currentPath);
httpGet(url, dispatchFileStatus);
}
function trashIcon() {
return "";
}
function backIcon() {
return "";
}
function fileIcon(plus = false) {
return (
""
);
}
function dirIcon(plus = false) {
return (
""
);
}
function dispatchFileStatus(jsonresponse) {
let json;
let eventslisteners = [];
let showESP3Dbutton = false;
try {
json = JSON.parse(jsonresponse);
//ugly but code is smaller
filecontentFooter.innerHTML =
"Status: " +
json.status +
" | Total space: " +
json.total +
" | Used space: " +
json.used +
" | Occupation: " +
"