use image selector for view background (#20898)

* use image selector for view background

* make config future proof

* improvements
This commit is contained in:
Bram Kragten 2024-05-29 17:29:09 +02:00 committed by GitHub
parent 5cc08cfe0b
commit d31a777135
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 47 additions and 35 deletions

View File

@ -86,10 +86,17 @@ class HcLovelace extends LitElement {
this.lovelaceConfig.views[index].background || this.lovelaceConfig.views[index].background ||
this.lovelaceConfig.background; this.lovelaceConfig.background;
if (configBackground) { const backgroundStyle =
typeof configBackground === "string"
? configBackground
: configBackground?.image
? `center / cover no-repeat url('${configBackground.image}')`
: undefined;
if (backgroundStyle) {
this._huiView!.style.setProperty( this._huiView!.style.setProperty(
"--lovelace-background", "--lovelace-background",
configBackground backgroundStyle
); );
} else { } else {
this._huiView!.style.removeProperty("--lovelace-background"); this._huiView!.style.removeProperty("--lovelace-background");

View File

@ -85,6 +85,8 @@ export class HaImageSelector extends LitElement {
<ha-picture-upload <ha-picture-upload
.hass=${this.hass} .hass=${this.hass}
.value=${this.value?.startsWith(URL_PREFIX) ? this.value : null} .value=${this.value?.startsWith(URL_PREFIX) ? this.value : null}
.original=${this.selector.image?.original}
.cropOptions=${this.selector.image?.crop}
@change=${this._pictureChanged} @change=${this._pictureChanged}
></ha-picture-upload> ></ha-picture-upload>
`} `}

View File

@ -7,6 +7,10 @@ export interface ShowViewConfig {
user?: string; user?: string;
} }
interface LovelaceViewBackgroundConfig {
image?: string;
}
export interface LovelaceBaseViewConfig { export interface LovelaceBaseViewConfig {
index?: number; index?: number;
title?: string; title?: string;
@ -14,7 +18,7 @@ export interface LovelaceBaseViewConfig {
icon?: string; icon?: string;
theme?: string; theme?: string;
panel?: boolean; panel?: boolean;
background?: string; background?: string | LovelaceViewBackgroundConfig;
visible?: boolean | ShowViewConfig[]; visible?: boolean | ShowViewConfig[];
subview?: boolean; subview?: boolean;
back_path?: string; back_path?: string;

View File

@ -14,6 +14,7 @@ import {
} from "./entity_registry"; } from "./entity_registry";
import { EntitySources } from "./entity_sources"; import { EntitySources } from "./entity_sources";
import { isHelperDomain } from "../panels/config/helpers/const"; import { isHelperDomain } from "../panels/config/helpers/const";
import type { CropOptions } from "../dialogs/image-cropper-dialog/show-image-cropper-dialog";
export type Selector = export type Selector =
| ActionSelector | ActionSelector
@ -259,7 +260,7 @@ export interface IconSelector {
export interface ImageSelector { export interface ImageSelector {
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
image: {} | null; image: { original?: boolean; crop?: CropOptions } | null;
} }
export interface LabelSelector { export interface LabelSelector {

View File

@ -2,19 +2,11 @@ import "@material/mwc-list/mwc-list-item";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/user/ha-user-badge"; import "../../../../components/ha-selector/ha-selector-image";
import { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import { HomeAssistant, ValueChangedEvent } from "../../../../types"; import { HomeAssistant, ValueChangedEvent } from "../../../../types";
import "../../../../components/ha-picture-upload";
import type { HaPictureUpload } from "../../../../components/ha-picture-upload";
import { CropOptions } from "../../../../dialogs/image-cropper-dialog/show-image-cropper-dialog";
const cropOptions: CropOptions = { const SELECTOR = { image: { original: true } };
round: false,
type: "image/jpeg",
quality: 0.75,
aspectRatio: 1.78,
};
@customElement("hui-view-background-editor") @customElement("hui-view-background-editor")
export class HuiViewBackgroundEditor extends LitElement { export class HuiViewBackgroundEditor extends LitElement {
@ -31,36 +23,35 @@ export class HuiViewBackgroundEditor extends LitElement {
return nothing; return nothing;
} }
const backgroundUrlRegex = /url\(['"]?([^'"]+)['"]?\)/; const background = this._config?.background;
const backgroundUrlMatch = backgroundUrlRegex.exec( const backgroundUrl =
this._config?.background || "" typeof background === "string"
); ? background.match(/url\(['"]?([^'"]+)['"]?\)/)?.[1]
const backgroundUrl = backgroundUrlMatch ? backgroundUrlMatch[1] : null; : background?.image;
return html` return html`
<p> <ha-selector-image
${this.hass.localize( .hass=${this.hass}
.label=${this.hass.localize(
"ui.panel.lovelace.editor.edit_view.background.title" "ui.panel.lovelace.editor.edit_view.background.title"
)} )}
</p>
<ha-picture-upload
.hass=${this.hass}
.value=${backgroundUrl} .value=${backgroundUrl}
crop .selector=${SELECTOR}
.cropOptions=${cropOptions} @value-changed=${this._backgroundChanged}
original ></ha-selector-image>
@change=${this._backgroundChanged}
></ha-picture-upload>
`; `;
} }
private _backgroundChanged(ev: ValueChangedEvent<string | null>) { private _backgroundChanged(ev: ValueChangedEvent<string | null>) {
const backgroundUrl = (ev.target as HaPictureUpload).value; const backgroundUrl = ev.detail.value;
const config = { const config = {
...this._config, ...this._config,
background: backgroundUrl background: {
? `center / cover no-repeat url('${backgroundUrl}')` ...(typeof this._config.background === "string"
: undefined, ? {}
: this._config.background),
image: backgroundUrl || undefined,
},
}; };
fireEvent(this, "view-config-changed", { config }); fireEvent(this, "view-config-changed", { config });
} }

View File

@ -932,8 +932,15 @@ class HUIRoot extends LitElement {
const configBackground = viewConfig.background || this.config.background; const configBackground = viewConfig.background || this.config.background;
if (configBackground) { const backgroundStyle =
root.style.setProperty("--lovelace-background", configBackground); typeof configBackground === "string"
? configBackground
: configBackground?.image
? `center / cover no-repeat url('${configBackground.image}')`
: undefined;
if (backgroundStyle) {
root.style.setProperty("--lovelace-background", backgroundStyle);
} else { } else {
root.style.removeProperty("--lovelace-background"); root.style.removeProperty("--lovelace-background");
} }