Files
fx_cast/ext/src/ui/popup/Receiver.svelte
2022-08-24 02:17:35 +01:00

180 lines
5.6 KiB
Svelte

<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import { PlayerState } from "../../cast/sdk/media/enums";
import { SenderMediaMessage, SenderMessage } from "../../cast/sdk/types";
import { ReceiverDevice } from "../../types";
import { Port } from "../../messaging";
import LoadingIndicator from "../LoadingIndicator.svelte";
import ReceiverMedia from "./ReceiverMedia.svelte";
const _ = browser.i18n.getMessage;
const dispatch = createEventDispatcher<{
cast: { device: ReceiverDevice };
stop: { device: ReceiverDevice };
}>();
export let port: Nullable<Port>;
/** Whether there are sessions being established for any receiver. */
export let isAnyConnecting: boolean;
/** Whether the selected media type is available for this receiver. */
export let isMediaTypeAvailable: boolean;
/** Receiver device to display. */
export let device: ReceiverDevice;
/** Current receiver application (if available) */
$: application = device.status?.applications?.[0];
/** Current media status (if available) */
$: mediaStatus = device.mediaStatus;
let isExpanded = false;
let isConnecting = false;
function sendReceiverMessage(
partialMessage: DistributiveOmit<SenderMessage, "requestId">
) {
const message: SenderMessage = {
...partialMessage,
requestId: 0
};
port?.postMessage({
subject: "receiverSelector:receiverMessage",
data: { deviceId: device.id, message }
});
}
function sendMediaMessage(
partialMessage: DistributiveOmit<
SenderMediaMessage,
"requestId" | "mediaSessionId"
>
) {
if (!device.mediaStatus) return;
const message: SenderMediaMessage = {
...(partialMessage as any),
requestId: 0,
mediaSessionId: device.mediaStatus.mediaSessionId
};
port?.postMessage({
subject: "receiverSelector:mediaMessage",
data: { deviceId: device.id, message }
});
}
onMount(() => {
sendMediaMessage({
type: "GET_STATUS"
});
});
</script>
<li class="receiver">
<div class="receiver__details">
<div class="receiver__name">
{device.friendlyName}
</div>
{#if application && !application.isIdleScreen}
<div class="receiver__status">
<span class="receiver__app-name">
{application.displayName}
</span>
{#if application.statusText !== application.displayName}
· {application.statusText}
{/if}
</div>
{/if}
</div>
{#if application && !application.isIdleScreen}
<button
class="receiver__stop-button"
on:click={() => dispatch("stop", { device })}
>
{_("popupStopButtonTitle")}
</button>
{:else}
<button
class="receiver__cast-button"
disabled={isConnecting || isAnyConnecting || !isMediaTypeAvailable}
on:click={() => {
isConnecting = true;
dispatch("cast", { device });
}}
>
{#if isConnecting}
{_("popupCastingButtonTitle", "")}<LoadingIndicator />
{:else}
{_("popupCastButtonTitle")}
{/if}
</button>
{/if}
<button
type="button"
class="receiver__expand-button ghost"
class:receiver__expand-button--expanded={isExpanded}
title={_("popupShowDetailsTitle")}
disabled={!mediaStatus}
on:click={() => {
isExpanded = !isExpanded;
}}
/>
{#if isExpanded}
<div class="receiver__expanded">
{#if mediaStatus}
<ReceiverMedia
status={mediaStatus}
{device}
on:togglePlayback={() => {
switch (mediaStatus?.playerState) {
case PlayerState.PLAYING:
sendMediaMessage({ type: "PAUSE" });
break;
case PlayerState.PAUSED:
sendMediaMessage({ type: "PLAY" });
break;
}
}}
on:previous={() => {
sendMediaMessage({
type: "QUEUE_UPDATE",
jump: -1
});
}}
on:next={() => {
sendMediaMessage({
type: "QUEUE_UPDATE",
jump: 1
});
}}
on:seek={ev => {
sendMediaMessage({
type: "SEEK",
currentTime: ev.detail.position
});
}}
on:trackChanged={ev => {
sendMediaMessage({
type: "EDIT_TRACKS_INFO",
activeTrackIds: ev.detail.activeTrackIds
});
}}
on:volumeChanged={ev => {
sendReceiverMessage({
type: "SET_VOLUME",
volume: ev.detail
});
}}
/>
{/if}
</div>
{/if}
</li>