+
+
mdi-lock-alert
+
+ {{ $t("providers.party_mode.no_player_access") }}
+
+
+ {{ $t("providers.party_mode.no_player_access_detail") }}
+
+
+
@@ -76,8 +89,22 @@ const theme = useTheme();
const route = useRoute();
const { config: partyConfig, fetchConfig } = usePartyModeConfig();
+const refreshPartyPlayer = async () => {
+ const partyPlayerId = await api.sendCommand
(
+ "party_mode/player",
+ );
+ accessError.value = "";
+ if (partyPlayerId) {
+ store.activePlayerId = partyPlayerId;
+ if (!api.players[partyPlayerId]) {
+ accessError.value = "no_access";
+ }
+ }
+};
+
const albumArtBackgroundEnabled = ref(true); // Default to true
const showPlayerControls = ref(false); // Whether footer player controls are shown
+const accessError = ref("");
// Badge colors (hex values from config)
const requestBadgeColor = ref("");
const boostBadgeColor = ref("");
@@ -352,14 +379,7 @@ onMounted(async () => {
// Set active player from party mode config (needed when opened in a new tab
// where the Default layout's player selection logic doesn't run)
- if (!store.activePlayerId) {
- const partyPlayerId = await api.sendCommand(
- "party_mode/player",
- );
- if (partyPlayerId) {
- store.activePlayerId = partyPlayerId;
- }
- }
+ await refreshPartyPlayer();
// Fetch party mode configuration via shared composable
const config = await fetchConfig();
@@ -398,7 +418,13 @@ onMounted(async () => {
fetchQueueItems();
});
- unsubscribeFunctions.value = [unsub1, unsub2];
+ // Subscribe to provider updates to detect party mode player config changes
+ const unsub3 = api.subscribe(EventType.PROVIDERS_UPDATED, async () => {
+ await refreshPartyPlayer();
+ fetchQueueItems(true);
+ });
+
+ unsubscribeFunctions.value = [unsub1, unsub2, unsub3];
});
// Cleanup when leaving the party view
@@ -557,6 +583,32 @@ watch(
opacity: 0;
}
+/* Access error state */
+.access-error-content {
+ justify-content: center;
+}
+
+.access-error {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ gap: 1rem;
+ padding: 2rem;
+}
+
+.access-error-title {
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.access-error-message {
+ font-size: 1rem;
+ color: rgba(255, 255, 255, 0.7);
+ max-width: 400px;
+}
+
/* Responsive adjustments */
@media (max-width: 1024px) {
.party-content {
diff --git a/src/views/PartyModeGuestView.vue b/src/views/PartyModeGuestView.vue
index 860e4bc59..9f3fe6360 100644
--- a/src/views/PartyModeGuestView.vue
+++ b/src/views/PartyModeGuestView.vue
@@ -8,6 +8,7 @@
:show-back="hasSearched || !!selectedArtist"
@clear="clearSearch"
@back="goBack"
+ @submit="performSearch"
/>
@@ -65,7 +66,11 @@
:boost-badge-color="boostBadgeColor"
:request-badge-color="requestBadgeColor"
:adding-items="addingItems"
+ :is-expanded="
+ expandedResultItemId === `${track.media_type}-${track.item_id}`
+ "
@add-to-queue="addToQueue"
+ @toggle-expand="toggleExpandedResult"
/>
@@ -119,8 +124,12 @@
:boost-badge-color="boostBadgeColor"
:request-badge-color="requestBadgeColor"
:adding-items="addingItems"
+ :is-expanded="
+ expandedResultItemId === `${item.media_type}-${item.item_id}`
+ "
@add-to-queue="addToQueue"
@select-artist="selectArtist"
+ @toggle-expand="toggleExpandedResult"
/>