Improve rendering person card (#10419)

This commit is contained in:
Paulus Schoutsen 2021-10-27 06:38:57 -07:00 committed by GitHub
parent 09ef72647e
commit 4a7a81ffdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 32 deletions

View File

@ -1,2 +1,3 @@
/** An empty image which can be set as src of an img element. */
export default "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
export const emptyImageBase64 =
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";

View File

@ -3,7 +3,7 @@ import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { Person } from "../../data/person";
import { computeInitials } from "./ha-user-badge";
import { computeUserInitials } from "../../data/user";
@customElement("ha-person-badge")
class PersonBadge extends LitElement {
@ -22,7 +22,7 @@ class PersonBadge extends LitElement {
class="picture"
></div>`;
}
const initials = computeInitials(this.person.name);
const initials = computeUserInitials(this.person.name);
return html`<div
class="initials ${classMap({ long: initials!.length > 2 })}"
>

View File

@ -10,25 +10,9 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { User } from "../../data/user";
import { computeUserInitials, User } from "../../data/user";
import { CurrentUser, HomeAssistant } from "../../types";
export const computeInitials = (name: string) => {
if (!name) {
return "?";
}
return (
name
.trim()
// Split by space and take first 3 words
.split(" ")
.slice(0, 3)
// Of each word, take first letter
.map((s) => s.substr(0, 1))
.join("")
);
};
@customElement("ha-user-badge")
class UserBadge extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@ -75,7 +59,7 @@ class UserBadge extends LitElement {
class="picture"
></div>`;
}
const initials = computeInitials(this.user.name);
const initials = computeUserInitials(this.user.name);
return html`<div
class="initials ${classMap({ long: initials!.length > 2 })}"
>

View File

@ -57,3 +57,19 @@ export const deleteUser = async (hass: HomeAssistant, userId: string) =>
type: "config/auth/delete",
user_id: userId,
});
export const computeUserInitials = (name: string) => {
if (!name) {
return "?";
}
return (
name
.trim()
// Split by space and take first 3 words
.split(" ")
.slice(0, 3)
// Of each word, take first letter
.map((s) => s.substr(0, 1))
.join("")
);
};

View File

@ -7,14 +7,12 @@ import {
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/ha-card";
import { UNAVAILABLE_STATES } from "../../../data/entity";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive";
@ -135,9 +133,9 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
</div>
`;
} else if (this._config.show_name) {
footer = html`<div class="footer">${name}</div>`;
footer = html`<div class="footer single">${name}</div>`;
} else if (this._config.show_state) {
footer = html`<div class="footer state">${entityState}</div>`;
footer = html`<div class="footer single">${entityState}</div>`;
}
return html`
@ -163,9 +161,6 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
? "0"
: undefined
)}
class=${classMap({
clickable: !UNAVAILABLE_STATES.includes(stateObj.state),
})}
></hui-image>
${footer}
</ha-card>
@ -182,7 +177,7 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
box-sizing: border-box;
}
hui-image.clickable {
hui-image {
cursor: pointer;
}
@ -212,8 +207,8 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
justify-content: space-between;
}
.state {
text-align: right;
.single {
text-align: center;
}
`;
}

View File

@ -16,6 +16,7 @@ import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { domainToName } from "../../../data/integration";
import { LovelaceCardConfig, LovelaceViewConfig } from "../../../data/lovelace";
import { SENSOR_DEVICE_CLASS_BATTERY } from "../../../data/sensor";
import { computeUserInitials } from "../../../data/user";
import {
AlarmPanelCardConfig,
EntitiesCardConfig,
@ -232,6 +233,62 @@ export const generateViewConfig = (
let cards: LovelaceCardConfig[] = [];
if ("person" in ungroupedEntitites) {
const personCards: LovelaceCardConfig[] = [];
if (ungroupedEntitites.person.length === 1) {
cards.push({
type: "entities",
entities: ungroupedEntitites.person,
});
} else {
let backgroundColor: string | undefined;
let foregroundColor = "";
for (const personEntityId of ungroupedEntitites.person) {
const stateObj = entities[personEntityId];
let image = stateObj.attributes.entity_picture;
if (!image) {
if (backgroundColor === undefined) {
const computedStyle = getComputedStyle(document.body);
backgroundColor = encodeURIComponent(
computedStyle.getPropertyValue("--light-primary-color").trim()
);
foregroundColor = encodeURIComponent(
(
computedStyle.getPropertyValue("--text-light-primary-color") ||
computedStyle.getPropertyValue("--primary-text-color")
).trim()
);
}
const initials = computeUserInitials(
stateObj.attributes.friendly_name || ""
);
image = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50' width='50' height='50' style='background-color:${backgroundColor}'%3E%3Cg%3E%3Ctext font-family='roboto' x='50%25' y='50%25' text-anchor='middle' stroke='${foregroundColor}' font-size='1.3em' dy='.3em'%3E${initials}%3C/text%3E%3C/g%3E%3C/svg%3E`;
}
personCards.push({
type: "picture-entity",
entity: personEntityId,
aspect_ratio: "1",
show_name: false,
image,
});
}
cards.push({
type: "grid",
square: true,
columns: 3,
cards: personCards,
});
}
delete ungroupedEntitites.person;
}
splitted.groups.forEach((groupEntity) => {
cards = cards.concat(
computeCards(

View File

@ -192,7 +192,7 @@ export class HuiImage extends LitElement {
: undefined,
backgroundImage:
useRatio && this._loadedImageSrc
? `url(${this._loadedImageSrc})`
? `url("${this._loadedImageSrc}")`
: undefined,
filter:
this._loadState === LoadState.Loaded || this.cameraView === "live"