Skip to content

Commit

Permalink
Merge pull request #108 from mlamberts78/develop
Browse files Browse the repository at this point in the history
Multiple bug fixes
  • Loading branch information
mlamberts78 committed Feb 22, 2024
2 parents a18165c + 6803f95 commit 5ce7dbd
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 50 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ HACS is a third party community store and is not included in Home Assistant out
| precipitation_color | string | rgba(132, 209, 253, 1.0) | Precipitation bar chart color. |
| chart_datetime_color | string | primary-text-color | Chart day or hour color |
| chart_text_color | string | none | Chart text color |
| chart_height | string | 180 | Adjust the forecast chart height |
| condition_icons | boolean | true | Show or hide forecast condition icons. |
| show_wind_forecast | boolean | true | Show or hide wind forecast on the card. |
| round_temp | boolean | false | Option for rounding the forecast temperatures |
Expand Down
124 changes: 99 additions & 25 deletions dist/weather-chart-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,12 @@ class WeatherCardEditor extends s {
.value="${forecastConfig.labels_font_size || '11'}"
@change="${(e) => this._valueChanged(e, 'forecast.labels_font_size')}"
></ha-textfield>
<ha-textfield
label="Chart height"
type="number"
.value="${forecastConfig.chart_height || '180'}"
@change="${(e) => this._valueChanged(e, 'forecast.chart_height')}"
></ha-textfield>
</div>
</div>
</div>
Expand Down Expand Up @@ -17672,6 +17678,7 @@ setConfig(config) {
forecast: {
precipitation_type: 'rainfall',
labels_font_size: 11,
chart_height: 180,
precip_bar_size: 100,
style: 'style1',
temperature1_color: 'rgba(255, 152, 0, 1.0)',
Expand Down Expand Up @@ -17761,18 +17768,59 @@ subscribeForecastEvents() {
return (this.weather.attributes.supported_features & feature) !== 0;
}

constructor() {
super();
this.resizeObserver = null;
this.resizeInitialized = false;
}

connectedCallback() {
super.connectedCallback();
if (!this.resizeInitialized) {
this.delayedAttachResizeObserver();
}
}

delayedAttachResizeObserver() {
setTimeout(() => {
this.attachResizeObserver();
this.resizeInitialized = true;
}, 0);
}

disconnectedCallback() {
super.disconnectedCallback();
this.detachResizeObserver();
if (this.forecastSubscriber) {
this.forecastSubscriber.then((unsub) => unsub());
}
super.disconnectedCallback();
}

constructor() {
super();
window.addEventListener('orientationchange', () => {
attachResizeObserver() {
this.resizeObserver = new ResizeObserver(() => {
this.measureCard();
});
const card = this.shadowRoot.querySelector('ha-card');
if (card) {
this.resizeObserver.observe(card);
}
}

detachResizeObserver() {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
}

measureCard() {
const card = this.shadowRoot.querySelector('ha-card');
let fontSize = this.config.forecast.labels_font_size;
if (!card) {
return;
}
this.forecastItems = Math.round(card.offsetWidth / (fontSize * 6));
this.drawChart();
}

ll(str) {
Expand Down Expand Up @@ -17930,15 +17978,6 @@ async updated(changedProperties) {
}
}

measureCard() {
const card = this.shadowRoot.querySelector('ha-card');
let fontSize = this.config.forecast.labels_font_size;
if (!card) {
return;
}
this.forecastItems = Math.round(card.offsetWidth / (fontSize * 6));
}

drawChart({ config, language, weather, forecastItems } = this) {
if (!this.forecasts || !this.forecasts.length) {
return [];
Expand All @@ -17961,7 +18000,7 @@ drawChart({ config, language, weather, forecastItems } = this) {
var precipUnit = lengthUnit === 'km' ? this.ll('units')['mm'] : this.ll('units')['in'];
}
var forecast = this.forecasts ? this.forecasts.slice(0, forecastItems) : [];
if (new Date(forecast[3].datetime) - new Date(forecast[2].datetime) < 864e5) {
if (new Date(forecast[2].datetime) - new Date(forecast[1].datetime) < 864e5) {
var mode = 'hourly';
} else {
var mode = 'daily';
Expand Down Expand Up @@ -18331,7 +18370,7 @@ updateChart({ config, language, weather, forecastItems } = this) {
}
.chart-container {
position: relative;
height: 180px;
height: ${config.forecast.chart_height}px;
width: 100%;
}
.conditions {
Expand Down Expand Up @@ -18432,14 +18471,14 @@ renderMain({ config, sun, weather, temperature, feels_like, description } = this
const showCurrentCondition = config.show_current_condition !== false;
const showTemperature = config.show_temperature !== false;

let roundedTemperature = temperature;
if (Number.isFinite(temperature) && temperature % 1 !== 0) {
roundedTemperature = Math.round(temperature * 10) / 10;
let roundedTemperature = parseFloat(temperature);
if (!isNaN(roundedTemperature) && roundedTemperature % 1 !== 0) {
roundedTemperature = Math.round(roundedTemperature * 10) / 10;
}

let roundedFeelsLike = feels_like;
if (Number.isFinite(feels_like) && feels_like % 1 !== 0) {
roundedFeelsLike = Math.round(feels_like * 10) / 10;
let roundedFeelsLike = parseFloat(feels_like);
if (!isNaN(roundedFeelsLike) && roundedFeelsLike % 1 !== 0) {
roundedFeelsLike = Math.round(roundedFeelsLike * 10) / 10;
}

const iconHtml = config.animated_icons || config.icons
Expand Down Expand Up @@ -18609,7 +18648,7 @@ const timeOptions = {
`;
}

renderForecastConditionIcons({ config, forecastItems } = this) {
renderForecastConditionIcons({ config, forecastItems, sun } = this) {
const forecast = this.forecasts ? this.forecasts.slice(0, forecastItems) : [];

if (config.forecast.condition_icons === false) {
Expand All @@ -18619,9 +18658,44 @@ renderForecastConditionIcons({ config, forecastItems } = this) {
return x`
<div class="conditions" @click="${(e) => this.showMoreInfo(config.entity)}">
${forecast.map((item) => {
const iconHtml = config.animated_icons || config.icons
? x`<img class="icon" src="${this.getWeatherIcon(item.condition, item.sun)}" alt="">`
: x`<ha-icon icon="${this.getWeatherIcon(item.condition, item.sun)}"></ha-icon>`;
const forecastTime = new Date(item.datetime);
const sunriseTime = new Date(sun.attributes.next_rising);
const sunsetTime = new Date(sun.attributes.next_setting);

// Adjust sunrise and sunset times to match the date of forecastTime
const adjustedSunriseTime = new Date(forecastTime);
adjustedSunriseTime.setHours(sunriseTime.getHours());
adjustedSunriseTime.setMinutes(sunriseTime.getMinutes());
adjustedSunriseTime.setSeconds(sunriseTime.getSeconds());

const adjustedSunsetTime = new Date(forecastTime);
adjustedSunsetTime.setHours(sunsetTime.getHours());
adjustedSunsetTime.setMinutes(sunsetTime.getMinutes());
adjustedSunsetTime.setSeconds(sunsetTime.getSeconds());

let isDayTime;

if (config.forecast.type === 'daily') {
// For daily forecast, assume it's day time
isDayTime = true;
} else {
// For other forecast types, determine based on sunrise and sunset times
isDayTime = forecastTime >= adjustedSunriseTime && forecastTime <= adjustedSunsetTime;
}

const weatherIcons = isDayTime ? weatherIconsDay : weatherIconsNight;
const condition = item.condition;

let iconHtml;

if (config.animated_icons || config.icons) {
const iconSrc = config.animated_icons ?
`${this.baseIconPath}${weatherIcons[condition]}.svg` :
`${this.config.icons}${weatherIcons[condition]}.svg`;
iconHtml = x`<img class="icon" src="${iconSrc}" alt="">`;
} else {
iconHtml = x`<ha-icon icon="${this.getWeatherIcon(condition, sun.state)}"></ha-icon>`;
}

return x`
<div class="forecast-item">
Expand Down
118 changes: 93 additions & 25 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ setConfig(config) {
forecast: {
precipitation_type: 'rainfall',
labels_font_size: 11,
chart_height: 180,
precip_bar_size: 100,
style: 'style1',
temperature1_color: 'rgba(255, 152, 0, 1.0)',
Expand Down Expand Up @@ -175,18 +176,59 @@ subscribeForecastEvents() {
return (this.weather.attributes.supported_features & feature) !== 0;
}

constructor() {
super();
this.resizeObserver = null;
this.resizeInitialized = false;
}

connectedCallback() {
super.connectedCallback();
if (!this.resizeInitialized) {
this.delayedAttachResizeObserver();
}
}

delayedAttachResizeObserver() {
setTimeout(() => {
this.attachResizeObserver();
this.resizeInitialized = true;
}, 0);
}

disconnectedCallback() {
super.disconnectedCallback();
this.detachResizeObserver();
if (this.forecastSubscriber) {
this.forecastSubscriber.then((unsub) => unsub());
}
super.disconnectedCallback();
}

constructor() {
super();
window.addEventListener('orientationchange', () => {
attachResizeObserver() {
this.resizeObserver = new ResizeObserver(() => {
this.measureCard();
});
const card = this.shadowRoot.querySelector('ha-card');
if (card) {
this.resizeObserver.observe(card);
}
}

detachResizeObserver() {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
}

measureCard() {
const card = this.shadowRoot.querySelector('ha-card');
let fontSize = this.config.forecast.labels_font_size;
if (!card) {
return;
}
this.forecastItems = Math.round(card.offsetWidth / (fontSize * 6));
this.drawChart();
}

ll(str) {
Expand Down Expand Up @@ -344,15 +386,6 @@ async updated(changedProperties) {
}
}

measureCard() {
const card = this.shadowRoot.querySelector('ha-card');
let fontSize = this.config.forecast.labels_font_size;
if (!card) {
return;
}
this.forecastItems = Math.round(card.offsetWidth / (fontSize * 6));
}

drawChart({ config, language, weather, forecastItems } = this) {
if (!this.forecasts || !this.forecasts.length) {
return [];
Expand All @@ -375,7 +408,7 @@ drawChart({ config, language, weather, forecastItems } = this) {
var precipUnit = lengthUnit === 'km' ? this.ll('units')['mm'] : this.ll('units')['in'];
}
var forecast = this.forecasts ? this.forecasts.slice(0, forecastItems) : [];
if (new Date(forecast[3].datetime) - new Date(forecast[2].datetime) < 864e5) {
if (new Date(forecast[2].datetime) - new Date(forecast[1].datetime) < 864e5) {
var mode = 'hourly';
} else {
var mode = 'daily';
Expand Down Expand Up @@ -745,7 +778,7 @@ updateChart({ config, language, weather, forecastItems } = this) {
}
.chart-container {
position: relative;
height: 180px;
height: ${config.forecast.chart_height}px;
width: 100%;
}
.conditions {
Expand Down Expand Up @@ -846,14 +879,14 @@ renderMain({ config, sun, weather, temperature, feels_like, description } = this
const showCurrentCondition = config.show_current_condition !== false;
const showTemperature = config.show_temperature !== false;

let roundedTemperature = temperature;
if (Number.isFinite(temperature) && temperature % 1 !== 0) {
roundedTemperature = Math.round(temperature * 10) / 10;
let roundedTemperature = parseFloat(temperature);
if (!isNaN(roundedTemperature) && roundedTemperature % 1 !== 0) {
roundedTemperature = Math.round(roundedTemperature * 10) / 10;
}

let roundedFeelsLike = feels_like;
if (Number.isFinite(feels_like) && feels_like % 1 !== 0) {
roundedFeelsLike = Math.round(feels_like * 10) / 10;
let roundedFeelsLike = parseFloat(feels_like);
if (!isNaN(roundedFeelsLike) && roundedFeelsLike % 1 !== 0) {
roundedFeelsLike = Math.round(roundedFeelsLike * 10) / 10;
}

const iconHtml = config.animated_icons || config.icons
Expand Down Expand Up @@ -1023,7 +1056,7 @@ const timeOptions = {
`;
}

renderForecastConditionIcons({ config, forecastItems } = this) {
renderForecastConditionIcons({ config, forecastItems, sun } = this) {
const forecast = this.forecasts ? this.forecasts.slice(0, forecastItems) : [];

if (config.forecast.condition_icons === false) {
Expand All @@ -1033,9 +1066,44 @@ renderForecastConditionIcons({ config, forecastItems } = this) {
return html`
<div class="conditions" @click="${(e) => this.showMoreInfo(config.entity)}">
${forecast.map((item) => {
const iconHtml = config.animated_icons || config.icons
? html`<img class="icon" src="${this.getWeatherIcon(item.condition, item.sun)}" alt="">`
: html`<ha-icon icon="${this.getWeatherIcon(item.condition, item.sun)}"></ha-icon>`;
const forecastTime = new Date(item.datetime);
const sunriseTime = new Date(sun.attributes.next_rising);
const sunsetTime = new Date(sun.attributes.next_setting);
// Adjust sunrise and sunset times to match the date of forecastTime
const adjustedSunriseTime = new Date(forecastTime);
adjustedSunriseTime.setHours(sunriseTime.getHours());
adjustedSunriseTime.setMinutes(sunriseTime.getMinutes());
adjustedSunriseTime.setSeconds(sunriseTime.getSeconds());
const adjustedSunsetTime = new Date(forecastTime);
adjustedSunsetTime.setHours(sunsetTime.getHours());
adjustedSunsetTime.setMinutes(sunsetTime.getMinutes());
adjustedSunsetTime.setSeconds(sunsetTime.getSeconds());
let isDayTime;
if (config.forecast.type === 'daily') {
// For daily forecast, assume it's day time
isDayTime = true;
} else {
// For other forecast types, determine based on sunrise and sunset times
isDayTime = forecastTime >= adjustedSunriseTime && forecastTime <= adjustedSunsetTime;
}
const weatherIcons = isDayTime ? weatherIconsDay : weatherIconsNight;
const condition = item.condition;
let iconHtml;
if (config.animated_icons || config.icons) {
const iconSrc = config.animated_icons ?
`${this.baseIconPath}${weatherIcons[condition]}.svg` :
`${this.config.icons}${weatherIcons[condition]}.svg`;
iconHtml = html`<img class="icon" src="${iconSrc}" alt="">`;
} else {
iconHtml = html`<ha-icon icon="${this.getWeatherIcon(condition, sun.state)}"></ha-icon>`;
}
return html`
<div class="forecast-item">
Expand Down

0 comments on commit 5ce7dbd

Please sign in to comment.