Skip to content

Commit

Permalink
More climate card fixes + More
Browse files Browse the repository at this point in the history
- [x] Possibility to hide target_temp_low or target_temp_high temperature controls. #877
- [x] The climate card color is now changing correctly based on if its actually cooling or heating. #923
- [x] The climate card buttons now change temperature after a delay when there is multiple buttons push to avoid multiples API calls. #877
- [x] When setting actions to a card or a sub-button, now if there is no entity defined in the sub-button actions, it will automatically take the sub-button entity for the action, and if there is no entity in the sub-button it will automatically take the card entity. This allow less YAML and easier configs. #926
- [x] It was impossible to change a select sub-button icon when an attribute with icons was set (like for the HVAC modes sub-button), this is now fixed! #924
- [x] Some styles improvements on the media player card.
  • Loading branch information
Clooos authored Nov 17, 2024
1 parent 6ea6046 commit 6f0734e
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 144 deletions.
26 changes: 24 additions & 2 deletions dist/bubble-card.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/bubble-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ class BubbleCard extends HTMLElement {

disconnectedCallback() {
this.isConnected = false;

if (this._hass && !this.justDisconnected) {
this.updateBubbleCard();
}
}

set editMode(editMode) {
Expand All @@ -50,6 +46,8 @@ class BubbleCard extends HTMLElement {

this._hass = hass;

if (this.editor) return;

if (this.isConnected || this.config.card_type === 'pop-up') {
this.updateBubbleCard();
}
Expand Down Expand Up @@ -186,6 +184,8 @@ class BubbleCard extends HTMLElement {
return 1;
case 'select':
return 1;
case 'climate':
return 1;
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/cards/climate/changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,20 @@ export function changeTemperature(context) {

export function changeTargetTempLow(context) {
const targetTempLow = getAttribute(context, "target_temp_low");
const hideTargetTempLow = context.config.hide_target_temp_low;

if (targetTempLow === '') {
context.elements.targetTemperatureContainer?.classList.add('hidden');
} else {
context.elements.targetTemperatureContainer?.classList.remove('hidden');
}

if (hideTargetTempLow) {
context.elements.lowTempContainer?.classList.add('hidden');
} else {
context.elements.lowTempContainer?.classList.remove('hidden');
}

if (targetTempLow !== context.previousTargetTempLow) {
context.previousTargetTempLow = targetTempLow;
if (context.elements.lowTempDisplay) {
Expand All @@ -96,6 +103,14 @@ export function changeTargetTempLow(context) {

export function changeTargetTempHigh(context) {
const targetTempHigh = getAttribute(context, "target_temp_high");
const hideTargetTempHigh = context.config.hide_target_temp_high;

if (hideTargetTempHigh) {
context.elements.highTempContainer?.classList.add('hidden');
} else {
context.elements.highTempContainer?.classList.remove('hidden');
}

if (targetTempHigh !== context.previousTargetTempHigh) {
context.previousTargetTempHigh = targetTempHigh;
if (context.elements.highTempDisplay) {
Expand Down
43 changes: 39 additions & 4 deletions src/cards/climate/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,51 @@ export function createStructure(context) {
container.appendChild(tempDisplay);
container.appendChild(plusButton);

let tempTimeout;
let currentTemp = parseFloat(getAttribute(context, attribute)) || 0;

function updateTempDisplay(newTemp) {
if (attribute === 'temperature') {
context.elements.tempDisplay.innerText = newTemp.toFixed(1);
} else if (attribute === 'target_temp_low') {
context.elements.lowTempDisplay.innerText = newTemp.toFixed(1);
} else if (attribute === 'target_temp_high') {
context.elements.highTempDisplay.innerText = newTemp.toFixed(1);
}
}

function callSetTemperature() {
const serviceData = { entity_id: context.config.entity };

if (attribute === 'target_temp_low') {
serviceData.target_temp_low = currentTemp;
serviceData.target_temp_high = getAttribute(context, 'target_temp_high');
} else if (attribute === 'target_temp_high') {
serviceData.target_temp_high = currentTemp;
serviceData.target_temp_low = getAttribute(context, 'target_temp_low');
} else {
serviceData[attribute] = currentTemp;
}

context._hass.callService('climate', 'set_temperature', serviceData);
}

minusButton.addEventListener('click', () => {
let currentTemp = parseFloat(getAttribute(context, attribute)) || 0;
currentTemp = parseFloat((currentTemp - step).toFixed(1));
adjustTemperature(attribute, currentTemp);
updateTempDisplay(currentTemp);

clearTimeout(tempTimeout);

tempTimeout = setTimeout(callSetTemperature, 700);
});

plusButton.addEventListener('click', () => {
let currentTemp = parseFloat(getAttribute(context, attribute)) || 0;
currentTemp = parseFloat((currentTemp + step).toFixed(1));
adjustTemperature(attribute, currentTemp);
updateTempDisplay(currentTemp);

clearTimeout(tempTimeout);

tempTimeout = setTimeout(callSetTemperature, 700);
});
}

Expand Down
74 changes: 7 additions & 67 deletions src/cards/climate/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,15 @@ import {
isEntityType
} from "../../tools/utils.ts";

// export function getClimateColor(stateObj) {
// let overlayColor = '';

// // Récupération des températures actuelles et cibles
// const currentTemp = stateObj.attributes.current_temperature;
// const targetTemp = stateObj.attributes.temperature;
// const targetTempLow = stateObj.attributes.target_temp_low;
// const targetTempHigh = stateObj.attributes.target_temp_high;
// const state = stateObj.state;

// switch (state) {
// case "heat":
// overlayColor = 'var(--state-climate-heat-color, var(--state-climate-active-color, var(--state-active-color)))';
// break;
// case "cool":
// overlayColor = 'var(--state-climate-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
// break;
// case "fan_only":
// overlayColor = 'var(--state-climate-fan-only-color, var(--state-climate-active-color, var(--state-active-color)))';
// break;
// case "dry":
// overlayColor = 'var(--state-climate-dry-color, var(--state-climate-active-color, var(--state-active-color)))';
// break;
// case "auto":
// overlayColor = 'var(--state-climate-auto-color, var(--state-climate-active-color, var(--state-active-color)))';
// break;
// case "heat_cool":
// if (currentTemp !== undefined) {
// if (targetTemp !== undefined) {
// overlayColor = currentTemp > targetTemp
// ? 'var(--state-climate-cool-color, var(--state-climate-active-color, var(--state-active-color)))'
// : 'var(--state-climate-heat-color, var(--state-climate-active-color, var(--state-active-color)))';
// }
// else if (targetTempLow !== undefined && targetTempHigh !== undefined) {
// overlayColor = currentTemp > targetTempHigh
// ? 'var(--state-climate-cool-color, var(--state-climate-active-color, var(--state-active-color)))'
// : (currentTemp < targetTempLow
// ? 'var(--state-climate-heat-color, var(--state-climate-active-color, var(--state-active-color)))'
// : 'var(--state-climate-heat-cool-color, var(--state-climate-active-color, var(--state-active-color)))');
// } else {
// overlayColor = 'var(--state-climate-heat-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
// }
// } else {
// overlayColor = 'var(--state-climate-heat-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
// }
// break;
// default:
// overlayColor = 'rgba(0, 0, 0, 0)';
// break;
// }

// return overlayColor;
// }

export function getClimateColor(stateObj) {
let overlayColor = '';

const currentTemp = stateObj.attributes.current_temperature;
const targetTemp = stateObj.attributes.temperature;
const targetTempLow = stateObj.attributes.target_temp_low;
const targetTempHigh = stateObj.attributes.target_temp_high;
const hvacAction = stateObj.attributes.hvac_action;
const state = stateObj.state;

const isHeating = targetTemp !== undefined ? currentTemp < targetTemp : currentTemp < targetTempLow;
const isCooling = targetTemp !== undefined ? currentTemp > targetTemp : currentTemp > targetTempHigh;
const isHeating = hvacAction === 'heating';
const isCooling = hvacAction === 'cooling';

switch (state) {
case "heat":
Expand All @@ -82,14 +26,10 @@ export function getClimateColor(stateObj) {
: '';
break;
case "heat_cool":
if (currentTemp !== undefined) {
if (isCooling) {
overlayColor = 'var(--state-climate-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
} else if (isHeating) {
overlayColor = 'var(--state-climate-heat-color, var(--state-climate-active-color, var(--state-active-color)))';
} else {
overlayColor = 'var(--state-climate-heat-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
}
if (isCooling) {
overlayColor = 'var(--state-climate-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
} else if (isHeating) {
overlayColor = 'var(--state-climate-heat-color, var(--state-climate-active-color, var(--state-active-color)))';
} else {
overlayColor = '';
}
Expand Down
5 changes: 1 addition & 4 deletions src/cards/climate/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ export default `
.bubble-target-temperature-container {
display: flex;
}
.bubble-low-temp-container {
margin-right: 8px;
gap: 10px;
}
.bubble-climate-minus-button,
Expand Down
24 changes: 13 additions & 11 deletions src/cards/media-player/changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,17 +161,19 @@ export function changePowerIcon(context) {
}

export function changeVolumeIcon(context) {
if (context.elements.volumeButton.isHidden) {
context.elements.volumeButton.setAttribute("icon", "mdi:volume-high");
context.elements.mediaInfoContainer.style.opacity = '1';
context.elements.nameContainer.style.opacity = '1';
context.elements.volumeButton.isHidden = false;
} else {
context.elements.volumeButton.setAttribute("icon", "mdi:close");
context.elements.mediaInfoContainer.style.opacity = '0';
context.elements.nameContainer.style.opacity = '0';
context.elements.volumeButton.isHidden = true;
}
const isHidden = context.elements.volumeButton.isHidden;
const newOpacity = isHidden ? '1' : '0';
const newIcon = isHidden ? "mdi:volume-high" : "mdi:close";

context.elements.volumeButton.setAttribute("icon", newIcon);
context.elements.mediaInfoContainer.style.opacity = newOpacity;
context.elements.nameContainer.style.opacity = newOpacity;
context.elements.subButtonContainer.style.opacity = newOpacity;
context.elements.previousButton.style.opacity = newOpacity;
context.elements.nextButton.style.opacity = newOpacity;
context.elements.powerButton.style.opacity = newOpacity;

context.elements.volumeButton.isHidden = !isHidden;
}

export function changeMuteIcon(context) {
Expand Down
3 changes: 1 addition & 2 deletions src/cards/media-player/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ export default `
height: 42px;
border-radius: var(--bubble-media-player-border-radius, var(--bubble-border-radius, 32px));
left: 60px;
width: calc(100% - 174px);
width: calc(100% - 168px);
}
.large .bubble-range-value {
Expand All @@ -308,7 +308,6 @@ export default `
.large .bubble-button-container {
align-items: center;
gap: 14px;
}
.rows-2 .bubble-sub-button-container {
Expand Down
70 changes: 36 additions & 34 deletions src/cards/pop-up/changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,62 @@ import { initializesubButtonIcon } from '../../tools/global-changes.ts';
export function changeEditor(context) {
if (!context.verticalStack) return;

const host = context.verticalStack.host;
const detectedEditor = host?.closest('hui-card-preview') ||
host?.closest('hui-card[preview][class]') ||
host?.getRootNode().host?.closest('hui-section[preview][class]');
const { host } = context.verticalStack;
const { popUp, sectionRow, sectionRowContainer, elements } = context;

const popUp = context.popUp;
const sectionRow = context.sectionRow;
const sectionRowContainer = context.sectionRowContainer;
const elements = context.elements;
// Cache detectedEditor and flags for performance
const detectedEditor = context._cachedDetectedEditor ??= (
host?.closest('hui-card-preview') ||
host?.closest('hui-card[preview][class]') ||
host?.getRootNode().host?.closest('hui-section[preview][class]')
);

const isPopUpOpened = popUp?.classList.contains('is-popup-opened');
const isCard = sectionRow.tagName.toLowerCase() === 'hui-card';
const isCard = sectionRow?.tagName.toLowerCase() === 'hui-card';

context.previousEditorState = context.previousEditorState ?? null;
context.previousDetectedEditor = context.previousDetectedEditor ?? null;
// Initialize previous states if undefined
context.previousEditorState ??= null;
context.previousDetectedEditor ??= null;

// Fix the empty space caused by the pop-ups in the section view
// Optimize DOM manipulations for hidden attribute and display style
if (!isPopUpOpened && isCard) {
if (!context.editor && context.editorAccess && !detectedEditor) {
if (sectionRow.style.display !== "none") {
sectionRow.toggleAttribute("hidden", true);
sectionRow.style.display = "none";
}
} else if (sectionRowContainer?.classList.contains('card') && context.editor) {
if (sectionRowContainer.style.display !== '') {
sectionRowContainer.style.display = '';
}
const { editor, editorAccess } = context;

if (!editor && editorAccess && !detectedEditor && !sectionRow?.hasAttribute("hidden")) {
sectionRow.setAttribute("hidden", "");
sectionRow.style.display = "none";
} else if (sectionRowContainer?.classList.contains('card') && editor && sectionRowContainer.style.display === "none") {
sectionRowContainer.style.display = '';
}
}

// Change the pop-up style for the editor
if (context.editor || detectedEditor !== null) {
if (!popUp.classList.contains('editor')) {
// Avoid redundant style updates for the pop-up
const popUpClasses = popUp?.classList;
const isEditorActive = context.editor || detectedEditor;

if (isEditorActive) {
if (!popUpClasses?.contains('editor')) {
document.body.style.overflow = '';
popUp?.classList.remove('is-popup-opened');
popUp?.classList.add('is-popup-closed');
popUp?.classList.add('editor');
popUpClasses?.remove('is-popup-opened');
popUpClasses?.add('is-popup-closed', 'editor');
}

context.editorAccess = true;

if (detectedEditor !== null) {
elements?.popUpContainer?.classList.remove('editor-cropped');
} else {
elements?.popUpContainer?.classList.add('editor-cropped');
// Update 'editor-cropped' class only if necessary
const shouldCrop = detectedEditor === null;
if (elements?.popUpContainer?.classList.contains('editor-cropped') !== shouldCrop) {
elements.popUpContainer.classList.toggle('editor-cropped', shouldCrop);
}
} else {
popUp?.classList.remove('editor');
if (popUpClasses?.contains('editor')) {
popUpClasses.remove('editor');
}
elements?.popUpContainer?.classList.remove('editor-cropped');
}

// Trigger editor change only if necessary
if (context.editor !== context.previousEditorState || detectedEditor !== context.previousDetectedEditor) {
onEditorChange(context);

context.previousEditorState = context.editor;
context.previousDetectedEditor = detectedEditor;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cards/select/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export function createDropdownActions(context, elements = context.elements, enti
event.stopPropagation();
event.preventDefault();

dropdownArrow.style.transform = 'rotate(0deg)'; // Revenir à la position fermée
dropdownArrow.style.transform = 'rotate(0deg)';
card.style.border = 'solid 2px rgba(0,0,0,0)';
elements.dropdownArrow.style.background = '';
};
Expand Down
Loading

0 comments on commit 6f0734e

Please sign in to comment.