diff --git a/CHANGELOG.md b/CHANGELOG.md
index 153fdd375..2eb2d2b54 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,7 @@
- model type: detection
- model type: add tracing to model detection
- settings: guard against non-string values, thanks @awsr
+ - ui: wait for server options to be ready before initializing ui
- ui: fix full-screen image viewer buttons with non-standard ui theme
- ui: control tab show override section
- ui: mobile layout for video tab
diff --git a/extensions-builtin/sdnext-modernui b/extensions-builtin/sdnext-modernui
index 388c22343..d6028d633 160000
--- a/extensions-builtin/sdnext-modernui
+++ b/extensions-builtin/sdnext-modernui
@@ -1 +1 @@
-Subproject commit 388c2234378fb0c45575d4e7993470377abfa790
+Subproject commit d6028d63319172a1b49cdb93418dd2b0c84c1cd9
diff --git a/javascript/logMonitor.js b/javascript/logMonitor.js
index 91ed8a7cd..ab70400af 100644
--- a/javascript/logMonitor.js
+++ b/javascript/logMonitor.js
@@ -99,7 +99,8 @@ async function initLogMonitor() {
const el = document.getElementsByTagName('footer')[0];
if (!el) return;
el.classList.add('log-monitor');
- if (window.opts.ui_disabled?.includes('logs')) return;
+ const ui_disabled = Array.isArray(window.opts.ui_disabled) ? window.opts.ui_disabled : [];
+ if (ui_disabled.includes('logs')) return;
el.innerHTML = `
diff --git a/javascript/settings.js b/javascript/settings.js
index f82f0a692..540e65af0 100644
--- a/javascript/settings.js
+++ b/javascript/settings.js
@@ -95,14 +95,22 @@ function markIfModified(setting_name, value) {
// elem.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
-onAfterUiUpdate(async () => {
- if (Object.keys(opts).length !== 0) return;
+function updateAllOpts() {
+ if (Object.keys(opts).length !== 0) return false;
const json_elem = gradioApp().getElementById('settings_json');
- if (!json_elem) return;
+ log('updateAllOpts', !!json_elem);
+ if (!json_elem) return false;
json_elem.parentElement.style.display = 'none';
const textarea = json_elem.querySelector('textarea');
const jsdata = textarea.value;
updateOpts(jsdata);
+ return true;
+}
+
+onAfterUiUpdate(async () => {
+ if (!updateAllOpts()) return;
+ const json_elem = gradioApp().getElementById('settings_json');
+ const textarea = json_elem.querySelector('textarea');
executeCallbacks(optionsChangedCallbacks);
registerDragDrop();
diff --git a/javascript/startup.js b/javascript/startup.js
index ac927e1e1..82194d942 100644
--- a/javascript/startup.js
+++ b/javascript/startup.js
@@ -2,6 +2,27 @@
window.api = '/sdapi/v1';
window.subpath = '';
+async function waitForOpts() {
+ // make sure all of the ui is ready and options are loaded
+ const t0 = performance.now();
+ let t1 = performance.now();
+ while (true) { // eslint-disable-line no-constant-condition
+ if (t1 - t0 > 120000) {
+ log('waitForOpts timeout');
+ break;
+ }
+ if (window.opts && Object.keys(window.opts).length > 0) {
+ ok = window.opts.theme_type === 'Modern' ? 'uiux_separator_appearance' in window.opts : true;
+ if (ok) {
+ log('waitForOpts', `time=${Math.round(t1 - t0)}`);
+ break;
+ }
+ }
+ await sleep(50);
+ t1 = performance.now();
+ }
+}
+
async function initStartup() {
const t0 = performance.now();
log('gradio', `time=${Math.round(t0 - appStartTime)}`);
@@ -24,13 +45,8 @@ async function initStartup() {
// reconnect server session
await reconnectUI();
+ await waitForOpts();
- // make sure all of the ui is ready and options are loaded
- let t1 = performance.now();
- while ((Object.keys(window.opts).length === 0) && (t1 - t0 < 120000)) {
- t1 = performance.now();
- await sleep(50);
- }
log('mountURL', window.opts.subpath);
if (window.opts.subpath?.length > 0) {
window.subpath = window.opts.subpath;