Merge branch 'ui_init' of github.com:CendioOssman/noVNC

This commit is contained in:
Pierre Ossman 2024-10-09 13:12:33 +02:00
commit ed1fef4fc3
4 changed files with 128 additions and 48 deletions

123
app/ui.js
View File

@ -20,8 +20,12 @@ import * as WebUtil from "./webutil.js";
const PAGE_TITLE = "noVNC"; const PAGE_TITLE = "noVNC";
const LINGUAS = ["cs", "de", "el", "es", "fr", "it", "ja", "ko", "nl", "pl", "pt_BR", "ru", "sv", "tr", "zh_CN", "zh_TW"];
const UI = { const UI = {
customSettings: {},
connected: false, connected: false,
desktopName: "", desktopName: "",
@ -42,20 +46,31 @@ const UI = {
reconnectCallback: null, reconnectCallback: null,
reconnectPassword: null, reconnectPassword: null,
prime() { async start(options={}) {
return WebUtil.initSettings().then(() => { UI.customSettings = options.settings || {};
if (document.readyState === "interactive" || document.readyState === "complete") { if (UI.customSettings.defaults === undefined) {
return UI.start(); UI.customSettings.defaults = {};
} }
if (UI.customSettings.mandatory === undefined) {
UI.customSettings.mandatory = {};
}
return new Promise((resolve, reject) => { // Set up translations
document.addEventListener('DOMContentLoaded', () => UI.start().then(resolve).catch(reject)); try {
await l10n.setup(LINGUAS, "app/locale/");
} catch (err) {
Log.Error("Failed to load translations: " + err);
}
// Initialize setting storage
await WebUtil.initSettings();
// Wait for the page to load
if (document.readyState !== "interactive" && document.readyState !== "complete") {
await new Promise((resolve, reject) => {
document.addEventListener('DOMContentLoaded', resolve);
}); });
}); }
},
// Render default UI and initialize settings menu
start() {
UI.initSettings(); UI.initSettings();
@ -70,22 +85,20 @@ const UI = {
} }
// Try to fetch version number // Try to fetch version number
fetch('./package.json') try {
.then((response) => { let response = await fetch('./package.json');
if (!response.ok) { if (!response.ok) {
throw Error("" + response.status + " " + response.statusText); throw Error("" + response.status + " " + response.statusText);
} }
return response.json();
}) let packageInfo = await response.json();
.then((packageInfo) => { Array.from(document.getElementsByClassName('noVNC_version')).forEach(el => el.innerText = packageInfo.version);
Array.from(document.getElementsByClassName('noVNC_version')).forEach(el => el.innerText = packageInfo.version); } catch (err) {
}) Log.Error("Couldn't fetch package.json: " + err);
.catch((err) => { Array.from(document.getElementsByClassName('noVNC_version_wrapper'))
Log.Error("Couldn't fetch package.json: " + err); .concat(Array.from(document.getElementsByClassName('noVNC_version_separator')))
Array.from(document.getElementsByClassName('noVNC_version_wrapper')) .forEach(el => el.style.display = 'none');
.concat(Array.from(document.getElementsByClassName('noVNC_version_separator'))) }
.forEach(el => el.style.display = 'none');
});
// Adapt the interface for touch screen devices // Adapt the interface for touch screen devices
if (isTouchDevice) { if (isTouchDevice) {
@ -120,7 +133,7 @@ const UI = {
document.documentElement.classList.remove("noVNC_loading"); document.documentElement.classList.remove("noVNC_loading");
let autoconnect = WebUtil.getConfigVar('autoconnect', false); let autoconnect = UI.getSetting('autoconnect');
if (autoconnect === 'true' || autoconnect == '1') { if (autoconnect === 'true' || autoconnect == '1') {
autoconnect = true; autoconnect = true;
UI.connect(); UI.connect();
@ -129,8 +142,6 @@ const UI = {
// Show the connect panel on first load unless autoconnecting // Show the connect panel on first load unless autoconnecting
UI.openConnectPanel(); UI.openConnectPanel();
} }
return Promise.resolve(UI.rfb);
}, },
initFullscreen() { initFullscreen() {
@ -158,23 +169,26 @@ const UI = {
UI.initSetting('logging', 'warn'); UI.initSetting('logging', 'warn');
UI.updateLogging(); UI.updateLogging();
UI.setupSettingLabels();
/* Populate the controls if defaults are provided in the URL */ /* Populate the controls if defaults are provided in the URL */
UI.initSetting('host', ''); UI.initSetting('host', '');
UI.initSetting('port', 0); UI.initSetting('port', 0);
UI.initSetting('encrypt', (window.location.protocol === "https:")); UI.initSetting('encrypt', (window.location.protocol === "https:"));
UI.initSetting('password');
UI.initSetting('autoconnect', false);
UI.initSetting('view_clip', false); UI.initSetting('view_clip', false);
UI.initSetting('resize', 'off'); UI.initSetting('resize', 'off');
UI.initSetting('quality', 6); UI.initSetting('quality', 6);
UI.initSetting('compression', 2); UI.initSetting('compression', 2);
UI.initSetting('shared', true); UI.initSetting('shared', true);
UI.initSetting('bell', 'on');
UI.initSetting('view_only', false); UI.initSetting('view_only', false);
UI.initSetting('show_dot', false); UI.initSetting('show_dot', false);
UI.initSetting('path', 'websockify'); UI.initSetting('path', 'websockify');
UI.initSetting('repeaterID', ''); UI.initSetting('repeaterID', '');
UI.initSetting('reconnect', false); UI.initSetting('reconnect', false);
UI.initSetting('reconnect_delay', 5000); UI.initSetting('reconnect_delay', 5000);
UI.setupSettingLabels();
}, },
// Adds a link to the label elements on the corresponding input elements // Adds a link to the label elements on the corresponding input elements
setupSettingLabels() { setupSettingLabels() {
@ -736,6 +750,10 @@ const UI = {
// Initial page load read/initialization of settings // Initial page load read/initialization of settings
initSetting(name, defVal) { initSetting(name, defVal) {
// Has the user overridden the default value?
if (name in UI.customSettings.defaults) {
defVal = UI.customSettings.defaults[name];
}
// Check Query string followed by cookie // Check Query string followed by cookie
let val = WebUtil.getConfigVar(name); let val = WebUtil.getConfigVar(name);
if (val === null) { if (val === null) {
@ -743,6 +761,11 @@ const UI = {
} }
WebUtil.setSetting(name, val); WebUtil.setSetting(name, val);
UI.updateSetting(name); UI.updateSetting(name);
// Has the user forced a value?
if (name in UI.customSettings.mandatory) {
val = UI.customSettings.mandatory[name];
UI.forceSetting(name, val);
}
return val; return val;
}, },
@ -761,9 +784,12 @@ const UI = {
let value = UI.getSetting(name); let value = UI.getSetting(name);
const ctrl = document.getElementById('noVNC_setting_' + name); const ctrl = document.getElementById('noVNC_setting_' + name);
if (ctrl === null) {
return;
}
if (ctrl.type === 'checkbox') { if (ctrl.type === 'checkbox') {
ctrl.checked = value; ctrl.checked = value;
} else if (typeof ctrl.options !== 'undefined') { } else if (typeof ctrl.options !== 'undefined') {
for (let i = 0; i < ctrl.options.length; i += 1) { for (let i = 0; i < ctrl.options.length; i += 1) {
if (ctrl.options[i].value === value) { if (ctrl.options[i].value === value) {
@ -796,7 +822,8 @@ const UI = {
getSetting(name) { getSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name); const ctrl = document.getElementById('noVNC_setting_' + name);
let val = WebUtil.readSetting(name); let val = WebUtil.readSetting(name);
if (typeof val !== 'undefined' && val !== null && ctrl.type === 'checkbox') { if (typeof val !== 'undefined' && val !== null &&
ctrl !== null && ctrl.type === 'checkbox') {
if (val.toString().toLowerCase() in {'0': 1, 'no': 1, 'false': 1}) { if (val.toString().toLowerCase() in {'0': 1, 'no': 1, 'false': 1}) {
val = false; val = false;
} else { } else {
@ -811,14 +838,22 @@ const UI = {
// disable the labels that belong to disabled input elements. // disable the labels that belong to disabled input elements.
disableSetting(name) { disableSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name); const ctrl = document.getElementById('noVNC_setting_' + name);
ctrl.disabled = true; if (ctrl !== null) {
ctrl.label.classList.add('noVNC_disabled'); ctrl.disabled = true;
if (ctrl.label !== undefined) {
ctrl.label.classList.add('noVNC_disabled');
}
}
}, },
enableSetting(name) { enableSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name); const ctrl = document.getElementById('noVNC_setting_' + name);
ctrl.disabled = false; if (ctrl !== null) {
ctrl.label.classList.remove('noVNC_disabled'); ctrl.disabled = false;
if (ctrl.label !== undefined) {
ctrl.label.classList.remove('noVNC_disabled');
}
}
}, },
/* ------^------- /* ------^-------
@ -1000,7 +1035,7 @@ const UI = {
const path = UI.getSetting('path'); const path = UI.getSetting('path');
if (typeof password === 'undefined') { if (typeof password === 'undefined') {
password = WebUtil.getConfigVar('password'); password = UI.getSetting('password');
UI.reconnectPassword = password; UI.reconnectPassword = password;
} }
@ -1730,7 +1765,7 @@ const UI = {
}, },
bell(e) { bell(e) {
if (WebUtil.getConfigVar('bell', 'on') === 'on') { if (UI.getSetting('bell') === 'on') {
const promise = document.getElementById('noVNC_bell').play(); const promise = document.getElementById('noVNC_bell').play();
// The standards disagree on the return value here // The standards disagree on the return value here
if (promise) { if (promise) {
@ -1761,10 +1796,4 @@ const UI = {
*/ */
}; };
// Set up translations
const LINGUAS = ["cs", "de", "el", "es", "fr", "it", "ja", "ko", "nl", "pl", "pt_BR", "ru", "sv", "tr", "zh_CN", "zh_TW"];
l10n.setup(LINGUAS, "app/locale/")
.catch(err => Log.Error("Failed to load translations: " + err))
.then(UI.prime);
export default UI; export default UI;

1
defaults.json Normal file
View File

@ -0,0 +1 @@
{}

1
mandatory.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -46,7 +46,56 @@
<link rel="preload" as="image" href="app/images/warning.svg"> <link rel="preload" as="image" href="app/images/warning.svg">
<script type="module" crossorigin="anonymous" src="app/error-handler.js"></script> <script type="module" crossorigin="anonymous" src="app/error-handler.js"></script>
<script type="module" crossorigin="anonymous" src="app/ui.js"></script>
<script type="module">
import UI from "./app/ui.js";
import * as Log from './core/util/logging.js';
let response;
let defaults = {};
let mandatory = {};
// Default settings will be loaded from defaults.json. Mandatory
// settings will be loaded from mandatory.json, which the user
// cannot change.
try {
response = await fetch('./defaults.json');
if (!response.ok) {
throw Error("" + response.status + " " + response.statusText);
}
defaults = await response.json();
} catch (err) {
Log.Error("Couldn't fetch defaults.json: " + err);
}
try {
response = await fetch('./mandatory.json');
if (!response.ok) {
throw Error("" + response.status + " " + response.statusText);
}
mandatory = await response.json();
} catch (err) {
Log.Error("Couldn't fetch mandatory.json: " + err);
}
// You can also override any defaults you need here:
//
// defaults['host'] = 'vnc.example.com';
// Or force a specific setting, preventing the user from
// changing it:
//
// mandatory['view_only'] = true;
// See docs/EMBEDDING.md for a list of possible settings.
UI.start({ settings: { defaults: defaults,
mandatory: mandatory } });
</script>
</head> </head>
<body> <body>