You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

392 lines
10 KiB
JavaScript

let menu_f = false;
let pin_id = null;
// ====================== VARS ======================
let screen = 'main';
let focused = null;
// ============== SCREEN ==============
async function show_screen(nscreen) {
spinArrows(false);
screen = nscreen;
document.body.dataset.screen = screen;
const $title = document.getElementsByClassName('header-title')[0];
const dev = hub.dev(focused);
if (dev) dev.fsStop();
switch (screen) {
case 'main':
$title.textContent = "GyverHub";
showCLI(false);
break;
case 'test':
$title.textContent = 'UI Test';
break;
case 'projects':
$title.textContent = lang.p_proj;
loadProjects();
break;
case 'ui':
$title.textContent = dev.info.name;
EL('controls').replaceChildren();
break;
case 'config':
$title.textContent = lang.config;
break;
case 'info':
$title.textContent = dev.info.name + '/info';
enterMenu('menu_info');
await show_info();
break;
case 'files':
$title.textContent = dev.info.name + '/fs';
EL('fs_upload').textContent = lang.fs_upload;
enterMenu('menu_fsbr');
display('fs_browser', dev.isModuleEnabled(Modules.FILES) ? 'block' : 'none');
display('fs_upload', dev.isModuleEnabled(Modules.UPLOAD) ? 'block' : 'none');
display('fs_create', dev.isModuleEnabled(Modules.CREATE) ? 'block' : 'none');
display('fs_format', dev.isModuleEnabled(Modules.FORMAT) ? 'flex' : 'none');
if (dev.isModuleEnabled(Modules.FILES)) {
EL('fsbr_inner').innerHTML = waiter();
await dev.updateFileList();
}
break;
case 'fsbr_edit':
$title.textContent = dev.info.name + '/fs';
enterMenu('menu_fsbr');
break;
case 'ota':
$title.textContent = dev.info.name + '/ota';
enterMenu('menu_ota');
const ota_t = '.' + dev.info.ota_t;
EL('ota_upload').accept = ota_t;
EL('ota_upload_fs').accept = ota_t;
EL('ota_url_f').value = "http://flash" + ota_t;
EL('ota_url_fs').value = "http://filesystem" + ota_t;
display('fs_otaf', dev.isModuleEnabled(Modules.OTA) ? 'block' : 'none');
display('fs_otaurl', dev.isModuleEnabled(Modules.OTA_URL) ? 'block' : 'none');
break;
case 'dev_config':
$title.textContent = dev.info.name + '/cfg';
enterMenu('menu_cfg');
show_cfg();
break;
}
}
function show_cfg() {
const dev = hub.dev(focused);
EL('main_width').value = dev.info.main_width;
EL('info_cli_sw').checked = document.body.classList.contains('show-cli');
EL('info_trust').checked = dev.info.trust;
EL('plugin_css').value = dev.info.plugin_css;
EL('plugin_js').value = dev.info.plugin_js;
}
async function show_info() {
const dev = hub.dev(focused);
EL('info_id').textContent = focused;
EL('info_set').textContent = dev.info.prefix + '/' + focused + '/ID/set/*';
EL('info_read').textContent = dev.info.prefix + '/' + focused + '/ID/read/*';
EL('info_get').textContent = dev.info.prefix + '/hub/' + focused + '/get/*';
EL('info_status').textContent = dev.info.prefix + '/hub/' + focused + '/status';
display('reboot_btn', dev.isModuleEnabled(Modules.REBOOT) ? 'block' : 'none');
display('info_topics', dev.isModuleEnabled(Modules.MQTT) ? 'block' : 'none');
EL('info_version').replaceChildren();
EL('info_net').replaceChildren();
EL('info_memory').replaceChildren();
EL('info_system').replaceChildren();
if (dev.isModuleEnabled(Modules.INFO)) {
const info = await dev.getInfo();
if (info) showInfo(info);
}
}
// =========== HANDLERS ===========
async function refresh_h() {
if (!focused) {
discover();
return
}
const dev = hub.dev(focused);
switch (screen) {
case "ui":
await dev.updateUi();
break;
case "files":
await dev.updateFileList();
break;
case "info":
const info = await dev.getInfo();
if (info) showInfo(info);
break;
}
}
async function back_h() {
if (focused) {
const dev = hub.dev(focused);
dev.fsStop();
}
if (menu_f) {
menu_show(false);
return;
}
switch (screen) {
case 'ui':
close_device();
break;
case 'dev_config':
case 'info':
case 'files':
case 'ota':
enterMenu();
show_screen('ui');
hub.dev(focused).updateUi();
break;
case 'fsbr_edit':
show_screen('files');
break;
case 'config':
config_h();
break;
case 'projects':
case 'test':
show_screen('main');
break;
}
}
function config_h() {
if (screen == 'config') {
show_screen('main');
if (cfg_changed) {
save_cfg();
discover();
}
cfg_changed = false;
} else {
show_screen('config');
}
}
async function manual_ip_h(ip) {
let device;
try {
device = await hub.http.discover_ip(ip);
} catch (e) {
showPopupError(getError(e));
return;
}
save_cfg();
show_screen('main');
if (device) device_h(device.info.id);
}
function update_ip_h() {
getLocalIP(false);
}
function menu_h() {
menu_show(!menu_f);
}
function devlink_h() {
copyClip(devLink());
}
function qr_h() {
/*@[if_not_target:esp]*/
const $qr = document.createElement('div');
new QRCode($qr, devLink());
$qr.style.margin = '0 auto';
asyncShowQr($qr);
/*@/[if_not_target:esp]*/
}
function devLink() {
let qs = window.location.origin + window.location.pathname + '?';
const info = hub.dev(focused).info;
["id", "prefix", "ip", "http_port"].forEach(x => { if (info[x]) qs += `${x}=${info[x]}&`; });
return qs.slice(0, -1);
}
function ui_width_h(el) {
hub.dev(focused).info.main_width = el.value;
}
function ui_plugin_css_h(el) {
hub.dev(focused).info.plugin_css = el.value;
addDOM('device_css', 'style', el.value, EL('plugins'));
}
function ui_plugin_js_h(el) {
hub.dev(focused).info.plugin_js = el.value;
addDOM('device_js', 'script', el.value, EL('plugins'));
}
// ============== MENU =============
function menu_show(state) {
menu_f = state;
const cl = EL('menu').classList;
if (menu_f) cl.add('menu_show');
else cl.remove('menu_show');
EL('icon_menu').textContent = menu_f ? '' : '';
display('menu_overlay', menu_f ? 'block' : 'none');
}
function updateSystemMenu() {
const dev = hub.dev(focused);
EL('menu').append(createElement(null, {
type: 'div',
class: "menu_item menu_cfg",
text: lang.m_config,
events: {
click: () => show_screen('dev_config')
}
}));
EL('menu').append(createElement(null, {
type: 'div',
class: "menu_item menu_info",
text: lang.m_info,
events: {
click: () => show_screen('info')
}
}));
if (dev.isModuleEnabled(Modules.FILES)) {
EL('menu').append(createElement(null, {
type: 'div',
class: "menu_item menu_fsbr",
text: lang.m_files,
events: {
click: () => show_screen('files')
}
}));
}
if (dev.isModuleEnabled(Modules.OTA) || dev.isModuleEnabled(Modules.OTA_URL)) {
EL('menu').append(createElement(null, {
type: 'div',
class: "menu_item menu_ota",
text: lang.m_ota,
events: {
click: () => show_screen('ota')
}
}));
}
}
function enterMenu(sel = null) {
menu_show(false);
for (const $i of document.getElementById('menu').children)
$i.classList.remove('menu_act');
if (sel !== null)
document.querySelector('.menu_item.' + sel).classList.add('menu_act');
}
// ============== DEVICE =============
async function device_h(id) {
const dev = hub.dev(id);
if (!dev || !dev.isConnected()) return;
if (!dev.info.api_v || dev.info.api_v != GyverHub.api_v) asyncAlert(lang.api_mis);
if (dev.info.pin && !dev.granted) {
if (!await asyncAskPin(lang.dev_pin + dev.info.name, dev.info.pin, true)) {
return false;
}
dev.granted = true;
}
/*@[if_not_target:esp]*/
await checkUpdates(dev);
/*@/[if_not_target:esp]*/
focused = id;
EL('menu').replaceChildren();
updateSystemMenu();
EL('conn').textContent = dev.getConnection().name;
addDOM('device_css', 'style', dev.info.plugin_css, EL('plugins'));
addDOM('device_js', 'script', dev.info.plugin_js, EL('plugins'));
show_screen('ui');
dev.focus();
}
function close_device() {
if (renderer) renderer.close();
renderer = null;
const $root = document.getElementById('controls');
$root.replaceChildren();
EL('plugins').replaceChildren();
EL('ota_label').replaceChildren();
errorBar(false);
hub.dev(focused).unfocus();
focused = null;
show_screen('main');
}
async function delete_h(id) {
if (await asyncConfirm(lang.delete + ' ' + id + '?')) {
hub.deleteDevice(id);
EL(`device#${id}`).remove();
}
}
function dev_up_h(id) {
hub.moveDevice(id, -1);
render_devices();
}
function dev_down_h(id) {
hub.moveDevice(id, 1);
render_devices();
}
async function trust_dev_h() {
const v = EL('info_trust').checked;
if (v && !await asyncConfirm(lang.dev_trust_warning)) {
EL('info_trust').checked = false;
return;
}
hub.dev(focused).info.trust = v;
}
// ============== CLI =============
function showCLI(v) {
if (v) document.body.classList.add('show-cli');
else document.body.classList.remove('show-cli');
if (v) EL('cli_input').focus();
EL('info_cli_sw').checked = v;
}
function printCLI(text, color) {
if (document.body.classList.contains('show-cli')) {
if (EL('cli').innerHTML) EL('cli').innerHTML += '\n';
let st = color ? `style="color:${intToCol(color)}"` : '';
EL('cli').innerHTML += `<span ${st}>${text}</span>`;
EL('cli').scrollTop = EL('cli').scrollHeight;
}
}
function toggleCLI() {
EL('cli').replaceChildren();
EL('cli_input').value = "";
showCLI(!document.body.classList.contains('show-cli'));
}
function checkCLI(event) {
if (event.key == 'Enter') sendCLI();
}
async function sendCLI() {
await hub.dev(focused).sendCli(EL('cli_input').value);
EL('cli').innerHTML += "\n>" + EL('cli_input').value;
EL('cli').scrollTop = EL('cli').scrollHeight;
EL('cli_input').value = "";
}
// =========== PIN ===========
function make_pin(arg) {
if (arg.value.length >= 4) arg.value = arg.value.hashCode();
else arg.value = '';
}
function check_type(arg) {
if (arg.value.length > 0) {
let c = arg.value[arg.value.length - 1];
if (c < '0' || c > '9') arg.value = arg.value.slice(0, -1);
}
}