98 lines
3.6 KiB
JavaScript
98 lines
3.6 KiB
JavaScript
// Assist dialog textfield readability — aggressive inline-style enforcement.
|
|
// v3: directly writes inline styles on every input / textarea element and their
|
|
// visible containers, bypassing CSS cascade entirely. Runs on every mutation.
|
|
(function () {
|
|
if (window.__assistFixLoaded) return;
|
|
window.__assistFixLoaded = true;
|
|
|
|
function rootComputed(varName, fallback) {
|
|
const v = getComputedStyle(document.documentElement)
|
|
.getPropertyValue(varName)
|
|
.trim();
|
|
return v || fallback;
|
|
}
|
|
|
|
function applyColors(el) {
|
|
if (!el || el.__assistFixStyled) return;
|
|
const fg = rootComputed('--primary-text-color', '#e7e9f4');
|
|
const bg = rootComputed('--card-background-color', 'rgba(22, 24, 40, 0.92)');
|
|
const muted = rootComputed('--secondary-text-color', '#9a9cb8');
|
|
el.style.setProperty('color', fg, 'important');
|
|
el.style.setProperty('caret-color', fg, 'important');
|
|
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
|
|
el.style.setProperty('background-color', 'transparent', 'important');
|
|
} else {
|
|
el.style.setProperty('background-color', bg, 'important');
|
|
}
|
|
// Also set the MDC variables at element level in case they're read here
|
|
el.style.setProperty('--mdc-text-field-fill-color', bg, 'important');
|
|
el.style.setProperty('--mdc-text-field-ink-color', fg, 'important');
|
|
el.style.setProperty('--mdc-text-field-label-ink-color', muted, 'important');
|
|
el.style.setProperty('--mdc-filled-text-field-container-color', bg, 'important');
|
|
el.style.setProperty('--mdc-filled-text-field-input-text-color', fg, 'important');
|
|
el.style.setProperty('--mdc-filled-text-field-label-text-color', muted, 'important');
|
|
el.__assistFixStyled = true;
|
|
}
|
|
|
|
// Walk document + every shadow root, applying inline styles to matching elements
|
|
const TARGET_SELECTORS = [
|
|
'input', 'textarea',
|
|
'ha-textfield', 'ha-textarea',
|
|
'mwc-textfield', 'mwc-textarea',
|
|
'.mdc-text-field',
|
|
'.mdc-text-field--filled',
|
|
'.mdc-text-field__input',
|
|
'.mdc-text-area__input',
|
|
];
|
|
|
|
function walkAndStyle(root, depth = 0) {
|
|
if (!root || depth > 10) return 0;
|
|
let count = 0;
|
|
try {
|
|
TARGET_SELECTORS.forEach(sel => {
|
|
root.querySelectorAll(sel).forEach(el => {
|
|
applyColors(el);
|
|
count++;
|
|
});
|
|
});
|
|
root.querySelectorAll('*').forEach(el => {
|
|
if (el.shadowRoot) count += walkAndStyle(el.shadowRoot, depth + 1);
|
|
});
|
|
} catch (e) {}
|
|
return count;
|
|
}
|
|
|
|
// Initial pass
|
|
const initialCount = walkAndStyle(document);
|
|
console.log('[assist-fix] v3 initial pass styled', initialCount, 'elements');
|
|
|
|
// Watch for document mutations (a dialog opening registers as a subtree mutation
|
|
// in the hosting shadow root, not body — so we also periodically re-scan)
|
|
const obs = new MutationObserver(() => walkAndStyle(document));
|
|
obs.observe(document.body || document.documentElement, {
|
|
childList: true,
|
|
subtree: true,
|
|
});
|
|
|
|
// Periodic rescan every 500ms for the first 2 minutes (catches dialogs
|
|
// that attach textfields lazily in their own shadow roots)
|
|
let passes = 0;
|
|
const iv = setInterval(() => {
|
|
const n = walkAndStyle(document);
|
|
if (++passes > 240) clearInterval(iv);
|
|
if (n > initialCount && passes % 4 === 0) {
|
|
console.log('[assist-fix] v3 total styled now', n);
|
|
}
|
|
}, 500);
|
|
|
|
// Also listen for show-dialog events that HA fires — do an immediate sweep
|
|
window.addEventListener('show-dialog', () => {
|
|
setTimeout(() => {
|
|
const n = walkAndStyle(document);
|
|
console.log('[assist-fix] v3 post-dialog styled', n);
|
|
}, 100);
|
|
});
|
|
|
|
console.log('[assist-fix] v3 loaded, observing for dialogs');
|
|
})();
|