From 65ad109a6db366546eb4bd77736d7a040e0ef7be Mon Sep 17 00:00:00 2001 From: Amit <91756648+pathofleastresistor@users.noreply.github.com> Date: Sat, 13 Jan 2024 11:57:35 -0800 Subject: [PATCH] Redesign the list layout (#12) * first commit * smaller list icon size * Adjust browser nav button size * first commit * smaller list icon size * Adjust browser nav button size --- polr-ytube-media-card.js | 220 +++++++++++++++++-------- src/elements/polr-ytube-browser.ts | 4 +- src/elements/polr-ytube-list-item.ts | 229 +++++++++++++++++++++++++++ src/elements/polr-ytube-list.ts | 198 +++-------------------- 4 files changed, 410 insertions(+), 241 deletions(-) create mode 100644 src/elements/polr-ytube-list-item.ts diff --git a/polr-ytube-media-card.js b/polr-ytube-media-card.js index 35c1c6b..faee57d 100644 --- a/polr-ytube-media-card.js +++ b/polr-ytube-media-card.js @@ -305,60 +305,64 @@ const VolumeOffIcon = x ` `; -let PoLRYTubeList = class PoLRYTubeList extends s$1 { - updated(_changedProperties) { - // this.renderRoot.querySelector(".current")?.scrollIntoView({ - // behavior: "smooth", - // block: "start", - // inline: "center", - // }); +let PoLRYTubeListItem = class PoLRYTubeListItem extends s$1 { + constructor() { + super(...arguments); + this._actions = []; + this._hasAdditionalActions = false; } - _is_current(element) { - if (this.entity == null) - return false; - if (!isNumeric(element.media_content_id)) - return false; - if ("current_track" in this.entity["attributes"]) { - return (parseInt(element.media_content_id) - 1 == - this.entity["attributes"]["current_track"]); - } - return false; + firstUpdated(_changedProperties) { + if (this.element.can_expand) + this._primaryAction = "more"; + else + this._primaryAction = "play"; + this._hasAdditionalActions = + this.element.can_expand == this.element.can_play + ? this.element.can_expand + : this.element.media_content_type == "track"; + this.requestUpdate(); } render() { - if (this.state == 4 /* PoLRYTubeListState.LOADING */) { - return x `
Loading...
`; - } - if (this.state == 8 /* PoLRYTubeListState.NO_RESULTS */) { - return x `
No results
`; - } - if (this.state == 16 /* PoLRYTubeListState.ERROR */) { - return x `
Unknown Error
`; + return x ` + + ${this._renderThumbnail(this.element)} ${this.element.title} + ${this._renderAction()} + + ${this._hasAdditionalActions + ? x ` +
+
+ ${this._primaryAction != "more" + ? this._renderMoreButton(this.element) + : x ``} + ${this._primaryAction != "play" + ? this._renderPlayButton(this.element) + : x ``} + ${this._renderRadioButton(this.element)} +
+ ` + : ``} + `; + } + _performPrimaryAction() { + if (this._primaryAction == "more") + this._fireNavigateEvent(this.element); + if (this._primaryAction == "play") + this._play(this.element); + } + _renderAction() { + if (this._primaryAction == "more") { + return x `${ForwardBurgerIcon}`; } - if (this.state == 2 /* PoLRYTubeListState.HAS_RESULTS */) { - if (this.elements.length == 0) - return x ``; - const renderedElements = this.elements.map((element) => { - return x ` -
- ${this._renderThumbnail(element)} -
${element.title}
-
- ${this._renderMoreButton(element)} - ${this._renderRadioButton(element)} - ${this._renderPlayButton(element)} -
-
- `; - }); - return x ` -
-
${renderedElements}
-
- `; + if (this._primaryAction == "play") { + return x ``; } + return x ``; } _renderMoreButton(element) { if (!element["can_expand"]) @@ -379,8 +383,7 @@ let PoLRYTubeList = class PoLRYTubeList extends s$1 { `; } _renderRadioButton(element) { - if (this._is_current(element) || - element.media_content_type == "track") { + if (element.media_content_type == "track") { const id = element.media_content_type == "track" ? element.media_content_id : this.entity["attributes"]["videoId"]; @@ -394,11 +397,13 @@ let PoLRYTubeList = class PoLRYTubeList extends s$1 { } _renderThumbnail(element) { if (element.thumbnail == "") { - return x `
+ return x `
`; } - return x ` `; + return x ` + + `; } async _fireNavigateEvent(element) { this.dispatchEvent(new CustomEvent("navigate", { @@ -441,25 +446,37 @@ let PoLRYTubeList = class PoLRYTubeList extends s$1 { static get styles() { return [ i$5 ` - .elements { - } - - .element { + :host { display: grid; - grid-template-columns: 40px 1fr min-content; + grid-template-columns: 1fr min-content min-content; align-items: center; - gap: 12px; - padding: 12px; + } + + mwc-list-item { border-radius: 12px; } + svg { + width: 18px; + height: 18px; + fill: var(--primary-text-color); + } + + .divider { + width: 2px; + background: rgba(var(--rgb-primary-text-color), 0.2); + height: 50%; + margin: 0 4px; + } + .actions { display: grid; - grid-template-columns: auto auto auto; + grid-template-columns: auto; + align-items: center; } .actions > mwc-button { - margin-right: 8px; + margin: 0 8px; } .element img { @@ -476,9 +493,80 @@ let PoLRYTubeList = class PoLRYTubeList extends s$1 { align-items: center; justify-content: center; } + `, + ]; + } +}; +__decorate([ + t$1() +], PoLRYTubeListItem.prototype, "entity", void 0); +__decorate([ + t$1() +], PoLRYTubeListItem.prototype, "hass", void 0); +__decorate([ + t$1() +], PoLRYTubeListItem.prototype, "element", void 0); +__decorate([ + t$1() +], PoLRYTubeListItem.prototype, "current", void 0); +PoLRYTubeListItem = __decorate([ + e$5("polr-ytube-list-item") +], PoLRYTubeListItem); - .current { - background-color: var(--primary-background-color); +let PoLRYTubeList = class PoLRYTubeList extends s$1 { + render() { + if (this.state == 4 /* PoLRYTubeListState.LOADING */) { + return x `
Loading...
`; + } + if (this.state == 8 /* PoLRYTubeListState.NO_RESULTS */) { + return x `
No results
`; + } + if (this.state == 16 /* PoLRYTubeListState.ERROR */) { + return x `
Unknown Error
`; + } + if (this.state == 2 /* PoLRYTubeListState.HAS_RESULTS */) { + if (this.elements.length == 0) + return x ``; + const renderedElements = this.elements.map((element) => { + return x ` + this._fireNavigateEvent(ev.detail.action)} + > + `; + }); + return x `${renderedElements}`; + } + } + _is_current(element) { + if (this.entity == null) + return false; + if (!isNumeric(element.media_content_id)) + return false; + if ("current_track" in this.entity["attributes"]) { + return (parseInt(element.media_content_id) - 1 == + this.entity["attributes"]["current_track"]); + } + return false; + } + async _fireNavigateEvent(element) { + this.dispatchEvent(new CustomEvent("navigate", { + detail: { + action: element, + }, + })); + return; + } + static get styles() { + return [ + i$5 ` + :host { + display: grid; + gap: 4px; + --mdc-list-item-graphic-size: 40px; } .empty, @@ -4552,8 +4640,8 @@ let PoLRYTubeBrowser = class PoLRYTubeBrowser extends s$1 { align-items: center; gap: 4px; justify-content: flex-start; - padding: 4px 0; - --mdc-icon-button-size: 32px; + padding: 8px 0; + --mdc-icon-button-size: 30px; --mdc-icon-size: 20px; } diff --git a/src/elements/polr-ytube-browser.ts b/src/elements/polr-ytube-browser.ts index a88a5e8..4cfddcd 100644 --- a/src/elements/polr-ytube-browser.ts +++ b/src/elements/polr-ytube-browser.ts @@ -266,8 +266,8 @@ export class PoLRYTubeBrowser extends LitElement { align-items: center; gap: 4px; justify-content: flex-start; - padding: 4px 0; - --mdc-icon-button-size: 32px; + padding: 8px 0; + --mdc-icon-button-size: 30px; --mdc-icon-size: 20px; } diff --git a/src/elements/polr-ytube-list-item.ts b/src/elements/polr-ytube-list-item.ts new file mode 100644 index 0000000..e7ba6d9 --- /dev/null +++ b/src/elements/polr-ytube-list-item.ts @@ -0,0 +1,229 @@ +import { + LitElement, + html, + css, + CSSResultGroup, + nothing, + PropertyValueMap, +} from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { PlayableMediaList, PoLRYTubeItem } from "../utils/utils"; +import { ForwardBurgerIcon, PlayIcon, RadioTowerIcon } from "../utils/icons"; + +@customElement("polr-ytube-list-item") +export class PoLRYTubeListItem extends LitElement { + @state() public entity: any; + @state() public hass: any; + @state() public element: PoLRYTubeItem; + @state() public current: boolean; + private _primaryAction: any; + private _actions: any[] = []; + private _hasAdditionalActions: boolean = false; + + protected firstUpdated( + _changedProperties: PropertyValueMap | Map + ): void { + if (this.element.can_expand) this._primaryAction = "more"; + else this._primaryAction = "play"; + + this._hasAdditionalActions = + this.element.can_expand == this.element.can_play + ? this.element.can_expand + : this.element.media_content_type == "track"; + this.requestUpdate(); + } + + render() { + return html` + + ${this._renderThumbnail(this.element)} ${this.element.title} + ${this._renderAction()} + + ${this._hasAdditionalActions + ? html` +
+
+ ${this._primaryAction != "more" + ? this._renderMoreButton(this.element) + : html``} + ${this._primaryAction != "play" + ? this._renderPlayButton(this.element) + : html``} + ${this._renderRadioButton(this.element)} +
+ ` + : ``} + `; + } + + private _performPrimaryAction() { + if (this._primaryAction == "more") + this._fireNavigateEvent(this.element); + + if (this._primaryAction == "play") this._play(this.element); + } + + private _renderAction() { + if (this._primaryAction == "more") { + return html`${ForwardBurgerIcon}`; + } + + if (this._primaryAction == "play") { + return html``; + } + + return html``; + } + + private _renderMoreButton(element: PoLRYTubeItem) { + if (!element["can_expand"]) return html``; + + return html` + this._fireNavigateEvent(element)}> + ${ForwardBurgerIcon} + + `; + } + + private _renderPlayButton(element: PoLRYTubeItem) { + if (!element.can_play) return html``; + return html` + this._play(element)}> + ${PlayIcon} + + `; + } + + private _renderRadioButton(element: PoLRYTubeItem) { + if (element.media_content_type == "track") { + const id = + element.media_content_type == "track" + ? element.media_content_id + : this.entity["attributes"]["videoId"]; + + return html` + this._startRadio(id)}> + ${RadioTowerIcon} + + `; + } + return nothing; + } + + private _renderThumbnail(element: PoLRYTubeItem) { + if (element.thumbnail == "") { + return html`
+ +
`; + } + + return html` + + `; + } + + private async _fireNavigateEvent(element: PoLRYTubeItem) { + this.dispatchEvent( + new CustomEvent("navigate", { + detail: { + action: element, + }, + }) + ); + return; + } + + private async _startRadio(media_content_id) { + this.hass.callService("media_player", "shuffle_set", { + entity_id: this.entity["entity_id"], + shuffle: false, + }); + + this.hass.callService("media_player", "play_media", { + entity_id: this.entity["entity_id"], + media_content_id: media_content_id, + media_content_type: "vid_channel", + }); + return; + } + + private async _play(element: PoLRYTubeItem) { + if (element.media_content_type == "PLAYLIST_GOTO_TRACK") { + this.hass.callService("ytube_music_player", "call_method", { + entity_id: this.entity["entity_id"], + command: "goto_track", + parameters: element.media_content_id, + }); + + return; + } + if (PlayableMediaList.includes(element.media_class)) { + this.hass.callService("media_player", "play_media", { + entity_id: this.entity["entity_id"], + media_content_id: element.media_content_id, + media_content_type: element.media_content_type, + }); + + return; + } + } + + static get styles(): CSSResultGroup { + return [ + css` + :host { + display: grid; + grid-template-columns: 1fr min-content min-content; + align-items: center; + } + + mwc-list-item { + border-radius: 12px; + } + + svg { + width: 18px; + height: 18px; + fill: var(--primary-text-color); + } + + .divider { + width: 2px; + background: rgba(var(--rgb-primary-text-color), 0.2); + height: 50%; + margin: 0 4px; + } + + .actions { + display: grid; + grid-template-columns: auto; + align-items: center; + } + + .actions > mwc-button { + margin: 0 8px; + } + + .element img { + width: 40px; + height: 40px; + border-radius: 5%; + } + + .empty-thumbnail { + display: flex; + background-color: rgba(111, 111, 111, 0.2); + border-radius: 5%; + height: 40px; + align-items: center; + justify-content: center; + } + `, + ]; + } +} diff --git a/src/elements/polr-ytube-list.ts b/src/elements/polr-ytube-list.ts index 5f8e452..da72d14 100644 --- a/src/elements/polr-ytube-list.ts +++ b/src/elements/polr-ytube-list.ts @@ -1,20 +1,7 @@ -import { - LitElement, - html, - css, - CSSResultGroup, - nothing, - PropertyValueMap, -} from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { - isNumeric, - PlayableMediaList, - PoLRYTubeItem, - PoLRYTubeListState, - areDeeplyEqual, -} from "../utils/utils"; -import { ForwardBurgerIcon, PlayIcon, RadioTowerIcon } from "../utils/icons"; +import { LitElement, html, css, CSSResultGroup } from "lit"; +import { customElement, state } from "lit/decorators.js"; +import { isNumeric, PoLRYTubeItem, PoLRYTubeListState } from "../utils/utils"; +import "./polr-ytube-list-item"; @customElement("polr-ytube-list") export class PoLRYTubeList extends LitElement { @@ -23,29 +10,6 @@ export class PoLRYTubeList extends LitElement { @state() public elements: PoLRYTubeItem[]; @state() public state: PoLRYTubeListState; - protected updated( - _changedProperties: PropertyValueMap | Map - ): void { - // this.renderRoot.querySelector(".current")?.scrollIntoView({ - // behavior: "smooth", - // block: "start", - // inline: "center", - // }); - } - - private _is_current(element: PoLRYTubeItem): boolean { - if (this.entity == null) return false; - if (!isNumeric(element.media_content_id)) return false; - - if ("current_track" in this.entity["attributes"]) { - return ( - parseInt(element.media_content_id) - 1 == - this.entity["attributes"]["current_track"] - ); - } - return false; - } - render() { if (this.state == PoLRYTubeListState.LOADING) { return html`
Loading...
`; @@ -64,75 +28,32 @@ export class PoLRYTubeList extends LitElement { const renderedElements = this.elements.map((element) => { return html` -
- ${this._renderThumbnail(element)} -
${element.title}
-
- ${this._renderMoreButton(element)} - ${this._renderRadioButton(element)} - ${this._renderPlayButton(element)} -
-
+ + this._fireNavigateEvent(ev.detail.action)} + > `; }); - return html` -
-
${renderedElements}
-
- `; + return html`${renderedElements}`; } } - private _renderMoreButton(element: PoLRYTubeItem) { - if (!element["can_expand"]) return html``; - - return html` - this._fireNavigateEvent(element)}> - ${ForwardBurgerIcon} - - `; - } - - private _renderPlayButton(element: PoLRYTubeItem) { - if (!element.can_play) return html``; - return html` - this._play(element)}> - ${PlayIcon} - - `; - } - - private _renderRadioButton(element: PoLRYTubeItem) { - if ( - this._is_current(element) || - element.media_content_type == "track" - ) { - const id = - element.media_content_type == "track" - ? element.media_content_id - : this.entity["attributes"]["videoId"]; - - return html` - this._startRadio(id)}> - ${RadioTowerIcon} - - `; - } - return nothing; - } + private _is_current(element: PoLRYTubeItem): boolean { + if (this.entity == null) return false; + if (!isNumeric(element.media_content_id)) return false; - private _renderThumbnail(element: PoLRYTubeItem) { - if (element.thumbnail == "") { - return html`
- -
`; + if ("current_track" in this.entity["attributes"]) { + return ( + parseInt(element.media_content_id) - 1 == + this.entity["attributes"]["current_track"] + ); } - - return html` `; + return false; } private async _fireNavigateEvent(element: PoLRYTubeItem) { @@ -146,82 +67,13 @@ export class PoLRYTubeList extends LitElement { return; } - private async _startRadio(media_content_id) { - this.hass.callService("media_player", "shuffle_set", { - entity_id: this.entity["entity_id"], - shuffle: false, - }); - - this.hass.callService("media_player", "play_media", { - entity_id: this.entity["entity_id"], - media_content_id: media_content_id, - media_content_type: "vid_channel", - }); - return; - } - - private async _play(element: PoLRYTubeItem) { - if (element.media_content_type == "PLAYLIST_GOTO_TRACK") { - this.hass.callService("ytube_music_player", "call_method", { - entity_id: this.entity["entity_id"], - command: "goto_track", - parameters: element.media_content_id, - }); - - return; - } - if (PlayableMediaList.includes(element.media_class)) { - this.hass.callService("media_player", "play_media", { - entity_id: this.entity["entity_id"], - media_content_id: element.media_content_id, - media_content_type: element.media_content_type, - }); - - return; - } - } - static get styles(): CSSResultGroup { return [ css` - .elements { - } - - .element { - display: grid; - grid-template-columns: 40px 1fr min-content; - align-items: center; - gap: 12px; - padding: 12px; - border-radius: 12px; - } - - .actions { + :host { display: grid; - grid-template-columns: auto auto auto; - } - - .actions > mwc-button { - margin-right: 8px; - } - - .element img { - width: 40px; - height: 40px; - border-radius: 5%; - } - - .empty-thumbnail { - display: flex; - background-color: rgba(111, 111, 111, 0.2); - border-radius: 5%; - height: 40px; - align-items: center; - justify-content: center; - } - - .current { - background-color: var(--primary-background-color); + gap: 4px; + --mdc-list-item-graphic-size: 40px; } .empty,