Skip to content

Commit

Permalink
feature: use apply button for predefined groups as well
Browse files Browse the repository at this point in the history
  • Loading branch information
punxaphil committed Feb 24, 2024
1 parent 8783270 commit 71ac51f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 65 deletions.
95 changes: 64 additions & 31 deletions src/sections/grouping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ import { dispatchActivePlayerId } from '../utils/utils';
import { listStyle } from '../constants';
import { MediaPlayer } from '../model/media-player';
import '../components/grouping-button';
import { PredefinedGroup, PredefinedGroupPlayer } from '../types';

export class Grouping extends LitElement {
@property({ attribute: false }) store!: Store;
private groupingItems!: GroupingItem[];
private activePlayer!: MediaPlayer;
private mediaControlService!: MediaControlService;
private allGroups!: MediaPlayer[];
private mediaPlayerIds!: string[];
private notJoinedPlayers!: string[];
private joinedPlayers!: string[];
@state() modifiedItems: string[] = [];

render() {
this.activePlayer = this.store.activePlayer;
this.allGroups = this.store.allGroups;
this.mediaControlService = this.store.mediaControlService;
this.mediaPlayerIds = this.store.allMediaPlayers.map((player) => player.id);
this.groupingItems = this.getGroupingItems();
Expand All @@ -42,7 +41,7 @@ export class Grouping extends LitElement {
class="icon"
selected=${item.isSelected || nothing}
.icon="mdi:${item.icon}"
@click=${() => this.itemClick(item)}
@click=${() => this.toggleItem(item)}
></ha-icon>
<div class="name-and-volume">
<span class="name">${item.name}</span>
Expand Down Expand Up @@ -145,40 +144,58 @@ export class Grouping extends LitElement {
];
}

itemClick(item: GroupingItem) {
toggleItem(item: GroupingItem) {
if (item.isDisabled) {
return;
}
this.toggleItemWithoutDisabledCheck(item);
}

private toggleItemWithoutDisabledCheck(item: GroupingItem) {
if (this.modifiedItems.includes(item.player.id)) {
this.modifiedItems = this.modifiedItems.filter((id) => id !== item.player.id);
} else {
this.modifiedItems = [...this.modifiedItems, item.player.id];
}
}

async applyGrouping() {
const isSelected = this.groupingItems.filter((item) => item.isSelected);
const unjoin = this.groupingItems
const unJoin = this.groupingItems
.filter((item) => !item.isSelected && this.joinedPlayers.includes(item.player.id))
.map((item) => item.player.id);
const join = this.groupingItems
.filter((item) => item.isSelected && !this.joinedPlayers.includes(item.player.id))
.map((item) => item.player.id);

let main = this.activePlayer.id;
if (unjoin.includes(this.activePlayer.id)) {
main = isSelected[0].player.id;
dispatchActivePlayerId(main, this.store.config, this);
}

if (unjoin.length > 0) {
await this.mediaControlService.unJoin(unjoin);
if (unJoin.length > 0) {
await this.mediaControlService.unJoin(unJoin);
}
if (join.length > 0) {
await this.mediaControlService.join(main, join);
}
await this.handlePredefinedGroupConfig(isSelected);
if (unJoin.includes(this.activePlayer.id)) {
main = isSelected[0].player.id;
dispatchActivePlayerId(main, this.store.config, this);
}
this.modifiedItems = [];
}

private async handlePredefinedGroupConfig(isSelected: GroupingItem[]) {
const predefinedGroup = this.store.predefinedGroups.find((pg) => {
return (
pg.entities.length === isSelected.length &&
pg.entities.every((pgp) => isSelected.some((s) => s.player.id === pgp.player.id))
);
});
if (predefinedGroup) {
await this.mediaControlService.setVolumeAndMediaForPredefinedGroup(predefinedGroup);
}
}

private cancelGrouping() {
this.groupingItems = this.getGroupingItems();
}
Expand All @@ -196,14 +213,13 @@ export class Grouping extends LitElement {
}

private renderJoinAllButton() {
return when(this.notJoinedPlayers.length, () => {
return html`
<sonos-grouping-button
@click=${async () => await this.mediaControlService.join(this.activePlayer.id, this.notJoinedPlayers)}
.icon=${'mdi:checkbox-multiple-marked-outline'}
></sonos-grouping-button>
`;
});
return when(this.notJoinedPlayers.length, () =>
this.groupingButton('mdi:checkbox-multiple-marked-outline', this.selectAll),
);
}

private groupingButton(icon: string, click: () => void) {
return html` <sonos-grouping-button @click=${click} .icon=${icon}></sonos-grouping-button> `;
}

private getNotJoinedPlayers() {
Expand All @@ -213,14 +229,9 @@ export class Grouping extends LitElement {
}

private renderUnJoinAllButton() {
return when(this.joinedPlayers.length, () => {
return html`
<sonos-grouping-button
@click=${async () => await this.mediaControlService.unJoin(this.joinedPlayers)}
.icon=${'mdi:minus-box-multiple-outline'}
></sonos-grouping-button>
`;
});
return when(this.joinedPlayers.length, () =>
this.groupingButton('mdi:minus-box-multiple-outline', this.deSelectAll),
);
}

private getJoinedPlayers() {
Expand All @@ -233,16 +244,38 @@ export class Grouping extends LitElement {
return this.store.predefinedGroups.map((predefinedGroup) => {
return html`
<sonos-grouping-button
@click=${async () => {
this.modifiedItems = [];
await this.mediaControlService.createGroup(predefinedGroup, this.allGroups, this);
}}
@click=${async () => this.selectPredefinedGroup(predefinedGroup)}
.icon=${'mdi:speaker-multiple'}
.name=${predefinedGroup.name}
></sonos-grouping-button>
`;
});
}

private selectPredefinedGroup(predefinedGroup: PredefinedGroup<PredefinedGroupPlayer>) {
this.groupingItems.forEach((item) => {
const inPG = predefinedGroup.entities.some((pgp) => pgp.player.id === item.player.id);
if ((inPG && !item.isSelected) || (!inPG && item.isSelected)) {
this.toggleItemWithoutDisabledCheck(item);
}
});
}

private selectAll() {
this.groupingItems.forEach((item) => {
if (!item.isSelected) {
this.toggleItem(item);
}
});
}

private deSelectAll() {
this.groupingItems.forEach((item) => {
if ((!item.isMain && item.isSelected) || (item.isMain && !item.isSelected)) {
this.toggleItem(item);
}
});
}
}

class GroupingItem {
Expand Down
35 changes: 1 addition & 34 deletions src/services/media-control-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { CardConfig, MediaPlayerItem, PredefinedGroup } from '../types';
import HassService from './hass-service';
import { dispatchActivePlayerId } from '../utils/utils';
import { MediaPlayer } from '../model/media-player';

export default class MediaControlService {
Expand All @@ -19,45 +18,13 @@ export default class MediaControlService {
});
}

private async joinPredefinedGroup(player: MediaPlayer, pg: PredefinedGroup) {
const ids = pg.entities.map(({ player }) => player.id);
await this.join(player.id, ids);
}

async unJoin(playerIds: string[]) {
await this.hassService.callMediaService('unjoin', {
entity_id: playerIds,
});
}

async createGroup(predefinedGroup: PredefinedGroup, currentGroups: MediaPlayer[], element: Element) {
let candidateGroup!: MediaPlayer;
for (const group of currentGroups) {
if (predefinedGroup.entities.some((item) => item.player.id === group.id)) {
if (group.isPlaying()) {
await this.modifyExistingGroup(group, predefinedGroup, element);
return;
}
candidateGroup = candidateGroup || group;
}
}
if (candidateGroup) {
await this.modifyExistingGroup(candidateGroup, predefinedGroup, element);
} else {
const { player } = predefinedGroup.entities[0];
dispatchActivePlayerId(player.id, this.config, element);
await this.joinPredefinedGroup(player, predefinedGroup);
}
}

private async modifyExistingGroup(group: MediaPlayer, pg: PredefinedGroup, element: Element) {
const members = group.members;
const membersNotToBeGrouped = members.filter((member) => !pg.entities.some((item) => item.player.id === member.id));
if (membersNotToBeGrouped?.length) {
await this.unJoin(membersNotToBeGrouped.map((member) => member.id));
}
dispatchActivePlayerId(group.id, this.config, element);
await this.joinPredefinedGroup(group, pg);
async setVolumeAndMediaForPredefinedGroup(pg: PredefinedGroup) {
for (const pgp of pg.entities) {
const volume = pgp.volume ?? pg.volume;
if (volume) {
Expand Down

0 comments on commit 71ac51f

Please sign in to comment.