diff --git a/www/community/compact-custom-header/compact-custom-header.js b/www/community/compact-custom-header/compact-custom-header.js
deleted file mode 100644
index 3734973..0000000
--- a/www/community/compact-custom-header/compact-custom-header.js
+++ /dev/null
@@ -1,3180 +0,0 @@
-console.info(
- `%c COMPACT-CUSTOM-HEADER \n%c Version 1.4.9 `,
- "color: orange; font-weight: bold; background: black",
- "color: white; font-weight: bold; background: dimgray"
-);
-
-class CompactCustomHeader {
- constructor() {
- this.LitElement = Object.getPrototypeOf(
- customElements.get("ha-panel-lovelace")
- );
- this.hass = document.querySelector("home-assistant").hass;
- this.fireEvent = (node, type, detail, options = {}) => {
- detail = detail === null || detail === undefined ? {} : detail;
- const event = new Event(type, {
- bubbles: options.bubbles === undefined ? true : options.bubbles,
- cancelable: Boolean(options.cancelable),
- composed: options.composed === undefined ? true : options.composed
- });
- event.detail = detail;
- node.dispatchEvent(event);
- return event;
- };
-
- let ll = document.querySelector("home-assistant");
- ll = ll && ll.shadowRoot;
- ll = ll && ll.querySelector("home-assistant-main");
- this.main = ll;
- ll = ll && ll.shadowRoot;
- ll = ll && ll.querySelector("app-drawer-layout partial-panel-resolver");
- this.panelResolver = ll;
- ll = (ll && ll.shadowRoot) || ll;
- ll = ll && ll.querySelector("ha-panel-lovelace");
- ll = ll && ll.shadowRoot;
- ll = ll && ll.querySelector("hui-root");
- this.lovelace = ll.lovelace;
- this.root = ll.shadowRoot;
-
- this.frontendVersion = Number(window.frontendVersion);
- this.newSidebar = this.frontendVersion >= 20190710;
- this.header = this.root.querySelector("app-header");
- this.editMode = this.header.className == "edit-mode";
- this.view = this.root.querySelector("ha-app-layout #view");
-
- this.sidebarClosed = false;
- this.firstRun = true;
- this.buttons = {};
- this.prevColor = {};
-
- this.defaultConfig = {
- header: true,
- disable: false,
- yaml_editor: false,
- menu: "show",
- voice: "show",
- notifications: "show",
- options: "show",
- clock_format: 12,
- clock_am_pm: true,
- clock_date: false,
- date_locale: this.hass.language,
- chevrons: false,
- redirect: true,
- background: "",
- hide_tabs: "",
- show_tabs: "",
- edit_mode_show_tabs: false,
- default_tab: "",
- default_tab_template: "",
- kiosk_mode: false,
- sidebar_swipe: true,
- sidebar_closed: false,
- disable_sidebar: false,
- hide_help: false,
- hide_config: false,
- hide_unused: false,
- tab_color: {},
- button_color: {},
- statusbar_color: "",
- swipe: false,
- swipe_amount: "15",
- swipe_animate: "none",
- swipe_skip: "",
- swipe_wrap: true,
- swipe_prevent_default: false,
- swipe_skip_hidden: true,
- warning: true,
- compact_header: true,
- view_css: "",
- time_css: "",
- date_css: "",
- header_css: "",
- tab_css: {},
- button_css: {}
- };
-
- this.cchConfig = this.buildConfig(
- this.lovelace.config.cch || {},
- this.hass.user.name
- );
- }
-
- run() {
- const tabContainer = this.root.querySelector("paper-tabs");
- const tabs = tabContainer
- ? Array.from(tabContainer.querySelectorAll("paper-tab"))
- : [];
- let disabled =
- window.location.href.includes("disable_cch") || this.cchConfig.disable;
-
- if (this.firstRun || this.buttons == undefined) {
- this.buttons = this.getButtonElements(tabContainer);
- }
- if (!this.buttons.menu || !this.buttons.options || this.editMode) return;
- if (!disabled) {
- this.insertEditMenu(tabs);
- this.hideMenuItems();
- this.styleHeader(tabContainer, tabs);
- this.styleButtons(tabs, tabContainer);
- if (this.firstRun) this.sidebarMod();
- this.hideTabs(tabContainer, tabs);
- for (let button in this.buttons) {
- if (this.cchConfig[button] == "clock") this.insertClock(button);
- }
- if (!this.editMode) this.tabContainerMargin(tabContainer);
- if (this.cchConfig.swipe) this.swipeNavigation(tabs, tabContainer);
- if (this.firstRun) this.defaultTab(tabs, tabContainer);
- }
- if (this.firstRun) {
- this.observers(tabContainer, tabs, disabled);
- this.breakingChangeNotification();
- }
- this.firstRun = false;
- this.fireEvent(this.header, "iron-resize");
- }
-
- buildConfig(config, user_name) {
- let exceptionConfig = {};
- let highestMatch = 0;
- // Count number of matching conditions and choose config with most matches.
- if (config.exceptions) {
- config.exceptions.forEach(exception => {
- const matches = countMatches(exception.conditions, user_name);
- if (matches > highestMatch) {
- highestMatch = matches;
- exceptionConfig = exception.config;
- }
- });
- }
- // If exception config uses hide_tabs and main config uses show_tabs,
- // delete show_tabs and vice versa.
- if (
- exceptionConfig.hide_tabs &&
- config.show_tabs &&
- exceptionConfig.hide_tabs.length &&
- config.show_tabs.length
- ) {
- delete config.show_tabs;
- } else if (
- exceptionConfig.show_tabs &&
- config.hide_tabs &&
- exceptionConfig.show_tabs.length &&
- config.hide_tabs.length
- ) {
- delete config.hide_tabs;
- }
-
- return { ...this.defaultConfig, ...config, ...exceptionConfig };
-
- function countMatches(conditions, user_name) {
- const userVars = {
- user: user_name,
- user_agent: navigator.userAgent
- };
- let count = 0;
- for (const cond in conditions) {
- if (cond == "user" && conditions[cond].includes(",")) {
- conditions[cond].split(/[ ,]+/).forEach(user => {
- if (userVars[cond] == user) count++;
- });
- } else {
- if (
- userVars[cond] == conditions[cond] ||
- (cond == "query_string" &&
- window.location.search.includes(conditions[cond])) ||
- (cond == "user_agent" &&
- userVars[cond].includes(conditions[cond])) ||
- (cond == "media_query" &&
- window.matchMedia(conditions[cond]).matches)
- ) {
- count++;
- } else {
- return 0;
- }
- }
- }
- return count;
- }
- }
-
- observers(tabContainer, tabs, disabled) {
- // Watch for changes in Lovelace.
- const callback = mutations => {
- // Theme changed.
- if (mutations[0].target.nodeName == "HTML") {
- mutations = [mutations[0]];
- this.styleHeader(tabContainer, tabs);
- this.conditionalStyling(tabs);
- return;
- }
- mutations.forEach(({ addedNodes, target }) => {
- if (addedNodes.length && target.nodeName == "PARTIAL-PANEL-RESOLVER") {
- // Navigated back to lovelace from elsewhere in HA.
- this.buttons = this.getButtonElements();
- this.run();
- } else if (target.className == "edit-mode" && addedNodes.length) {
- // Entered edit mode.
- this.editMode = true;
- if (!disabled) this.removeStyles(tabContainer, tabs, this.header);
- this.buttons.options = this.root.querySelector("paper-menu-button");
- this.insertEditMenu(tabs);
- this.fireEvent(this.header, "iron-resize");
- } else if (target.nodeName == "APP-HEADER" && addedNodes.length) {
- // Exited edit mode.
- let editor = this.root
- .querySelector("ha-app-layout")
- .querySelector("editor");
- if (editor) {
- this.root.querySelector("ha-app-layout").removeChild(editor);
- }
- for (let node of addedNodes) {
- if (node.nodeName == "APP-TOOLBAR") {
- this.editMode = false;
- this.buttons = this.getButtonElements();
- this.root.querySelectorAll("[id^='cch']").forEach(style => {
- style.remove();
- });
- setTimeout(() => {
- this.run();
- if (!disabled) this.conditionalStyling(tabs, this.header);
- }, 100);
- }
- }
- } else if (
- // Viewing unused entities
- this.frontendVersion < 20190911 &&
- addedNodes.length &&
- !addedNodes[0].nodeName == "HUI-UNUSED-ENTITIES"
- ) {
- let editor = this.root
- .querySelector("ha-app-layout")
- .querySelector("editor");
- if (editor) {
- this.root.querySelector("ha-app-layout").removeChild(editor);
- }
- if (this.cchConfig.conditional_styles) {
- this.buttons = this.getButtonElements(tabContainer);
- this.conditionalStyling(tabs, this.header);
- }
- } else if (target.id == "view" && addedNodes.length) {
- // Navigating to new tab/view.
- this.run();
- if (tabContainer) this.scrollTabIconIntoView();
- }
- });
- };
- let observer = new MutationObserver(callback);
- observer.observe(this.panelResolver, { childList: true });
- observer.observe(document.querySelector("html"), { attributes: true });
- observer.observe(this.view, { childList: true });
- observer.observe(this.root.querySelector("app-header"), {
- childList: true
- });
-
- if (!disabled) {
- // Watch for changes in entities.
- window.hassConnection.then(({ conn }) => {
- conn.socket.onmessage = () => {
- if (this.cchConfig.conditional_styles && !this.editMode) {
- this.conditionalStyling(tabs, this.header);
- }
- };
- });
- }
- }
-
- getButtonElements(disabled) {
- let buttons = {};
- buttons.options = this.root.querySelector("paper-menu-button");
- if (!this.editMode) {
- buttons.menu = this.root.querySelector("ha-menu-button");
- buttons.voice =
- this.root.querySelector("ha-start-voice-button") ||
- this.root.querySelector('[icon="hass:microphone"]');
- if (!this.newSidebar) {
- buttons.notifications = this.root.querySelector(
- "hui-notifications-button"
- );
- }
- }
- // Remove space taken up by "hidden" menu button anytime we get buttons.
- if (
- buttons.menu &&
- buttons.menu.style.visibility == "hidden" &&
- !disabled
- ) {
- buttons.menu.style.display = "none";
- } else if (buttons.menu) {
- buttons.menu.style.display = "";
- }
- return buttons;
- }
-
- tabContainerMargin(tabContainer) {
- let marginRight = 0;
- let marginLeft = 15;
- for (const button in this.buttons) {
- if (!this.buttons[button]) continue;
- let paperIconButton =
- this.buttons[button].querySelector("paper-icon-button") ||
- this.buttons[button].shadowRoot.querySelector("paper-icon-button");
- let visible = paperIconButton
- ? this.buttons[button].style.display !== "none" &&
- !paperIconButton.hasAttribute("hidden")
- : this.buttons[button].style.display !== "none";
- if (this.cchConfig[button] == "show" && visible) {
- if (button == "menu") marginLeft += 45;
- else marginRight += 45;
- } else if (this.cchConfig[button] == "clock" && visible) {
- const clockWidth =
- (this.cchConfig.clock_format == 12 && this.cchConfig.clock_am_pm) ||
- this.cchConfig.clock_date
- ? 110
- : 80;
- if (button == "menu") marginLeft += clockWidth + 15;
- else marginRight += clockWidth;
- }
- }
- if (tabContainer) {
- tabContainer.style.marginRight = `${marginRight}px`;
- tabContainer.style.marginLeft = `${marginLeft}px`;
- }
- }
-
- scrollTabIconIntoView() {
- let paperTabs = this.root.querySelector("paper-tabs");
- let currentTab = paperTabs.querySelector(".iron-selected");
- if (!paperTabs || !currentTab) return;
- let tab = currentTab.getBoundingClientRect();
- let container = paperTabs.shadowRoot
- .querySelector("#tabsContainer")
- .getBoundingClientRect();
- // If tab's icon isn't in view scroll it in.
- if (container.right < tab.right || container.left > tab.left) {
- if ("scrollMarginInline" in document.documentElement.style) {
- currentTab.scrollIntoView({ inline: "center" });
- } else if (Element.prototype.scrollIntoViewIfNeeded) {
- currentTab.scrollIntoViewIfNeeded(true);
- } else {
- currentTab.scrollIntoView();
- }
- }
- }
-
- hideMenuItems() {
- // Hide items in options menu.
- if (
- this.cchConfig.hide_help ||
- this.cchConfig.hide_config ||
- this.cchConfig.hide_unused
- ) {
- const localized = (item, string) => {
- let localString = this.hass.localize(
- `ui.panel.lovelace.menu.${string}`
- );
- return (
- item.innerHTML.includes(localString) ||
- item.getAttribute("aria-label") == localString
- );
- };
- this.buttons.options
- .querySelector("paper-listbox")
- .querySelectorAll("paper-item")
- .forEach(item => {
- if (
- (this.cchConfig.hide_help && localized(item, "help")) ||
- (this.cchConfig.hide_unused &&
- localized(item, "unused_entities")) ||
- (this.cchConfig.hide_config && localized(item, "configure_ui"))
- ) {
- item.parentNode.removeChild(item);
- }
- });
- }
- }
-
- insertEditMenu(tabs, disabled) {
- if (
- this.buttons.options &&
- (this.editMode ||
- (this.lovelace.mode == "yaml" && this.cchConfig.yaml_editor))
- ) {
- // If any tabs are hidden, add "show all tabs" option.
- if (this.cchConfig.hide_tabs && !this.cchConfig.edit_mode_show_tabs) {
- let show_tabs = document.createElement("paper-item");
- show_tabs.setAttribute("id", "show_tabs");
- show_tabs.addEventListener("click", () => {
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.removeProperty("display");
- }
- });
- show_tabs.innerHTML = "Show all tabs";
- this.insertMenuItem(
- this.buttons.options.querySelector("paper-listbox"),
- show_tabs
- );
- }
-
- // Add menu item to open CCH settings.
- let cchSettings = document.createElement("paper-item");
- cchSettings.setAttribute("id", "cch_settings");
- cchSettings.addEventListener("click", () => this.showEditor());
- cchSettings.innerHTML = "CCH Settings";
- this.insertMenuItem(
- this.buttons.options.querySelector("paper-listbox"),
- cchSettings
- );
- if (!disabled) this.hideMenuItems();
- }
- }
-
- removeStyles(tabContainer, tabs, { style }) {
- this.root.querySelector("app-header").style.backgroundColor = "#455a64";
- this.root.querySelectorAll("[id^='cch']").forEach(style => {
- style.remove();
- });
- if (this.cchConfig.tab_css) {
- for (let [key, value] of Object.entries(this.cchConfig.tab_css)) {
- key = this.getViewIndex(key);
- value = value.replace(/: /g, ":").replace(/; /g, ";");
- let css = tabs[key].style.cssText
- .replace(/: /g, ":")
- .replace(/; /g, ";");
- tabs[key].style.cssText = css.replace(value, "");
- }
- }
- if (this.cchConfig.header_css) {
- let value = this.cchConfig.header_css
- .replace(/: /g, ":")
- .replace(/; /g, ";");
- let css = style.cssText.replace(/: /g, ":").replace(/; /g, ";");
- style.cssText = css.replace(value, "");
- }
- if (tabContainer) {
- tabContainer.style.marginLeft = "";
- tabContainer.style.marginRight = "";
- }
- this.view.style = "";
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.color = "";
- }
- if (this.cchConfig.edit_mode_show_tabs) {
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.removeProperty("display");
- }
- }
- let viewStyle = document.createElement("style");
- viewStyle.setAttribute("id", "cch_view_styling");
- viewStyle.innerHTML = `
- hui-view {
- min-height: 100vh;
- }
- hui-panel-view {
- min-height: calc(100vh - 52px);
- }
- `;
- this.root.appendChild(viewStyle);
- }
-
- styleHeader(tabContainer, tabs) {
- // Fix for old background config option.
- if (typeof this.cchConfig.background == "boolean") {
- this.cchConfig.background = "";
- }
- this.prevColor.background =
- this.cchConfig.background ||
- getComputedStyle(document.body).getPropertyValue("--cch-background") ||
- getComputedStyle(document.body).getPropertyValue("--primary-color");
- let statusBarColor =
- this.cchConfig.statusbar_color || this.prevColor.background;
- // Match mobile status bar color to header color.
- let themeColor = document.querySelector('[name="theme-color"]');
- let themeColorApple =
- document.querySelector(
- '[name="apple-mobile-web-app-status-bar-style"]'
- ) || document.createElement("meta");
- colorStatusBar(statusBarColor);
- // If browser is idle or in background sometimes theme-color needs reset.
- let observeStatus = new MutationObserver(() => {
- if (themeColor.content != statusBarColor) colorStatusBar(statusBarColor);
- });
- if (this.firstRun) {
- observeStatus.observe(themeColor, {
- attributes: true,
- attributeFilter: ["content"]
- });
- }
-
- // Adjust view size & padding for new header size.
- if (!this.cchConfig.header || this.cchConfig.kiosk_mode) {
- this.header.style.display = "none";
- this.view.style.minHeight = "100vh";
- if (
- this.frontendVersion >= 20190911 &&
- !this.root.querySelector("#cch_view_styling")
- ) {
- let viewStyle = document.createElement("style");
- viewStyle.setAttribute("id", "cch_view_styling");
- viewStyle.innerHTML = `
- hui-view {
- ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
- }
- hui-panel-view {
- ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
- }
- `;
- this.root.appendChild(viewStyle);
- }
- } else {
- this.view.style.minHeight = "100vh";
- this.view.style.marginTop = "-48.5px";
- this.view.style.paddingTop = "48.5px";
- this.view.style.boxSizing = "border-box";
- this.header.style.background = this.prevColor.background;
- this.conditionalStyling(tabs, this.header);
- this.header.querySelector("app-toolbar").style.background = "transparent";
- if (
- this.frontendVersion >= 20190911 &&
- !this.root.querySelector("#cch_view_styling")
- ) {
- let viewStyle = document.createElement("style");
- viewStyle.setAttribute("id", "cch_view_styling");
- viewStyle.innerHTML = `
- hui-view {
- margin-top: -48.5px;
- padding-top: 52px;
- min-height: 100vh;
- ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
- }
- hui-panel-view {
- margin-top: -52px;
- padding-top: 52px;
- min-height: calc(100vh - 52px);
- ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
- }
- `;
- this.root.appendChild(viewStyle);
- }
- }
-
- // Match sidebar elements to header's size.
- if (this.newSidebar && this.cchConfig.compact_header) {
- let sidebar = this.main.shadowRoot.querySelector("ha-sidebar").shadowRoot;
- sidebar.querySelector(".menu").style = "height:49px;";
- sidebar.querySelector("paper-listbox").style =
- "height:calc(100% - 180px);";
- }
-
- // Current tab icon color.
- let conditionalTabs = this.cchConfig.conditional_styles
- ? JSON.stringify(this.cchConfig.conditional_styles).includes("tab")
- : false;
- if (
- !this.root.querySelector("#cch_iron_selected") &&
- !this.editMode &&
- !conditionalTabs &&
- tabContainer
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_iron_selected");
- style.innerHTML = `
- .iron-selected {
- ${
- this.cchConfig.active_tab_color
- ? `color: ${`${
- this.cchConfig.active_tab_color
- } !important`}`
- : "var(--cch-active-tab-color)"
- }
- }
- `;
- tabContainer.appendChild(style);
- }
-
- // Style current tab indicator.
- let indicator = this.cchConfig.tab_indicator_color;
- if (
- indicator &&
- !this.root.querySelector("#cch_header_colors") &&
- !this.editMode
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_header_colors");
- style.innerHTML = `
- paper-tabs {
- ${
- indicator
- ? `--paper-tabs-selection-bar-color: ${indicator} !important`
- : "var(--cch-tab-indicator-color) !important"
- }
- }
- `;
- this.root.appendChild(style);
- }
-
- // Tab's icon color.
- let all_tabs_color =
- this.cchConfig.all_tabs_color || "var(--cch-all-tabs-color)";
- if (
- (this.cchConfig.tab_color &&
- Object.keys(this.cchConfig.tab_color).length) ||
- all_tabs_color
- ) {
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.color = this.cchConfig.tab_color[i] || all_tabs_color;
- }
- }
-
- // Add custom css.
- if (this.cchConfig.tab_css) {
- for (let [key, value] of Object.entries(this.cchConfig.tab_css)) {
- key = this.getViewIndex(key);
- if (tabs[key]) tabs[key].style.cssText += value;
- }
- }
- if (this.cchConfig.header_css)
- this.header.style.cssText += this.cchConfig.header_css;
- if (this.cchConfig.view_css && this.frontendVersion < 20190911) {
- this.view.style.cssText += this.cchConfig.view_css;
- }
-
- if (tabContainer) {
- // Shift the header up to hide unused portion.
- this.root.querySelector("app-toolbar").style.marginTop = this.cchConfig
- .compact_header
- ? "-64px"
- : "";
-
- tabs.forEach(({ style }) => {
- style.marginTop = "-1px";
- });
-
- // Show/hide tab navigation chevrons.
- if (!this.cchConfig.chevrons) {
- let chevron = tabContainer.shadowRoot.querySelectorAll(
- '[icon^="paper-tabs:chevron"]'
- );
- chevron[0].style.display = "none";
- chevron[1].style.display = "none";
- } else {
- // Remove space taken up by "not-visible" chevron.
- let style = document.createElement("style");
- style.setAttribute("id", "cch_chevron");
- style.innerHTML = `
- .not-visible {
- display:none;
- }
- `;
- tabContainer.shadowRoot.appendChild(style);
- }
- }
- function colorStatusBar(statusBarColor) {
- themeColor = document.querySelector("meta[name=theme-color]");
- themeColor.setAttribute("content", statusBarColor);
- themeColor.setAttribute("default-content", statusBarColor);
- if (
- !document.querySelector(
- '[name="apple-mobile-web-app-status-bar-style"]'
- )
- ) {
- themeColorApple.name = "apple-mobile-web-app-status-bar-style";
- themeColorApple.content = statusBarColor;
- document.getElementsByTagName("head")[0].appendChild(themeColorApple);
- } else {
- themeColorApple.setAttribute("content", statusBarColor);
- }
- }
- }
-
- styleButtons({ length }, tabContainer) {
- let topMargin =
- length > 0 && this.cchConfig.compact_header ? "margin-top:111px;" : "";
- let topMarginMenu =
- length > 0 && this.cchConfig.compact_header ? "margin-top:115px;" : "";
- // Reverse buttons object so "menu" is first in the overflow menu.
- this.buttons = this.reverseObject(this.buttons);
- for (const button in this.buttons) {
- if (!this.buttons[button]) continue;
- if (button == "options" && this.cchConfig[button] == "overflow") {
- this.cchConfig[button] = "show";
- }
- let buttonStyle = `
- z-index:1;
- ${
- button == "menu"
- ? `padding: 8px 0; margin-bottom:5px; ${topMarginMenu}`
- : "padding: 8px;"
- }
- ${
- button == "voice" && this.cchConfig["voice"] == "clock"
- ? "width: 100px; padding:4px;"
- : ""
- }
- ${button == "menu" ? "" : topMargin}
- ${button == "options" ? "margin-right:-5px;" : ""}
- `;
- if (
- this.cchConfig[button] == "show" ||
- this.cchConfig[button] == "clock"
- ) {
- if (button == "menu") {
- let paperIconButton = this.buttons[button].querySelector(
- "paper-icon-button"
- )
- ? this.buttons[button].querySelector("paper-icon-button")
- : this.buttons[button].shadowRoot.querySelector(
- "paper-icon-button"
- );
- if (!paperIconButton) continue;
- paperIconButton.style.cssText = buttonStyle;
- } else {
- this.buttons[button].style.cssText = buttonStyle;
- }
- } else if (this.cchConfig[button] == "overflow") {
- const menu_items = this.buttons.options.querySelector("paper-listbox");
- let paperIconButton = this.buttons[button].querySelector(
- "paper-icon-button"
- )
- ? this.buttons[button].querySelector("paper-icon-button")
- : this.buttons[button].shadowRoot.querySelector("paper-icon-button");
- if (paperIconButton && paperIconButton.hasAttribute("hidden")) {
- continue;
- }
- const id = `menu_item_${button}`;
- if (!menu_items.querySelector(`#${id}`)) {
- const wrapper = document.createElement("paper-item");
- wrapper.setAttribute("id", id);
- wrapper.innerText = this.getTranslation(button);
- wrapper.appendChild(this.buttons[button]);
- wrapper.addEventListener("click", () => {
- paperIconButton.click();
- });
- paperIconButton.style.pointerEvents = "none";
- this.insertMenuItem(menu_items, wrapper);
- if (button == "notifications" && !this.newSidebar) {
- let style = document.createElement("style");
- style.innerHTML = `
- .indicator {
- top: 5px;
- right: 0px;
- width: 10px;
- height: 10px;
- ${
- this.cchConfig.notify_indicator_color
- ? `background-color:${
- this.cchConfig.notify_indicator_color
- }`
- : ""
- }
- }
- .indicator > div{
- display:none;
- }
- `;
- paperIconButton.parentNode.appendChild(style);
- }
- }
- } else if (this.cchConfig[button] == "hide") {
- this.buttons[button].style.display = "none";
- }
- // Hide menu button if hiding the sidebar.
- if (
- this.newSidebar &&
- (this.cchConfig.kiosk_mode || this.cchConfig.disable_sidebar)
- ) {
- this.buttons.menu.style.display = "none";
- }
- }
-
- // Remove empty space taken up by hidden menu button.
- if (this.buttons.menu && this.newSidebar && this.firstRun) {
- new MutationObserver(() => {
- if (this.buttons.menu.style.visibility == "hidden") {
- this.buttons.menu.style.display = "none";
- } else {
- this.buttons.menu.style.display = "";
- }
- this.tabContainerMargin(tabContainer);
- }).observe(this.buttons.menu, {
- attributes: true,
- attributeFilter: ["style"]
- });
- }
-
- // Use color vars set in HA theme.
- this.buttons.menu.style.color = "var(--cch-button-color-menu)";
- if (!this.newSidebar) {
- this.buttons.notifications.style.color =
- "var(--cch-button-color-notifications)";
- }
- if (this.buttons.voice) this.buttons.voice.style.color = "var(--cch-button-color-voice)";
- this.buttons.options.style.color = "var(--cch-button-color-options)";
- if (this.cchConfig.all_buttons_color) {
- this.root.querySelector("app-toolbar").style.color =
- this.cchConfig.all_buttons_color || "var(--cch-all-buttons-color)";
- }
-
- // Use colors set in CCH config.
- for (const button in this.buttons) {
- if (this.cchConfig.button_color[button]) {
- this.buttons[button].style.color = this.cchConfig.button_color[button];
- }
- }
-
- // Notification indicator's color for HA 0.96 and above.
- if (
- this.newSidebar &&
- this.cchConfig.menu != "hide" &&
- !this.buttons.menu.shadowRoot.querySelector("#cch_dot")
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_dot");
- let indicator =
- this.cchConfig.notify_indicator_color ||
- getComputedStyle(this.header).getPropertyValue(
- "--cch-tab-indicator-color"
- ) ||
- "";
- let border = getComputedStyle(this.header)
- .getPropertyValue("background")
- .includes("url")
- ? "border-color: transparent !important"
- : `border-color: ${getComputedStyle(this.header).getPropertyValue(
- "background-color"
- )} !important;`;
- style.innerHTML = `
- .dot {
- ${topMargin}
- z-index: 2;
- ${indicator ? `background: ${indicator} !important` : ""}
- ${border}
- }
- `;
- this.buttons.menu.shadowRoot.appendChild(style);
- } else if (
- // Notification indicator's color for HA 0.95 and below.
- this.cchConfig.notify_indicator_color &&
- this.cchConfig.notifications == "show" &&
- !this.newSidebar
- ) {
- let style = document.createElement("style");
- style.innerHTML = `
- .indicator {
- background-color:${this.cchConfig.notify_indicator_color ||
- "var(--cch-notify-indicator-color)"} !important;
- color: ${this.cchConfig.notify_text_color ||
- "var(--cch-notify-text-color), var(--primary-text-color)"};
- }
- `;
- this.buttons.notifications.shadowRoot.appendChild(style);
- }
-
- // Add buttons's custom css.
- let buttonCss = this.cchConfig.button_css;
- if (buttonCss) {
- for (const [key, value] of Object.entries(buttonCss)) {
- if (!this.buttons[key]) {
- continue;
- } else {
- this.buttons[key].style.cssText += value;
- }
- }
- }
- }
-
- getTranslation(button) {
- switch (button) {
- case "notifications":
- return this.hass.localize("ui.notification_drawer.title");
- default:
- return button.charAt(0).toUpperCase() + button.slice(1);
- }
- }
-
- defaultTab(tabs, tabContainer) {
- let firstTab = tabs.indexOf(tabs.filter(tab => tab.style.display == "")[0]);
- let default_tab = this.cchConfig.default_tab;
- if (typeof default_tab == "object" && !default_tab.length) return;
- let template = this.cchConfig.default_tab_template;
- if ((default_tab || template) && tabContainer) {
- if (template) default_tab = this.templateEval(template, this.hass.states);
- default_tab = this.getViewIndex(default_tab);
- let activeTab = tabs.indexOf(
- tabContainer.querySelector(".iron-selected")
- );
- if (
- activeTab != default_tab &&
- activeTab == firstTab &&
- (!this.cchConfig.redirect ||
- (this.cchConfig.redirect &&
- tabs[default_tab].style.display != "none"))
- ) {
- tabs[default_tab].click();
- }
- }
- }
-
- sidebarMod() {
- let menu = this.buttons.menu.querySelector("paper-icon-button");
- let sidebar = this.main.shadowRoot.querySelector("app-drawer");
-
- // HA 0.95 and below
- if (!this.newSidebar) {
- if (!this.cchConfig.sidebar_swipe || this.cchConfig.kiosk_mode) {
- sidebar.removeAttribute("swipe-open");
- }
- if (
- (this.cchConfig.sidebar_closed || this.cchConfig.kiosk_mode) &&
- !this.sidebarClosed
- ) {
- if (sidebar.hasAttribute("opened")) menu.click();
- this.sidebarClosed = true;
- }
- // HA 0.96 and above
- } else if (this.cchConfig.disable_sidebar || this.cchConfig.kiosk_mode) {
- sidebar.style.display = "none";
- sidebar.addEventListener(
- "mouseenter",
- event => {
- event.stopPropagation();
- },
- true
- );
- let style = document.createElement("style");
- style.type = "text/css";
- style.appendChild(
- document.createTextNode(
- ":host(:not([expanded])) {width: 0px !important;}"
- )
- );
- this.main.shadowRoot
- .querySelector("ha-sidebar")
- .shadowRoot.appendChild(style);
-
- style = document.createElement("style");
- style.type = "text/css";
- style.appendChild(
- document.createTextNode(":host {--app-drawer-width: 0px !important;}")
- );
- this.main.shadowRoot.appendChild(style);
- }
- }
-
- hideTabs(tabContainer, tabs) {
- let hidden_tabs = String(this.cchConfig.hide_tabs).length
- ? String(this.cchConfig.hide_tabs)
- .replace(/\s+/g, "")
- .split(",")
- : null;
- let shown_tabs = String(this.cchConfig.show_tabs).length
- ? String(this.cchConfig.show_tabs)
- .replace(/\s+/g, "")
- .split(",")
- : null;
-
- // Set the tab config source.
- if (!hidden_tabs && shown_tabs) {
- let all_tabs = [];
- shown_tabs = this.buildRanges(shown_tabs);
- for (let i = 0; i < tabs.length; i++) all_tabs.push(i);
- // Invert shown_tabs to hidden_tabs.
- hidden_tabs = all_tabs.filter(el => !shown_tabs.includes(el));
- } else {
- hidden_tabs = this.buildRanges(hidden_tabs);
- }
-
- // Hide tabs.
- for (const tab of hidden_tabs) {
- if (!tabs[tab]) continue;
- tabs[tab].style.display = "none";
- }
-
- if (this.cchConfig.redirect && tabContainer) {
- const activeTab = tabContainer.querySelector("paper-tab.iron-selected");
- const activeTabIndex = tabs.indexOf(activeTab);
- // Is the current tab hidden and is there at least one tab is visible.
- if (
- hidden_tabs.includes(activeTabIndex) &&
- hidden_tabs.length != tabs.length
- ) {
- let i = 0;
- // Find the first visible tab and navigate.
- while (hidden_tabs.includes(i)) {
- i++;
- }
- tabs[i].click();
- }
- }
- return hidden_tabs;
- }
-
- insertMenuItem(menu_items, element) {
- let first_item = menu_items.querySelector("paper-item");
- if (!menu_items.querySelector(`#${element.id}`)) {
- first_item.parentNode.insertBefore(element, first_item);
- }
- }
-
- insertClock(button) {
- if (!this.buttons[button]) return;
- const clock_button = this.buttons[button].querySelector("paper-icon-button")
- ? this.buttons[button]
- : this.buttons[button].shadowRoot;
- const clockIcon =
- clock_button.querySelector("paper-icon-button") || this.buttons[button];
- const clockIronIcon =
- clockIcon.querySelector("iron-icon") ||
- clockIcon.shadowRoot.querySelector("iron-icon");
- const clockWidth =
- (this.cchConfig.clock_format == 12 && this.cchConfig.clock_am_pm) ||
- this.cchConfig.clock_date
- ? 105
- : 80;
-
- if (
- !this.newSidebar &&
- this.cchConfig.notifications == "clock" &&
- this.cchConfig.clock_date &&
- !this.buttons.notifications.shadowRoot.querySelector("#cch_indicator")
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_indicator");
- style.innerHTML = `
- .indicator {
- top: unset;
- bottom: -3px;
- right: 0px;
- width: 90%;
- height: 3px;
- border-radius: 0;
- ${
- this.cchConfig.notify_indicator_color
- ? `background-color:${this.cchConfig.notify_indicator_color}`
- : ""
- }
- }
- .indicator > div{
- display:none;
- }
- `;
- this.buttons.notifications.shadowRoot.appendChild(style);
- }
-
- let clockElement = clockIronIcon.parentNode.getElementById("cch_clock");
- if (this.cchConfig.menu == "clock") {
- this.buttons.menu.style.marginTop = this.cchConfig.compact_header
- ? "111px"
- : "";
- this.buttons.menu.style.zIndex = "1";
- }
- if (!clockElement) {
- clockIcon.style.cssText = `
- margin-right:-5px;
- width:${clockWidth}px;
- text-align: center;
- `;
- clockElement = document.createElement("p");
- clockElement.setAttribute("id", "cch_clock");
- let clockAlign = "center";
- let padding = "";
- let fontSize = "";
- if (this.cchConfig.clock_date && this.cchConfig.menu == "clock") {
- clockAlign = "left";
- padding = "margin-right:-20px";
- fontSize = "font-size:12pt";
- } else if (this.cchConfig.clock_date) {
- clockAlign = "right";
- padding = "margin-left:-20px";
- fontSize = "font-size:12pt";
- }
- clockElement.style.cssText = `
- margin-top: ${this.cchConfig.clock_date ? "-4px" : "2px"};
- text-align: ${clockAlign};
- ${padding};
- ${fontSize};
- `;
- clockIronIcon.parentNode.insertBefore(clockElement, clockIronIcon);
- clockIronIcon.style.display = "none";
- let style = document.createElement("style");
- style.setAttribute("id", "cch_clock");
- style.innerHTML = `
- time {
- ${this.cchConfig.time_css}
- }
- date {
- ${this.cchConfig.date_css}
- }
- `;
- clockIronIcon.parentNode.insertBefore(style, clockIronIcon);
- }
-
- const clockFormat = {
- hour12: this.cchConfig.clock_format != 24,
- hour: "2-digit",
- minute: "2-digit"
- };
- this.updateClock(clockElement, clockFormat);
- }
-
- updateClock(clock, clockFormat) {
- let date = new Date();
- let seconds = date.getSeconds();
- let locale = this.cchConfig.date_locale || this.hass.language;
- let time = date.toLocaleTimeString([], clockFormat);
- let options = {
- weekday: "short",
- month: "2-digit",
- day: "2-digit"
- };
- date = this.cchConfig.clock_date
- ? `
${cch.hass.user.name}
-