Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/__tests__/sidebar-room-actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ vi.mock('@/components/ThePwaInstall.vue', () => ({ default: { template: '<div />
vi.mock('@/components/ReportProblem.vue', () => ({ default: { template: '<div />' } }));
vi.mock('@/components/TheSettingsDialog.vue', () => ({ default: { template: '<div />' } }));

const setup = (component, inRoom = true) => {
const setup = (component, inRoom = true, host = null) => {
const disconnect = vi.fn();
const store = createStore({
state: { isLeftSidebarOpen: true, isRightSidebarOpen: true },
Expand All @@ -31,7 +31,7 @@ const setup = (component, inRoom = true) => {
getters: {
IS_IN_ROOM: () => inRoom,
GET_USERS: () => ({ me: { username: 'Me' } }),
GET_HOST_USER: () => null,
GET_HOST_USER: () => host,
AM_I_HOST: () => false,
IS_PARTY_PAUSING_ENABLED: () => false,
IS_AUTO_HOST_ENABLED: () => false,
Expand Down Expand Up @@ -79,6 +79,14 @@ describe('sidebar close and room exit', () => {
} finally { wrapper.unmount(); }
});

it('omits host-only control rows for a viewer during playback', () => {
const { wrapper } = setup(TheSidebarRight, true, { username: 'Host', state: 'playing' });
try {
expect(wrapper.findAll('.switch-item')).toHaveLength(0);
expect(wrapper.get('[aria-label="Pause party"]').exists()).toBe(true);
} finally { wrapper.unmount(); }
});

it('disconnects only through the labeled navigation action', async () => {
const { wrapper, store, disconnect } = setup(TheSidebarLeft);
try {
Expand Down
24 changes: 13 additions & 11 deletions src/components/TheSidebarRight.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
@update:model-value="SET_ADVANCED_PARTY_MODE"
/>
<v-list-item
v-if="AM_I_HOST || (GET_HOST_USER && GET_HOST_USER.state === 'stopped')"
density="compact"
class="px-3 py-0 switch-item"
>
Expand All @@ -59,7 +60,7 @@
v-if="AM_I_HOST"
class="text-caption text-medium-emphasis pb-2"
>
Viewers can pause or resume everyone’s playback when this is enabled.
Allow viewers to pause or resume everyone.
</p>

<v-list-item-subtitle
Expand Down Expand Up @@ -226,7 +227,7 @@ export default {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 16px;
padding: 8px 12px;
border-bottom: 1px solid var(--sl-border);
}

Expand All @@ -238,34 +239,35 @@ export default {
.party-body {
display: flex;
flex-direction: column;
min-height: 100%;
height: 100%;
min-height: 0;
}

.party-controls,
.party-users {
flex: 0 0 auto;
}
.party-controls { flex: 0 0 auto; }
.party-users { flex: 0 1 auto; min-height: 0; }

.messages {
overflow-y: auto;
flex: 1 0 180px;
max-height: 60dvh;
min-height: 180px;
flex: 1 1 96px;
min-height: 96px;
}

.participant-count {
font-size: 0.8em;
color: rgb(255 255 255 / 70%);
}

.party-controls :deep(.v-selection-control) { min-height: 36px; }
.party-controls :deep(.v-input) { flex: 0 0 auto; }

.party-controls :deep(.v-label) { white-space: normal; }

.switch-item :deep(.v-list-item__content) {
overflow: visible;
}

.sidebar-switch :deep(.v-selection-control) {
min-height: 44px;
min-height: 36px;
}

.sidebar-switch :deep(.v-switch__track) {
Expand Down
36 changes: 25 additions & 11 deletions src/components/UserList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<v-list-item
v-for="(user, id) in GET_USERS"
:key="id"
class="user-row px-3 py-2"
class="user-row"
>
<div class="user-heading">
<v-avatar
Expand Down Expand Up @@ -45,7 +45,10 @@
class="text-medium-emphasis"
>(you)</span>
</div>
<span class="user-time">{{ getTimeFromMs(getAdjustedTime(user)) }}</span>
<div class="user-meta">
<span class="user-time">{{ getTimeFromMs(getAdjustedTime(user)) }}</span>
<span class="user-readiness">{{ readinessLabel(user, id) }}</span>
</div>
</div>
</template>
{{ getTitle(user.media) }}
Expand All @@ -59,7 +62,7 @@
<div class="user-actions">
<v-chip
v-if="id === GET_HOST_ID"
size="small"
size="x-small"
color="primary"
variant="tonal"
>
Expand All @@ -71,6 +74,7 @@
v-bind="props"
icon="more_vert"
size="small"
class="participant-action"
variant="text"
:aria-label="`Actions for ${user.username}`"
:title="`Actions for ${user.username}`"
Expand All @@ -91,9 +95,11 @@
</v-menu>
</div>
</div>
<div class="user-status text-caption text-medium-emphasis">
<span>{{ readinessLabel(user, id) }}</span>
<span v-if="GET_ADVANCED_PARTY_MODE">{{ driftLabel(user) }}</span>
<div
v-if="GET_ADVANCED_PARTY_MODE"
class="user-status text-caption text-medium-emphasis"
>
{{ driftLabel(user) }}
</div>
<ul
v-if="user.health && GET_ADVANCED_PARTY_MODE"
Expand All @@ -107,7 +113,8 @@
</li>
</ul>
<v-progress-linear
class="pt-content-progress mt-2"
v-if="GET_ADVANCED_PARTY_MODE"
class="pt-content-progress mt-1"
:height="2"
:model-value="percent(user)"
/>
Expand Down Expand Up @@ -368,7 +375,8 @@ export default {
.moderation-actions { flex-wrap: wrap; }

.user-list {
max-height: calc(50vh - 100px);
padding-block: 0;
min-height: 0;
}

.avatar-img {
Expand Down Expand Up @@ -404,7 +412,12 @@ export default {
border-color: #0de47499;
}

.user-heading { display: flex; align-items: center; gap: 10px; min-width: 0; }
.user-row { min-height: 52px; padding: 6px 12px; }
.user-meta { display: flex; align-items: baseline; gap: 8px; line-height: 18px; color: rgb(255 255 255 / 65%); }
.user-readiness { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.participant-action { width: 32px; height: 32px; }
@media (pointer: coarse) { .participant-action { width: 40px; height: 40px; } }
.user-heading { display: flex; align-items: center; gap: 8px; min-width: 0; }
.user-avatar, .user-actions { flex-shrink: 0; }
.user-identity { flex: 1 1 auto; min-width: 0; }
.user-actions { display: flex; align-items: center; gap: 2px; }
Expand All @@ -414,15 +427,16 @@ export default {
.user-row + .user-row { border-top: 1px solid rgba(255, 255, 255, 0.06); }

.user-name {
font-size: 14px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}

.user-time {
font-size: 75%;
opacity: 0.7;
font-size: 12px;
flex-shrink: 0;
}
</style>
9 changes: 6 additions & 3 deletions test/fixtures/ui-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ const image = (text, background = '#29231d') => `data:image/svg+xml,${encodeURIC
// eslint-disable-next-line max-len
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 450"><rect width="300" height="450" fill="${background}"/><circle cx="150" cy="170" r="70" fill="#e5a00d"/><path d="m135 135 50 35-50 35z" fill="#17120a"/><text x="150" y="300" text-anchor="middle" fill="white" font-family="sans-serif" font-size="20">${text}</text></svg>`,
)}`;
const users = Object.fromEntries(['Alex', 'Morgan', 'Sam', 'Taylor with a long name'].map((username, i) => [
const participantNames = ['Alex', 'Morgan', 'Sam', 'Taylor with a long name', 'Jordan', 'Riley'];
const users = Object.fromEntries(participantNames.map((username, i) => [
`user-${i}`, {
username,
thumb: image(username.slice(0, 1), ['#303e52', '#49304b', '#28504b', '#503b27'][i]),
state: ['playing', 'paused', 'buffering', 'playing'][i],
thumb: image(username.slice(0, 1), ['#303e52', '#49304b', '#28504b', '#503b27'][i % 4]),
state: ['playing', 'paused', 'buffering', 'playing', 'playing', 'playing'][i],
time: 360000,
duration: 7200000,
updatedAt: Date.now(),
Expand Down Expand Up @@ -155,6 +156,8 @@ const store = createStore({
IS_AUTO_HOST_ENABLED: (state) => state.autoHost,
},
mutations: {
SET_PREVIEW_HOST(state, id) { state.hostId = id; },
SET_PREVIEW_MESSAGES(state, messages) { state.messages = messages; },
ADD_MESSAGE(state, text) { state.messages.push({ senderId: 'user-0', time: Date.now(), text }); },
SET_SYNC_PRESET(state, value) { state.syncPreset = value; },
SET_PAUSING(state, value) { state.pausing = value; },
Expand Down
4 changes: 3 additions & 1 deletion test/fixtures/ui-preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
Watch party preview
</h1>
<p class="mb-4">
Four sample participants. Messages and party controls stay in this fixture’s memory.
Six sample participants. Messages and party controls stay in this fixture’s memory.
</p>
<v-btn
color="primary"
Expand All @@ -126,6 +126,8 @@
<v-btn class="mb-4 ml-2" @click="$store.commit('SET_LEFT_SIDEBAR_OPEN', true)">
Open navigation
</v-btn>
<v-btn class="mb-4" @click="$store.commit('synclounge/SET_PREVIEW_HOST', 'user-1')">Preview as viewer</v-btn>
<v-btn class="mb-4" @click="$store.commit('synclounge/SET_PREVIEW_MESSAGES', [])">Empty chat</v-btn>
<div class="preview-chat">
<MessageList />
<MessageInput />
Expand Down
Loading