97 lines
3.0 KiB
JavaScript
97 lines
3.0 KiB
JavaScript
// Assist dialog input-field readability patch
|
|
// Targets ha-voice-command-dialog's text input and forces theme-driven colors,
|
|
// since HA's own theme variables don't reach the nested mwc-textfield shadow root.
|
|
(function () {
|
|
if (window.__assistFixLoaded) return;
|
|
window.__assistFixLoaded = true;
|
|
|
|
const css = `
|
|
:host .mdc-text-field,
|
|
:host .mdc-text-field--filled,
|
|
.mdc-text-field,
|
|
.mdc-text-field--filled {
|
|
background-color: var(--card-background-color, rgba(22, 24, 40, 0.92)) !important;
|
|
border-radius: 8px !important;
|
|
}
|
|
:host .mdc-text-field__input,
|
|
.mdc-text-field__input,
|
|
:host input,
|
|
input {
|
|
color: var(--primary-text-color, #e7e9f4) !important;
|
|
caret-color: var(--primary-text-color, #e7e9f4) !important;
|
|
}
|
|
:host .mdc-floating-label,
|
|
.mdc-floating-label,
|
|
:host .mdc-text-field__affix,
|
|
.mdc-text-field__affix {
|
|
color: var(--secondary-text-color, #9a9cb8) !important;
|
|
}
|
|
:host .mdc-line-ripple::before,
|
|
.mdc-line-ripple::before {
|
|
border-bottom-color: var(--divider-color, rgba(255, 255, 255, 0.18)) !important;
|
|
}
|
|
`;
|
|
|
|
function walkShadow(root, depth = 0) {
|
|
if (!root || depth > 8) return [];
|
|
const found = [];
|
|
try {
|
|
root.querySelectorAll('ha-textfield, ha-textarea, mwc-textfield, mwc-textarea').forEach(el => found.push(el));
|
|
root.querySelectorAll('*').forEach(el => {
|
|
if (el.shadowRoot) found.push(...walkShadow(el.shadowRoot, depth + 1));
|
|
});
|
|
} catch (e) {}
|
|
return found;
|
|
}
|
|
|
|
function injectInto(textfield) {
|
|
if (!textfield || textfield.__assistFixDone) return;
|
|
textfield.__assistFixDone = true;
|
|
const sr = textfield.shadowRoot;
|
|
if (!sr) return;
|
|
const style = document.createElement('style');
|
|
style.textContent = css;
|
|
sr.appendChild(style);
|
|
// Also patch the nested mwc-textfield if present
|
|
walkShadow(sr).forEach(tf => {
|
|
if (tf !== textfield && !tf.__assistFixDone && tf.shadowRoot) {
|
|
tf.__assistFixDone = true;
|
|
const s = document.createElement('style');
|
|
s.textContent = css;
|
|
tf.shadowRoot.appendChild(s);
|
|
}
|
|
});
|
|
}
|
|
|
|
function scan() {
|
|
// Look for any Assist dialog in the DOM
|
|
const dialogs = document.querySelectorAll(
|
|
'ha-voice-command-dialog, dialog-voice-command-dialog, ha-conversation-dialog'
|
|
);
|
|
dialogs.forEach(d => {
|
|
if (d.shadowRoot) walkShadow(d.shadowRoot).forEach(injectInto);
|
|
});
|
|
// Also scan root-level more-info dialogs that might host textfields
|
|
if (document.body) {
|
|
walkShadow(document.body).forEach(injectInto);
|
|
}
|
|
}
|
|
|
|
// Run on mutations (dialog opens / closes)
|
|
const obs = new MutationObserver(() => scan());
|
|
obs.observe(document.body || document.documentElement, {
|
|
childList: true,
|
|
subtree: true,
|
|
});
|
|
|
|
// Initial pass + periodic sweep for first 30s (covers page-load races)
|
|
let passes = 0;
|
|
const interval = setInterval(() => {
|
|
scan();
|
|
if (++passes > 30) clearInterval(interval);
|
|
}, 1000);
|
|
scan();
|
|
|
|
console.log('[assist-fix] loaded');
|
|
})();
|