89 lines
2.5 KiB
Vue
89 lines
2.5 KiB
Vue
<script setup lang="ts">
|
|
import {
|
|
Maximize2,
|
|
Minimize2,
|
|
LogOut,
|
|
Radio,
|
|
Wifi,
|
|
RotateCw,
|
|
} from "lucide-vue-next";
|
|
const { t } = useI18n();
|
|
useHead({ title: computed(() => `${t("nav.watch")} · Webka`) });
|
|
const session = useSessionStore();
|
|
const { remote, state, error, resolution, start, stop } = useStream("viewer");
|
|
const player = ref<HTMLElement>(),
|
|
full = ref(false),
|
|
actionError = ref("");
|
|
onMounted(() => {
|
|
void start();
|
|
document.addEventListener("fullscreenchange", changed);
|
|
});
|
|
onBeforeUnmount(() =>
|
|
document.removeEventListener("fullscreenchange", changed),
|
|
);
|
|
function changed() {
|
|
full.value = !!document.fullscreenElement;
|
|
}
|
|
async function fullscreen() {
|
|
try {
|
|
if (document.fullscreenElement) await document.exitFullscreen();
|
|
else await player.value?.requestFullscreen();
|
|
} catch {
|
|
actionError.value = t("errors.fullscreen");
|
|
}
|
|
}
|
|
async function disconnect() {
|
|
stop();
|
|
await session.logout();
|
|
}
|
|
</script>
|
|
<template>
|
|
<div ref="player" class="watch-page">
|
|
<StreamVideo v-if="remote" :stream="remote" />
|
|
<div v-else class="watch-empty">
|
|
<Radio :size="44" :stroke-width="1.2" />
|
|
<div class="eyebrow">{{ $t(`stream.${state}`) }}</div>
|
|
<h1>
|
|
{{
|
|
$t(
|
|
state === "waiting"
|
|
? "watch.waitingTitle"
|
|
: "watch.connectingTitle",
|
|
)
|
|
}}
|
|
</h1>
|
|
<p>
|
|
{{
|
|
$t(state === "waiting" ? "watch.waitingHint" : "watch.connectingHint")
|
|
}}
|
|
</p>
|
|
<GlassButton v-if="state === 'offline'" @click="start"
|
|
><RotateCw :size="18" />{{ $t("watch.reconnect") }}</GlassButton
|
|
>
|
|
</div>
|
|
<p v-if="error || actionError" class="error watch-error" role="alert">
|
|
{{ error || actionError }}
|
|
</p>
|
|
<GlassCard class="watch-controls"
|
|
><span class="watch-state" role="status"
|
|
><span class="status-dot" :class="{ live: state === 'live' }" />{{
|
|
$t(`stream.${state}`)
|
|
}}</span
|
|
><span class="watch-quality"
|
|
><Wifi :size="17" />{{ resolution || $t("quality.auto") }}</span
|
|
><GlassButton
|
|
class="icon-button"
|
|
:aria-label="$t('watch.fullscreen')"
|
|
@click="fullscreen"
|
|
><Minimize2 v-if="full" :size="20" /><Maximize2
|
|
v-else
|
|
:size="20" /></GlassButton
|
|
><GlassButton @click="disconnect"
|
|
><LogOut :size="18" /><span>{{
|
|
$t("watch.disconnect")
|
|
}}</span></GlassButton
|
|
><LanguageSwitcher v-if="full"
|
|
/></GlassCard>
|
|
</div>
|
|
</template>
|