Skip to content

Commit

Permalink
More climate card fixes + Various fixes
Browse files Browse the repository at this point in the history
- [x] Toggle in the editor for enabling or disabling sub-button background color based on light color. E.g: `light_background: false`
- [x] The climate card color is now changing only when it is actually cooling or heating.
- [x] Slider card with fan 'preset_modes' sub-button does not actually set the preset #920
- [x] Climate Card Shows Multiple Set Temperature Groups #917
- [x] The editor should be faster on some setups/browsers.
  • Loading branch information
Clooos authored Nov 15, 2024
1 parent a8e6bde commit 736f48e
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 115 deletions.
86 changes: 49 additions & 37 deletions dist/bubble-card.js

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/bubble-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import { handleSelect } from './cards/select/index.ts';
import { handleClimate } from './cards/climate/index.ts';
import { createBubbleCardEditor } from './editor/bubble-card-editor.ts';

let editor;

class BubbleCard extends HTMLElement {
editor = false;
isConnected;
isConnected = false;

connectedCallback() {
this.isConnected = true;
Expand Down
22 changes: 18 additions & 4 deletions src/cards/climate/changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,31 @@ export function changeStatus(context) {
}

export function changeTemperature(context) {
const currentTemp = getAttribute(context, "temperature");
if (currentTemp !== context.previousTemp) {
context.previousTemp = currentTemp;
const temperature = getAttribute(context, "temperature");

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

if (temperature !== context.previousTemp) {
context.previousTemp = temperature;
if (context.elements.tempDisplay) {
context.elements.tempDisplay.innerText = parseFloat(currentTemp).toFixed(1);
context.elements.tempDisplay.innerText = parseFloat(temperature).toFixed(1);
}
}
}

export function changeTargetTempLow(context) {
const targetTempLow = getAttribute(context, "target_temp_low");

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

if (targetTempLow !== context.previousTargetTempLow) {
context.previousTargetTempLow = targetTempLow;
if (context.elements.lowTempDisplay) {
Expand Down
85 changes: 51 additions & 34 deletions src/cards/climate/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import {
isEntityType
} from "../../tools/utils.ts";

// export function getClimateColor(state) {
// 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)))';
Expand All @@ -17,15 +24,32 @@ import {
// case "fan_only":
// overlayColor = 'var(--state-climate-fan-only-color, var(--state-climate-active-color, var(--state-active-color)))';
// break;
// case "heat_cool":
// overlayColor = 'var(--state-climate-heat-cool-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;
Expand All @@ -37,20 +61,38 @@ import {
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;

// Gestion des couleurs en fonction de l'état et des valeurs de température
const isHeating = targetTemp !== undefined ? currentTemp < targetTemp : currentTemp < targetTempLow;
const isCooling = targetTemp !== undefined ? currentTemp > targetTemp : currentTemp > targetTempHigh;

switch (state) {
case "heat":
overlayColor = 'var(--state-climate-heat-color, var(--state-climate-active-color, var(--state-active-color)))';
overlayColor = isHeating
? '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)))';
overlayColor = isCooling
? 'var(--state-climate-cool-color, var(--state-climate-active-color, var(--state-active-color)))'
: '';
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)))';
}
} else {
overlayColor = '';
}
break;
case "fan_only":
overlayColor = 'var(--state-climate-fan-only-color, var(--state-climate-active-color, var(--state-active-color)))';
Expand All @@ -61,33 +103,8 @@ export function getClimateColor(stateObj) {
case "auto":
overlayColor = 'var(--state-climate-auto-color, var(--state-climate-active-color, var(--state-active-color)))';
break;
case "heat_cool":
// Logique dynamique pour le mode heat_cool
if (currentTemp !== undefined) {
// Cas avec l'attribut 'temperature'
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)))';
}
// Cas sans 'temperature' mais avec 'target_temp_low' et 'target_temp_high'
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 {
// Si aucune température cible n'est définie, couleur par défaut pour heat_cool
overlayColor = 'var(--state-climate-heat-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
}
} else {
// Pas de température courante, couleur par défaut pour heat_cool
overlayColor = 'var(--state-climate-heat-cool-color, var(--state-climate-active-color, var(--state-active-color)))';
}
break;
default:
overlayColor = 'rgba(0, 0, 0, 0)';
overlayColor = '';
break;
}

Expand Down
5 changes: 5 additions & 0 deletions src/cards/climate/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export default `
width: 38px;
justify-content: center;
align-items: center;
transition: all 2s;
}
.bubble-entity-picture {
Expand Down Expand Up @@ -210,6 +211,10 @@ export default `
right: 0 !important;
}
.hidden {
display: none !important;
}
@keyframes tap-feedback {
0% {transform: translateX(-100%); opacity: 0;}
64% {transform: translateX(0); opacity: 0.1;}
Expand Down
61 changes: 27 additions & 34 deletions src/cards/pop-up/changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,62 +7,55 @@ import { initializesubButtonIcon } from '../../tools/global-changes.ts';
export function changeEditor(context) {
if (!context.verticalStack) return;

const detectedEditor = context.verticalStack.host?.closest('hui-card-preview') ||
context.verticalStack.host?.closest('hui-card[preview][class]') ||
context.verticalStack.host?.getRootNode().host?.closest('hui-section[preview][class]');
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 isPopUpOpened = context.popUp?.classList.contains('is-popup-opened');
const isCard = context.sectionRow.tagName.toLowerCase() === 'hui-card';
const popUp = context.popUp;
const sectionRow = context.sectionRow;
const sectionRowContainer = context.sectionRowContainer;
const elements = context.elements;

if (context.previousEditorState === undefined) {
context.previousEditorState = null;
}
if (context.previousDetectedEditor === undefined) {
context.previousDetectedEditor = null;
}
const isPopUpOpened = popUp?.classList.contains('is-popup-opened');
const isCard = sectionRow.tagName.toLowerCase() === 'hui-card';

context.previousEditorState = context.previousEditorState ?? null;
context.previousDetectedEditor = context.previousDetectedEditor ?? null;

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

// Change the pop-up style for the editor
if (context.editor || detectedEditor !== null) {
if (!context.popUp.classList.contains('editor')) {
if (!popUp.classList.contains('editor')) {
document.body.style.overflow = '';
context.popUp?.classList.remove('is-popup-opened');
context.popUp?.classList.add('is-popup-closed');
context.popUp?.classList.add('editor');
popUp?.classList.remove('is-popup-opened');
popUp?.classList.add('is-popup-closed');
popUp?.classList.add('editor');
}

context.editorAccess = true;

if (detectedEditor !== null) {
if (context.elements?.popUpContainer?.classList.contains('editor-cropped')) {
context.elements?.popUpContainer?.classList.remove('editor-cropped');
}
elements?.popUpContainer?.classList.remove('editor-cropped');
} else {
if (!context.elements?.popUpContainer?.classList.contains('editor-cropped')) {
context.elements?.popUpContainer?.classList.add('editor-cropped');
}
elements?.popUpContainer?.classList.add('editor-cropped');
}
} else {
if (context.popUp?.classList.contains('editor')) {
context.popUp?.classList.remove('editor');
}

if (context.elements?.popUpContainer?.classList.contains('editor-cropped')) {
context.elements?.popUpContainer?.classList.remove('editor-cropped');
}
popUp?.classList.remove('editor');
elements?.popUpContainer?.classList.remove('editor-cropped');
}

if (context.editor !== context.previousEditorState || detectedEditor !== context.previousDetectedEditor) {
Expand Down
10 changes: 7 additions & 3 deletions src/cards/pop-up/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,15 @@ export function onUrlChange(context) {

export function onEditorChange(context) {
const { hideBackdrop } = getBackdrop(context);
if (context.editor || context.verticalStack.host?.closest('hui-card-preview')) {
const host = context.verticalStack.host;
const detectedEditor = host?.closest('hui-card-preview');

if (context.editor || detectedEditor) {
hideBackdrop();
clearTimeout(context.removeDomTimeout);
if (!context.verticalStack.contains(context.popUp)) {

if (!detectedEditor && !context.verticalStack.contains(context.popUp)) {
context.verticalStack.appendChild(context.popUp);
}
}
}
}
11 changes: 11 additions & 0 deletions src/cards/select/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ export function callSelectService(context, entity, selectedOption, config) {
}
break;

case 'fan':
switch (config.select_attribute) {
case 'preset_modes':
context._hass.callService('fan', 'set_preset_mode', {
entity_id: entity,
preset_mode: selectedOption
});
break;
}
break;

case 'light':
switch (config.select_attribute) {
case 'effect_list':
Expand Down
12 changes: 12 additions & 0 deletions src/editor/bubble-card-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,18 @@ export function createBubbleCardEditor() {
</div>
</ha-formfield>
` : ''}
${array === 'sub_button' && (context?.show_background ?? true) && (context?.entity ? context?.entity?.startsWith("light") : this._config?.entity?.startsWith("light")) ? html`
<ha-formfield .label="Optional - Background color based on light color">
<ha-switch
aria-label="Optional - Background color based light color"
.checked=${context?.light_background ?? true}
@change="${(ev) => this._arrayValueChange(index, { light_background: ev.target.checked }, array)}"
></ha-switch>
<div class="mdc-form-field">
<label class="mdc-label">Optional - Background color based light color</label>
</div>
</ha-formfield>
` : ''}
<ha-formfield .label="Optional - Show icon">
<ha-switch
aria-label="Optional - Show icon"
Expand Down
5 changes: 4 additions & 1 deletion src/tools/global-changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export function changeSubButtonState(context, container = context.content, appen
const showIcon = subButton.show_icon ?? true;
const showBackground = subButton.show_background ?? true;
const stateBackground = subButton.state_background ?? true;
const lightBackground = subButton.light_background ?? true;
const showArrow = subButton.show_arrow ?? true;

const isSelect = entity?.startsWith("input_select") || entity?.startsWith("select") || subButton.select_attribute;
Expand Down Expand Up @@ -292,7 +293,9 @@ export function changeSubButtonState(context, container = context.content, appen
// Handle background display
if (showBackground) {
if (isOn && stateBackground) {
subButtonElement.style.setProperty('--bubble-sub-button-light-background-color', getIconColor(context, entity, 0.8));
if (lightBackground) {
subButtonElement.style.setProperty('--bubble-sub-button-light-background-color', getIconColor(context, entity, 0.8));
}
subButtonElement.classList.add('background-on');
subButtonElement.classList.remove('background-off');
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/var/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export let version = 'v2.3.0-beta.5';
export let version = 'v2.3.0-beta.6';

0 comments on commit 736f48e

Please sign in to comment.