diff --git a/src/sections/grouping.ts b/src/sections/grouping.ts
index e3334e01..78fe9327 100755
--- a/src/sections/grouping.ts
+++ b/src/sections/grouping.ts
@@ -7,13 +7,13 @@ 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[];
@@ -21,7 +21,6 @@ export class Grouping extends LitElement {
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();
@@ -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)}
>
${item.name}
@@ -145,19 +144,24 @@ 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
@@ -165,20 +169,33 @@ export class Grouping extends LitElement {
.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();
}
@@ -196,14 +213,13 @@ export class Grouping extends LitElement {
}
private renderJoinAllButton() {
- return when(this.notJoinedPlayers.length, () => {
- return html`
-
await this.mediaControlService.join(this.activePlayer.id, this.notJoinedPlayers)}
- .icon=${'mdi:checkbox-multiple-marked-outline'}
- >
- `;
- });
+ return when(this.notJoinedPlayers.length, () =>
+ this.groupingButton('mdi:checkbox-multiple-marked-outline', this.selectAll),
+ );
+ }
+
+ private groupingButton(icon: string, click: () => void) {
+ return html`
`;
}
private getNotJoinedPlayers() {
@@ -213,14 +229,9 @@ export class Grouping extends LitElement {
}
private renderUnJoinAllButton() {
- return when(this.joinedPlayers.length, () => {
- return html`
-
await this.mediaControlService.unJoin(this.joinedPlayers)}
- .icon=${'mdi:minus-box-multiple-outline'}
- >
- `;
- });
+ return when(this.joinedPlayers.length, () =>
+ this.groupingButton('mdi:minus-box-multiple-outline', this.deSelectAll),
+ );
}
private getJoinedPlayers() {
@@ -233,16 +244,38 @@ export class Grouping extends LitElement {
return this.store.predefinedGroups.map((predefinedGroup) => {
return html`
{
- this.modifiedItems = [];
- await this.mediaControlService.createGroup(predefinedGroup, this.allGroups, this);
- }}
+ @click=${async () => this.selectPredefinedGroup(predefinedGroup)}
.icon=${'mdi:speaker-multiple'}
.name=${predefinedGroup.name}
>
`;
});
}
+
+ private selectPredefinedGroup(predefinedGroup: PredefinedGroup
) {
+ 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 {
diff --git a/src/services/media-control-service.ts b/src/services/media-control-service.ts
index 06088867..3c24663c 100644
--- a/src/services/media-control-service.ts
+++ b/src/services/media-control-service.ts
@@ -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 {
@@ -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) {