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.

762 lines
34 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// =========== MISC ===========
function add_device(device, dev) {
let icon = dev.icon;
/*@[if_target:esp]*/
if (icon.length) icon = '';
/*@/[if_target:esp]*/
EL('devices').innerHTML += `
<div class="device ${device.isConnected() ? '' : 'offline'}" id="device#${dev.id}" onclick="device_h('${dev.id}')" title="${dev.id} [${dev.prefix}]">
<div id="d_head#${dev.id}">
<div class="d_icon">
<span class="icon icon_min" id="icon#${dev.id}">${getIcon(icon) ?? ''}</span>
</div>
<div class="d_title">
<span class="d_name" id="name#${dev.id}">${dev.name}</span><sup class="conn_dev" id="SERIAL#${dev.id}">S</sup><sup class="conn_dev" id="BLE#${dev.id}">B</sup><sup class="conn_dev" id="HTTP#${dev.id}">W</sup><sup class="conn_dev" id="MQTT#${dev.id}">M</sup><sup class="conn_dev" id="TG#${dev.id}">T</sup>
</div>
</div>
<div id="d_cfg#${dev.id}" class="d_btn_cont">
<div class="icon d_btn_red" onclick="delete_h('${dev.id}');event.stopPropagation()"></div>
<div class="icon d_btn_green" onclick="dev_up_h('${dev.id}');event.stopPropagation()"></div>
<div class="icon d_btn_green" onclick="dev_down_h('${dev.id}');event.stopPropagation()"></div>
</div>
<span class="icon d_btn_cfg" onclick="dev_cfg_h('${dev.id}');event.stopPropagation()"></span>
</div>`;
EL('d_head#' + dev.id).style.display = device.cfg_flag ? 'none' : 'flex';
EL('d_cfg#' + dev.id).style.display = device.cfg_flag ? 'flex' : 'none';
}
function render_devices() {
EL('devices').replaceChildren();
for (const id of hub.getDeviceIds()) {
const dev = hub.dev(id);
add_device(dev, dev.info);
for (let connection of dev.active_connections) {
display(`${connection.name}#${dev.info.id}`, 'inline-block');
}
}
}
function dev_cfg_h(id) {
const dev = hub.dev(id);
dev.cfg_flag = !dev.cfg_flag;
EL('d_head#' + id).style.display = dev.cfg_flag ? 'none' : 'flex';
EL('d_cfg#' + id).style.display = dev.cfg_flag ? 'flex' : 'none';
}
// ============= UI =============
function errorBar(v) {
if (v) document.body.classList.add('connection-error');
else document.body.classList.remove('connection-error');
}
function spinArrows(val) {
if (val) EL('icon_refresh').classList.add('spinning');
else EL('icon_refresh').classList.remove('spinning');
}
// ============= CONNECTION =============
// mqtt
function mq_change(opened) {
display('mq_start', opened ? 'none' : 'inline-block');
display('mq_stop', opened ? 'inline-block' : 'none');
display('mqtt_ok', opened ? 'block' : 'none');
}
// bt
function bt_change(opened) {
display('bt_open', opened ? 'none' : 'inline-block');
display('bt_close', opened ? 'inline-block' : 'none');
display('bt_ok', opened ? 'block' : 'none');
}
// serial
function serial_change(opened) {
display('serial_open', opened ? 'none' : 'inline-block');
display('serial_close', opened ? 'inline-block' : 'none');
display('serial_ok', opened ? 'block' : 'none');
}
// telegram
function tg_change(opened) {
display('tg_start', opened ? 'none' : 'inline-block');
display('tg_stop', opened ? 'inline-block' : 'none');
display('tg_ok', opened ? 'block' : 'none');
}
// ============= INFO =============
function showInfo(info) {
function addInfo(el, label, value, title = '') {
EL(el).innerHTML += `
<div class="ui_row info">
<label>${label}</label>
<label title="${title}" class="info_label">${value}</label>
</div>`;
}
EL('info_version').replaceChildren();
EL('info_net').replaceChildren();
EL('info_memory').replaceChildren();
EL('info_system').replaceChildren();
for (const i in info.version) addInfo('info_version', i, info.version[i]);
for (const i in info.net) addInfo('info_net', i, info.net[i]);
for (const i in info.memory) {
if (typeof (info.memory[i]) === 'object') {
const used = info.memory[i][0];
const total = info.memory[i][1];
let mem = (used / 1024).toFixed(1) + ' KiB';
let title = used;
if (total) {
mem += ' [' + (used / total * 100).toFixed(0) + '%]';
title += ' of ' + total;
}
addInfo('info_memory', i, mem, `Used ${title} bytes`);
} else {
addInfo('info_memory', i, info.memory[i]);
}
}
for (const i in info.system) {
if (i == 'Uptime') {
const sec = info.system[i];
const upt = Math.floor(sec / 86400) + ':' + new Date(sec * 1000).toISOString().slice(11, 19);
const d = new Date();
const utc = d.getTime() - (d.getTimezoneOffset() * 60000);
addInfo('info_system', i, upt);
addInfo('info_system', 'Started', new Date(utc - sec * 1000).toISOString().split('.')[0].replace('T', ' '));
continue;
}
addInfo('info_system', i, info.system[i]);
}
}
function renderBody() {
document.body.innerHTML += `
<div id="plugins"></div>
<div id="app_plugins"></div>
<div class="header-row">
<div class="header">
<div class="icon header-back" data-action="back"></div>
<div class="header-title" data-action="back">GyverHub</div>
<div id="conn" class="header-connection"></div>
<div id='bt_ok' class="icon header-connection-icon"></div>
<div id='mqtt_ok' class="icon header-connection-icon"></div>
<div id='serial_ok' class="icon header-connection-icon"></div>
<div id='tg_ok' class="icon header-connection-icon"></div>
<div class="header-connections"></div>
<div class="icon header-icon icon_refresh" id='icon_refresh' data-action="refresh"></div>
<div class="icon header-icon icon_cfg" data-action="config"></div>
<div class="icon header-icon icon_menu" id='icon_menu' data-action="menu"></div>
</div>
</div>
<div class="main">
<div id="menu_overlay" onclick="menu_show(0)"></div>
<div id="menu" class="main_col menu"></div>
<div class="main_inn">
<div class="main_col screen-test">
<div class="test_text">А тут пока ничего нет. Но будет онлайн-тест интерфейса, в котором можно будет поиграться и проверить свой билд без загрузки прошивки</div>
</div>
<div id="projects_cont" class="main_col screen-projects">
<div class="proj">
<div class="proj_name">
<a href="https://github.com/GyverLibs/GyverHub-projects" target="_blank">+ <slot name="lang.p_add"></slot></a>
</div>
</div>
</div>
<div id="devices" class="main_col screen-main"></div>
<div id="controls" class="main_col screen-ui"></div>
<div class="main_col screen-dev_config">
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.i_settings"></slot></label>
</div>
<div class="ui_row">
<label><slot name="lang.i_console"></slot></label>
<label class="switch"><input type="checkbox" id="info_cli_sw" onchange="showCLI(this.checked);save_cfg()">
<span class="slider"></span></label>
</div>
<div class="ui_row">
<label><slot name="lang.i_trust"></slot></label>
<label class="switch"><input type="checkbox" id="info_trust" onchange="trust_dev_h()">
<span class="slider"></span></label>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.i_main"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="main_width" onchange="ui_width_h(this)">
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.i_css"></slot></label>
<div class="ui_inp_row">
<textarea class="w_area" id="plugin_css" onchange="ui_plugin_css_h(this)"></textarea>
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.i_js"></slot></label>
<div class="ui_inp_row">
<textarea class="w_area" id="plugin_js" onchange="ui_plugin_js_h(this)"></textarea>
</div>
</div>
<div class="ui_btn_row">
<button id="reboot_btn" class="ui_btn ui_btn_mini" onclick="reboot_h()"><span class="icon icon_inline"></span><slot name="lang.i_reboot"></slot></button>
<!--@[if_not_target:esp]-->
<button class="ui_btn ui_btn_mini" onclick="devlink_h()"><span class="icon icon_inline"></span><slot name="lang.i_link"></slot></button>
<button class="ui_btn ui_btn_mini" onclick="qr_h()"><span class="icon icon_inline"></span>QR</button>
<!--@/[if_not_target:esp]-->
</div>
</div>
</div>
<div class="main_col screen-info">
<div class="ui_col" id="info_topics">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.i_topics"></slot></label>
</div>
<div class="ui_row info">
<label>ID</label>
<label id="info_id" class="info_label info_label_small">-</label>
</div>
<div class="ui_row info">
<label>Set</label>
<label id="info_set" class="info_label info_label_small">-</label>
</div>
<div class="ui_row info">
<label>Read</label>
<label id="info_read" class="info_label info_label_small">-</label>
</div>
<div class="ui_row info">
<label>Get</label>
<label id="info_get" class="info_label info_label_small">-</label>
</div>
<div class="ui_row info">
<label>Status</label>
<label id="info_status" class="info_label info_label_small">-</label>
</div>
</div>
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.i_version"></slot></label>
</div>
<div id="info_version"></div>
</div>
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.i_net"></slot></label>
</div>
<div id="info_net"></div>
</div>
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.i_memory"></slot></label>
</div>
<div id="info_memory"></div>
</div>
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.i_system"></slot></label>
</div>
<div id="info_system"></div>
</div>
</div>
<div class="main_col screen-fsbr_edit">
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span>Editor</label>
</div>
<div class="ui_row">
<label id="edit_path"></label>
</div>
<div class="ui_row">
<label>Wrap text</label>
<label class="switch">
<input type="checkbox" id="editor_wrap" onchange="this.checked?editor_area.classList.remove('w_area_wrap'):editor_area.classList.add('w_area_wrap')">
<span class="slider"></span>
</label>
</div>
<div class="ui_row">
<textarea rows=20 id="editor_area" class="ui_inp w_area w_area_wrap"></textarea>
</div>
<div class="ui_row">
<button id="editor_save" onclick="editor_save()" class="ui_btn ui_btn_mini">Save & Upload</button>
<button onclick="editor_cancel()" class="ui_btn ui_btn_mini">Cancel</button>
</div>
</div>
</div>
<div class="main_col screen-files">
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span><slot name="lang.fs_fsbr"></slot></label>
</div>
<div id="fs_browser">
<div id="fsbr_inner"></div>
<div class="ui_row" style="justify-content: flex-start;">
<button id="fs_format" onclick="format_h()" class="ui_btn ui_btn_mini"><slot name="lang.fs_format"></slot></button>
<button id="fs_create" onclick="create_h()" class="ui_btn ui_btn_mini"><slot name="lang.fs_create"></slot></button>
<button id="fs_upload" onclick="upload_h()" class="ui_btn ui_btn_mini"><slot name="lang.fs_upload"></slot></button>
</div>
</div>
</div>
</div>
<div class="main_col screen-ota">
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span>OTA FILE</label>
</div>
<div id="fs_otaf">
<div class="ui_row">
<div>
<input type="file" id="ota_upload" style="display:none" onchange="uploadOta(this.files[0], 'flash')">
<button onclick="ota_upload.click()" class="ui_btn ui_btn_mini drop_area" ondrop="uploadOta(event.dataTransfer.files[0], 'flash')">Flash</button>
<input type="file" id="ota_upload_fs" style="display:none" onchange="uploadOta(this.files[0], 'fs')">
<button onclick="ota_upload_fs.click()" class="ui_btn ui_btn_mini drop_area" ondrop="uploadOta(event.dataTransfer.files[0], 'fs')">Filesystem</button>
</div>
<label style="font-size:18px" id="ota_label"></label>
</div>
</div>
</div>
<div class="ui_col">
<div class="ui_row ui_head">
<label><span class="icon icon_ui"></span>OTA URL</label>
</div>
<div id="fs_otaurl">
<div class="upl_row">
<input class="ui_inp ui_inp_wbtn" type="text" id="ota_url_f">
<button id="ota_url_btn" onclick="otaUrl(ota_url_f.value,'flash')" class="ui_btn upl_btn">Flash</button>
</div>
<div class="upl_row">
<input class="ui_inp ui_inp_wbtn" type="text" id="ota_url_fs">
<button id="ota_url_btn" onclick="otaUrl(ota_url_fs.value,'fs')" class="ui_btn upl_btn">FS</button>
</div>
</div>
</div>
</div>
<div class="main_col screen-config">
<div class="ui_col">
<div class="ui_row ui_head ui_tab" onclick="use_local.click()">
<label class="ui_label ui_tab" id="local_label"><span class="icon icon_ui"></span>WiFi</label>
<input type="checkbox" id="use_local" data-hub-config="connections.HTTP.enabled" onchange="update_cfg(this);save_cfg()" style="display:none">
</div>
<div id="local_block" style="display:none">
<div class="ui_row" id="http_only_http" style="display:none">
<span style="color:#c60000">Works only on <strong class="span_btn" onclick="window.location.href = window.location.href.replace('https', 'http')">HTTP</strong>!</span>
</div>
<div id="http_settings">
<div class="ui_row">
<label class="ui_label"><slot name="lang.wifi_ip"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="local_ip" data-hub-config="connections.HTTP.local_ip" onchange="update_cfg(this)">
<div class="btn_inp_block">
<button class="icon icon_btn" onclick="update_ip_h();update_cfg(EL('local_ip'))"></button>
</div>
</div>
</div>
<div class="ui_row">
<label><slot name="lang.wifi_mask"></slot></label>
<div class="ui_inp_row">
<select class="ui_inp ui_sel" id="netmask" data-hub-config="connections.HTTP.netmask" onchange="update_cfg(this)"></select>
</div>
</div>
<div class="ui_row">
<label><slot name="lang.wifi_port"></slot></label>
<div class="ui_inp_row"><input class="ui_inp" type="text" id="http_port" data-hub-config="connections.HTTP.port" onchange="update_cfg(this)">
</div>
</div>
<!--@[if_target:host,esp]-->
<span class="notice_block">Disable:
<u><slot name="browser"></slot>://flags/#block-insecure-private-network-requests</u></span>
<!--@/[if_target:host,esp]-->
<hr>
<div class="ui_row">
<label class="ui_label"><slot name="lang.wifi_add"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" value="192.168.1.1" id="local_add_ip">
<div class="btn_inp_block">
<button class="icon icon_btn" onclick="manual_ip_h(local_add_ip.value)"></button>
</div>
</div>
</div>
</div>
</div>
</div>
<!--@[if_not_target:esp]-->
<div class="ui_col" id="mq_col">
<div class="ui_row ui_head ui_tab" onclick="use_mqtt.click()">
<label class="ui_label ui_tab" id="mqtt_label"><span class="icon icon_ui"></span>MQTT</label>
<input type="checkbox" id="use_mqtt" data-hub-config="connections.MQTT.enabled" onchange="update_cfg(this);hub.mqtt.disconnect();save_cfg()" style="display:none">
</div>
<div id="mq_block" style="display:none">
<div class="ui_row">
<label class="ui_label"><slot name="lang.mq_host"></slot></label>
<div class="ui_inp_row"><input class="ui_inp" type="text" id="mq_host" data-hub-config="connections.MQTT.host" onchange="update_cfg(this);hub.mqtt.disconnect()"></div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.mq_port"></slot></label>
<div class="ui_inp_row"><input class="ui_inp" type="number" id="mq_port" data-hub-config="connections.MQTT.port" onchange="update_cfg(this);hub.mqtt.disconnect()"></div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.mq_login"></slot></label>
<div class="ui_inp_row"><input class="ui_inp" type="text" id="mq_login" data-hub-config="connections.MQTT.login" onchange="update_cfg(this);hub.mqtt.disconnect()"></div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.mq_pass"></slot></label>
<div class="ui_inp_row"><input class="ui_inp" type="password" id="mq_pass" data-hub-config="connections.MQTT.password" onchange="update_cfg(this);hub.mqtt.disconnect()">
</div>
</div>
<div class="ui_row">
<div></div>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" onclick="hub.mqtt.connect()" id="mq_start"><slot name="lang.connect"></slot></button>
<button class="ui_btn ui_btn_mini" onclick="hub.mqtt.disconnect()" id="mq_stop" style="display:none"><slot name="lang.disconnect"></slot></button>
</div>
</div>
</div>
</div>
<div class="ui_col" id="tg_col">
<div class="ui_row ui_head ui_tab" onclick="use_tg.click()">
<label class="ui_label ui_tab" id="tg_label"><span class="icon icon_ui"></span>Telegram</label>
<input type="checkbox" id="use_tg" data-hub-config="connections.TG.enabled" onchange="update_cfg(this);hub.tg.disconnect();save_cfg()" style="display:none">
</div>
<div id="tg_block" style="display:none">
<div class="ui_row">
<label class="ui_label"><slot name="lang.tg_token"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="tg_token" data-hub-config="connections.TG.token" onchange="update_cfg(this);hub.tg.disconnect()">
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.tg_chat"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="tg_chat" data-hub-config="connections.TG.chat" onchange="update_cfg(this)">
</div>
</div>
<div class="ui_row">
<div></div>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" onclick="hub.tg.connect()" id="tg_start"><slot name="lang.connect"></slot></button>
<button class="ui_btn ui_btn_mini" onclick="hub.tg.disconnect()" id="tg_stop" style="display:none"><slot name="lang.disconnect"></slot></button>
</div>
</div>
</div>
</div>
<div class="ui_col" id="serial_col">
<div class="ui_row ui_head ui_tab" onclick="use_serial.click()">
<label class="ui_label ui_tab" id="serial_label"><span class="icon icon_ui"></span>Serial</label>
<input type="checkbox" id="use_serial" data-hub-config="connections.SERIAL.enabled" onchange="update_cfg(this);hub.serial.disconnect();save_cfg()" style="display:none">
</div>
<div id="serial_block" style="display:none">
<div class="ui_row">
<label class="ui_label"><slot name="lang.sr_baud"></slot></label>
<div class="ui_inp_row">
<select class="ui_inp ui_sel" id='baudrate' data-hub-config="connections.SERIAL.baudrate" onchange="update_cfg(this)">
<option value="4800">4800</option>
<option value="9600">9600</option>
<option value="19200">19200</option>
<option value="38400">38400</option>
<option value="57600">57600</option>
<option value="74880">74880</option>
<option value="115200">115200</option>
<option value="230400">230400</option>
<option value="250000">250000</option>
<option value="500000">500000</option>
<option value="1000000">1000000</option>
<option value="2000000">2000000</option>
</select>
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.sr_offset"></slot></label>
<div class="ui_inp_row"><input class="ui_inp" type="text" id="serial_offset" data-hub-config="connections.SERIAL.offset" onchange="update_cfg(this)">
</div>
</div>
<div class="ui_row">
<div><label class="ui_label" id="serial_device"><slot name="lang.not_conn"></slot></label> <label class="ui_label" id="port_name"></label></div>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" onclick="hub.serial.select()"><slot name="lang.select"></slot></button>
<button id="serial_open" class="ui_btn ui_btn_mini" onclick="hub.serial.connect()" style="display:none"><slot name="lang.connect"></slot></button>
<button id="serial_close" class="ui_btn ui_btn_mini" onclick="hub.serial.disconnect()" style="display:none"><slot name="lang.disconnect"></slot></button>
</div>
</div>
</div>
</div>
<div class="ui_col" id="bt_col">
<div class="ui_row ui_head ui_tab" onclick="use_bt.click()">
<label class="ui_label ui_tab" id="bt_label"><span class="icon icon_ui"></span>Bluetooth</label>
<input type="checkbox" id="use_bt" data-hub-config="connections.BLE.enabled" onchange="update_cfg(this);save_cfg()" style="display:none">
</div>
<div id="bt_block" style="display:none">
<div class="ui_row">
<label class="ui_label" id="bt_device"><slot name="lang.not_conn"></slot></label>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" onclick="hub.bt.select()"><slot name="lang.select"></slot></button>
<button id="bt_open" class="ui_btn ui_btn_mini" onclick="hub.bt.connect()" style="display:none"><slot name="lang.connect"></slot></button>
<button id="bt_close" class="ui_btn ui_btn_mini" onclick="hub.bt.disconnect()" style="display:none"><slot name="lang.disconnect"></slot></button>
</div>
</div>
</div>
</div>
<!--@/[if_not_target:esp]-->
<div class="ui_col">
<div class="ui_row ui_head">
<label class="ui_label"><span class="icon icon_ui"></span><slot name="lang.cfg_sett"></slot></label>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_search"></slot></label>
<button class="icon icon_btn_big" onclick="search()" title="Find new devices"></button>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_prefix"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="prefix" data-hub-config="hub.prefix" onchange="update_cfg(this)">
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_id"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="client_id" data-hub-config="hub.client_id" onchange="update_cfg(this)" oninput="if(this.value.length>8)this.value=this.value.slice(0,-1)">
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_theme"></slot></label>
<div class="ui_inp_row">
<select class="ui_inp ui_sel" id='theme' onchange="update_cfg(this)">
<option value="auto"></option>
<option value="dark"></option>
<option value="light"></option>
</select>
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_color"></slot></label>
<div class="ui_inp_row">
<select class="ui_inp ui_sel" id='maincolor' onchange="update_cfg(this)">
<option value="ORANGE"></option>
<option value="YELLOW"></option>
<option value="GREEN"></option>
<option value="MINT"></option>
<option value="AQUA"></option>
<option value="BLUE"></option>
<option value="VIOLET"></option>
<option value="PINK"></option>
</select>
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_font"></slot></label>
<div class="ui_inp_row">
<select class="ui_inp ui_sel" id='font' onchange="update_cfg(this)">
<option value="monospace">monospace</option>
<option value="system-ui">system-ui</option>
<option value="cursive">cursive</option>
<option value="Arial">Arial</option>
<option value="Verdana">Verdana</option>
<option value="Tahoma">Tahoma</option>
<option value="Trebuchet MS">Trebuchet MS</option>
<option value="Georgia">Georgia</option>
<option value="Garamond">Garamond</option>
</select>
</div>
</div>
<div class="ui_row">
<label class="ui_label">Language</label>
<div class="ui_inp_row">
<select class="ui_inp ui_sel" id='lang' onchange="update_cfg(this)">
<option value="English">English</option>
<option value="Russian">Russian</option>
</select>
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_width"></slot></label>
<div class="ui_inp_row">
<input class="ui_inp" type="text" id="ui_width" onchange="update_cfg(this)">
</div>
</div>
<div class="ui_row">
<label><slot name="lang.cfg_wide_mode"></slot></label>
<label class="switch"><input type="checkbox" id="wide_mode" onchange="update_cfg(this)"><span class="slider"></span></label>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_css"></slot></label>
<div class="ui_inp_row">
<textarea class="w_area" id="app_plugin_css" onchange="update_cfg(this)"></textarea>
</div>
</div>
<div class="ui_row">
<label class="ui_label"><slot name="lang.cfg_js"></slot></label>
<div class="ui_inp_row">
<textarea class="w_area" id="app_plugin_js" onchange="update_cfg(this)"></textarea>
</div>
</div>
<div class="ui_row">
<label><slot name="lang.cfg_updates"></slot></label>
<label class="switch"><input type="checkbox" id="check_upd" onchange="update_cfg(this)"><span class="slider"></span></label>
</div>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" onclick="cfg_export()"><slot name="lang.cfg_export"></slot></button>
<button class="ui_btn ui_btn_mini" onclick="cfg_import()"><slot name="lang.cfg_import"></slot></button>
<button class="ui_btn ui_btn_mini" onclick="cfg_reset()"><slot name="lang.cfg_reset"></slot></button>
</div>
</div>
<div class="ui_col">
<div class="ui_row ui_head ui_tab" onclick="use_pin.click()">
<label id="pin_label" class="ui_label ui_tab"><span class="icon icon_ui"></span>PIN</label>
<input type="checkbox" id="use_pin" onchange="update_cfg(this)" style="display:none">
</div>
<div id="pin_block" style="display:none">
<div class="ui_row">
<label class="ui_label">PIN</label>
<div class="ui_inp_row"><input class="ui_inp" type="password" pattern="[0-9]*" inputmode="numeric" id="pin" onchange="make_pin(this);update_cfg(this)" oninput="check_type(this)">
</div>
</div>
</div>
</div>
<!--@[if_target:host]-->
<div class="ui_col">
<div class="ui_row ui_head">
<label class="ui_label"><span class="icon icon_ui"></span>App</label>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" onclick="openURL('https://github.com/neko-neko-nyan/gyverhub-desktop/releases/latest')">PC</button>
<button class="ui_btn ui_btn_mini" onclick="openURL('https://apps.apple.com/kz/app/gyverhub/id6474273925')">iOS</button>
<button class="ui_btn ui_btn_mini" onclick="openURL('https://play.google.com/store/apps/details?id=ru.alexgyver.GyverHub')">Android</button>
<button class="ui_btn ui_btn_mini" onclick="openURL('https://github.com/GyverLibs/GyverHub-app/releases/latest/download/app-release.apk')">.apk</button>
</div>
</div>
</div>
<div class="ui_col" id="pwa_block" style="display: none;">
<div class="ui_row ui_head">
<label class="ui_label"><span class="icon icon_ui"></span>Web App</label>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" id="btn_pwa"><slot name="lang.p_install"></slot></button>
</div>
</div>
<span class="notice_block" id="pwa_unsafe">Enable <u><slot name="browser"></slot>://flags/#unsafely-treat-insecure-origin-as-secure</u> and add <u><slot name="location"></slot></u> to list</span>
</div>
<div class="ui_col">
<div class="ui_row ui_head">
<label class="ui_label"><span class="icon icon_ui"></span>HTTP/HTTPS</label>
<div class="ui_btn_row">
<button class="ui_btn ui_btn_mini" id="btn_pwa_http" onclick="switch_ssl(false)">HTTP</button>
<button class="ui_btn ui_btn_mini" id="btn_pwa_https" onclick="switch_ssl(true)">HTTPS</button>
</div>
</div>
</div>
<!--@/[if_target:host]-->
<div class="ui_col">
<div class="cfg_info" id="hub_stat">GyverHub v<!--@![:version]--> <!--@![:target]--></div>
<div class="cfg_info">
Contribution:
<a href="https://github.com/Simonwep/pickr" target="_blank">Pickr</a>
<a href="https://github.com/mqttjs/MQTT.js" target="_blank">MQTT.js</a>
<a href="https://github.com/ghornich/sort-paths" target="_blank">sort-paths</a>
<a href="https://fontawesome.com/v5/search?o=r&m=free&s=solid" target="_blank">Fontawesome</a>
<a href="https://github.com/loginov-rocks/Web-Bluetooth-Terminal" target="_blank">Bluetooth Terminal</a>
<a href="https://github.com/davidshimjs/qrcodejs" target="_blank">QRCode.js</a>
<a href="https://esphome.github.io/esp-web-tools/" target="_blank">ESP Web Tools</a>
</div>
</div>
</div>
</div>
</div>
<div class="cli" id="cli_cont">
<div class="cli_block">
<div class="cli_area" id="cli"></div>
<div class="cli_row">
<span class="icon cli_icon"></span>
<input type="text" class="ui_inp cli_inp" id="cli_input" onkeydown="checkCLI(event)">
<button class="icon icon_btn cli_icon cli_enter" onclick="sendCLI()"></button>
</div>
</div>
</div>
<div class="footer">
<!-- <a href="https://alexgyver.ru/support_alex/" target="_blank"><span class="icon icon_inline i_footer"></span> Support</a> -->
<a style="cursor:pointer" data-action="show_screen" data-screen="projects"><span class="icon icon_inline i_footer"></span> <slot name="lang.p_proj"></slot></a>
<a style="cursor:pointer" data-action="show_screen" data-screen="test"><span class="icon icon_inline i_footer"></span> Test</a>
<!-- <a href="https://hub.gyver.ru/old/" target="_blank"><span class="icon icon_inline i_footer"></span> Old</a> -->
<a href="https://github.com/GyverLibs/GyverHub/wiki" target="_blank"><span class="icon icon_inline i_footer"></span> Wiki</a>
</div>
`;
}