Skip to content

Commit 23c1879

Browse files
authored
Merge pull request #371 from droans/next
Refactor Expressive scheme
2 parents be751c1 + 086b820 commit 23c1879

File tree

6 files changed

+153
-152
lines changed

6 files changed

+153
-152
lines changed

src/components/navigation-bar-expressive.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,9 @@ class MassNavBar extends LitElement {
102102
const bounce_move = to_width * 0.2;
103103

104104
const bounce_left = Math.max(0, to_left - bounce_move);
105-
const bounce_width = bounce_left > 0 ? to_width : to_width - (to_left + bounce_move)
106-
const translate_x = bounce_left - from_left;
105+
const bounce_width = bounce_left > 0 ? to_width : to_width - bounce_move
106+
const extra_left = to_left == 0 ? (bounce_move / 2) : 0;
107+
const translate_x = bounce_left - from_left - extra_left;
107108
const scale_x = bounce_width / from_width;
108109

109110
return {
@@ -118,13 +119,14 @@ class MassNavBar extends LitElement {
118119
const to_left = to_element.offsetLeft;
119120
const to_width = to_element.offsetWidth;
120121

121-
const bounce_move = to_width * 0.1;
122+
const bounce_move = to_width * 0.2;
122123
const navbarWidth = this.navbar.offsetWidth;
123124
const to_elem_x_end = to_left + to_width;
124125

125126
const bounce_left = to_left + bounce_move;
126127
const bounce_width = to_elem_x_end >= navbarWidth ? navbarWidth - bounce_left : to_width;
127-
const translate_x = bounce_left - from_left;
128+
const extra_left = to_elem_x_end >= navbarWidth ? (bounce_move / 2) : 0;
129+
const translate_x = bounce_left - from_left - extra_left;
128130
const scale_x = bounce_width / from_width;
129131
return {
130132
transform: `translateX(${translate_x.toString()}px) scaleX(${scale_x.toString()})`,
@@ -153,6 +155,11 @@ class MassNavBar extends LitElement {
153155
const scale_x = to_width / from_width;
154156

155157
const _keyframes = [
158+
159+
{
160+
transform: `translateX(${translate_x.toString()}px) scaleX(${scale_x.toString()})`,
161+
offset: 0.6,
162+
},
156163
bounce,
157164
{
158165
transform: `translateX(${translate_x.toString()}px) scaleX(${scale_x.toString()})`,

src/components/player-artwork.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ export class MassPlayerArtwork extends LitElement {
9999
image: img
100100
}
101101
const ev = new CustomEvent('artwork-updated', { detail: detail });
102+
const elem = this.shadowRoot?.querySelectorAll('sl-carousel-item')[idx];
103+
if (elem) {
104+
this.controller.ActivePlayer.activeArtworkElement = elem.firstElementChild as HTMLElement;
105+
}
102106
this.controller.host.dispatchEvent(ev);
103107
this._timeout = setTimeout(
104108
() => {
@@ -117,10 +121,10 @@ export class MassPlayerArtwork extends LitElement {
117121
return item?.playing
118122
}
119123
)
120-
if (idx >= 0) {
124+
if (idx >= 0 && idx != this.carouselElement?.activeSlide) {
121125
this.currentIdx = idx;
122-
this.setActiveSlide(this.currentIdx)
123126
}
127+
this.setActiveSlide(this.currentIdx)
124128
}
125129

126130
private onSwipe = (ev: SLSwipeEvent) => {

src/controller/active-player.ts

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ import { DynamicScheme } from "@material/material-color-utilities";
2323
import { getGroupVolumeServiceResponse, getGroupVolumeServiceSchema } from "mass-queue-types/packages/mass_queue/actions/get_group_volume";
2424
import { setGroupVolumeServiceSchema } from "mass-queue-types/packages/mass_queue/actions/set_group_volume";
2525
import { isActive, jsonMatch, playerHasUpdated } from "../utils/util";
26-
import { applyDefaultExpressiveScheme, applyExpressiveSchemeFromImage } from "../utils/expressive";
27-
import { ArtworkUpdatedEventData } from "../const/events";
26+
import {
27+
applyExpressiveScheme,
28+
generateDefaultExpressiveSchemeColor,
29+
generateExpressiveSchemeFromColor,
30+
generateExpressiveSourceColorFromImage
31+
} from "../utils/expressive.js";
2832

2933
export class ActivePlayerController {
3034
private _activeEntityConfig: ContextProvider<typeof activeEntityConfContext>;
@@ -42,6 +46,8 @@ export class ActivePlayerController {
4246
private _config!: Config;
4347
private _host: HTMLElement;
4448
private _updatingScheme = false;
49+
private _activeArtworkElement?: HTMLElement;
50+
private _activeSchemeColor!: number;
4551

4652
constructor(hass: ExtendedHass, config: Config, host: HTMLElement) {
4753
this._expressiveScheme = new ContextProvider(host, {
@@ -77,7 +83,6 @@ export class ActivePlayerController {
7783
this._hass = hass;
7884
this.config = config;
7985
this._host = host;
80-
host.addEventListener("artwork-updated", this.onActiveTrackChange);
8186
this.setDefaultActivePlayer();
8287
}
8388
public set hass(hass: ExtendedHass) {
@@ -135,18 +140,6 @@ export class ActivePlayerController {
135140
if (player.attributes?.group_members) {
136141
this.setGroupAttributes();
137142
}
138-
if (
139-
isActive(this.hass, this.activeMediaPlayer, this.activeEntityConfig)
140-
&& (
141-
!this.expressiveScheme
142-
|| player.attributes.media_content_id != this.activeMediaPlayer.attributes.media_content_id
143-
)
144-
) {
145-
const img =
146-
player.attributes.entity_picture_local ??
147-
player.attributes.entity_picture;
148-
void this.applyExpressiveSchemeFromImage(img);
149-
}
150143
}
151144
}
152145
public get activeMediaPlayer() {
@@ -217,6 +210,17 @@ export class ActivePlayerController {
217210
return this._activePlayerData.value;
218211
}
219212

213+
public set activeArtworkElement(elem: HTMLElement | undefined) {
214+
if (!elem) {
215+
return
216+
}
217+
this._activeArtworkElement = elem;
218+
this.createAndApplyExpressiveScheme();
219+
}
220+
public get activeArtworkElement() {
221+
return this._activeArtworkElement;
222+
}
223+
220224
public async updateActivePlayerData() {
221225
if (!this.activeMediaPlayer || !this.volumeMediaPlayer || !this.activeEntityID) {
222226
return;
@@ -235,14 +239,6 @@ export class ActivePlayerController {
235239
});
236240
this._host.dispatchEvent(ev);
237241
}
238-
public firstUpdateComplete() {
239-
if (
240-
!isActive(this.hass, this.activeMediaPlayer, this.activeEntityConfig) ||
241-
!this.expressiveScheme
242-
) {
243-
this.applyDefaultExpressiveScheme();
244-
}
245-
}
246242
private setGroupAttributes() {
247243
this.groupMembers = this.getGroupedPlayers().map((item) => {
248244
return item.entity_id;
@@ -334,36 +330,45 @@ export class ActivePlayerController {
334330
const result = ret.response[entity_id];
335331
return result;
336332
}
337-
public onActiveTrackChange = (ev: Event) => {
338-
const detail = (ev as ArtworkUpdatedEventData).detail;
339-
if (detail.type != "current") {
340-
return;
341-
}
342-
const img = detail.image;
343-
if (!img || !(this.activeMediaPlayer.state == 'playing') ) {
344-
return;
345-
}
346-
void this.applyExpressiveSchemeFromImage(img);
347-
};
348-
public applyDefaultExpressiveScheme() {
349-
if (!this.config.expressive || this._updatingScheme) {
333+
public createAndApplyExpressiveScheme() {
334+
void this.createExpressiveSchemeFromArtwork().then(
335+
(result) => {
336+
if (!result) {
337+
return;
338+
}
339+
this.applyExpressiveScheme();
340+
}
341+
);
342+
}
343+
public applyExpressiveScheme() {
344+
const scheme = this.expressiveScheme;
345+
if (!scheme) {
350346
return;
351347
}
352-
this._host.getRootNode()
353-
this.expressiveScheme = applyDefaultExpressiveScheme(this.hass, this.config.expressive_scheme, this._host);
348+
applyExpressiveScheme(scheme, this._host)
354349
}
355-
public async applyExpressiveSchemeFromImage(img: string) {
356-
if (!this.config.expressive || this._updatingScheme) {
350+
public async createExpressiveSchemeFromArtwork(): Promise<DynamicScheme | undefined> {
351+
if (this._updatingScheme) {
357352
return;
358353
}
359354
this._updatingScheme = true;
360-
this.expressiveScheme = await applyExpressiveSchemeFromImage(
361-
img,
362-
this.hass,
363-
this.config.expressive_scheme,
364-
this._host,
365-
);
355+
let schemeColor: number;
356+
if (!(this?.activeArtworkElement?.tagName?.toLowerCase() == 'img')) {
357+
schemeColor = generateDefaultExpressiveSchemeColor();
358+
} else {
359+
const src = (this.activeArtworkElement as HTMLImageElement).src;
360+
schemeColor = await generateExpressiveSourceColorFromImage(src, this.hass);
361+
}
362+
if (schemeColor == this._activeSchemeColor) {
363+
this._updatingScheme = false;
364+
return;
365+
}
366+
this._activeSchemeColor = schemeColor;
367+
const schemeName = this.config.expressive_scheme;
368+
const scheme = generateExpressiveSchemeFromColor(schemeColor, schemeName, this.hass.themes.darkMode);
369+
this.expressiveScheme = scheme;
366370
this._updatingScheme = false;
371+
return this.expressiveScheme;
367372
}
368373
private async _getAndSetGroupedVolume() {
369374
const entity = this.activeMediaPlayer.entity_id;
@@ -407,11 +412,10 @@ export class ActivePlayerController {
407412
return vol;
408413
}
409414
public disconnected() {
410-
this._host.removeEventListener("artwork-updated", this.onActiveTrackChange);
415+
// Intentionally left blank
411416
}
412417
public reconnected(hass: ExtendedHass) {
413418
this.hass = hass;
414-
this._host.addEventListener("artwork-updated", this.onActiveTrackChange);
415419
this.setActivePlayer(this.activeEntityID);
416420
}
417421
}

src/main.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ export class MusicAssistantPlayerCard extends LitElement {
323323
//eslint-disable-next-line @typescript-eslint/no-non-null-assertion
324324
const stylesheet = head_styles.styleSheet!;
325325
document.adoptedStyleSheets.push(stylesheet);
326-
this._controller.ActivePlayer.firstUpdateComplete();
327326
}
328327
this.addEventListener("section-changed", this.onSectionChangedEvent);
329328
}

0 commit comments

Comments
 (0)