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
13 changes: 5 additions & 8 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import Player from './components/Player.vue';
import { getVideoDataByHash } from './services/videoLookup';

const manifestUrl = ref<string | null>(null);
const title = ref('Microfrontends');
const subtitle = ref('Arquitetura do Futuro');
const description = ref('Aprenda como construir aplicações escaláveis e modulares usando a arquitetura de microfrontends.');
const title = ref('Error carregar titulo');
const subtitle = ref('');

onMounted(async () => {
const videoShared = await import('catalog/VideoShared') as any;
Expand All @@ -17,11 +16,9 @@ onMounted(async () => {

if (videoData) {
const { metadata } = videoData;

if (metadata.title) title.value = metadata.title;
if (metadata.synopsis && metadata.synopsis.length > 0) {
description.value = metadata.synopsis.join(' ');
}

if (metadata.category) subtitle.value = metadata.category;

if (metadata.manifestUrl) {
Expand All @@ -43,7 +40,7 @@ onMounted(async () => {
</script>

<template>
<Player :manifestUrl="manifestUrl" :title="title" :subtitle="subtitle" :description="description" />
<Player :manifestUrl="manifestUrl" :title="title" :subtitle="subtitle" />
</template>
<style>
@import "tailwindcss";
Expand Down
95 changes: 46 additions & 49 deletions src/components/Player.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,29 @@
<Loader2 class="w-16 h-16 text-white animate-spin" />
</div>

<div v-if="showDetails && !isPlaying && !isLoading"
class="absolute inset-0 flex items-end pointer-events-none z-10">
<div class="w-full bg-gradient-to-t from-black/95 via-black/70 via-black/40 to-transparent pb-24 pt-32">
<div class="p-12 max-w-4xl">
<h1 class="text-5xl mb-4 text-white drop-shadow-lg">{{ title }}</h1>
<p class="text-xl text-gray-200 mb-2 drop-shadow-md">{{ subtitle }}</p>
<p v-if="description" class="text-gray-300 text-lg drop-shadow-md max-w-2xl">{{ description }}</p>
<div v-if="showDetails && !isPlaying && !isLoading"
class="absolute inset-0 flex items-end pointer-events-none z-10">
<div class="w-full bg-gradient-to-t from-black/95 via-black/70 via-black/40 to-transparent pb-24 pt-32">

</div>
</div>
</div>

<div
:class="['absolute inset-0 bg-gradient-to-t from-black/90 via-transparent to-black/50 transition-opacity duration-300 z-20', showControls || !isPlaying ? 'opacity-100' : 'opacity-0']">
<div class="absolute top-0 left-0 right-0 p-6 flex items-center gap-4 z-30">
<button class="text-white hover:bg-white/20 p-2 rounded-full transition-colors z-40 pointer-events-auto" @click.stop="handleBack">
<ArrowLeft class="w-6 h-6" />
</button>
</div>
<div
:class="['absolute inset-0 bg-gradient-to-t from-black/90 via-transparent to-black/50 transition-opacity duration-300 z-20', showControls || !isPlaying ? 'opacity-100' : 'opacity-0']">
<div class="absolute top-0 left-0 right-0 p-6 flex items-center gap-4 z-30">
<button class="text-white hover:bg-white/20 p-2 rounded-full transition-colors z-40 pointer-events-auto"
@click.stop="handleBack">
<ArrowLeft class="w-6 h-6" />
</button>
</div>

<div v-if="!isPlaying && !isLoading" class="absolute inset-0 flex items-center justify-center pointer-events-none z-25">
<button @click.stop="togglePlay"
class="bg-white/20 hover:bg-white/30 backdrop-blur-sm p-8 rounded-full transition-all pointer-events-auto">
<Play class="w-16 h-16 text-white fill-white" />
</button>
</div>
<div v-if="!isPlaying && !isLoading"
class="absolute inset-0 flex items-center justify-center pointer-events-none z-25">
<button @click.stop="togglePlay"
class="bg-white/20 hover:bg-white/30 backdrop-blur-sm p-8 rounded-full transition-all pointer-events-auto">
<Play class="w-16 h-16 text-white fill-white" />
</button>
</div>

<div class="absolute bottom-0 left-0 right-0 p-6">
<div class="mb-4">
Expand Down Expand Up @@ -97,7 +95,7 @@
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { onMounted, onUnmounted, ref, watch, toRefs } from 'vue';
import {
ArrowLeft,
Loader2,
Expand All @@ -116,10 +114,9 @@ const props = defineProps<{
manifestUrl: string | null;
title: string;
subtitle: string;
description?: string;
}>();

const { manifestUrl, title, subtitle, description } = props;
const { manifestUrl, title, subtitle } = toRefs(props);

const showControls = ref(true);
const showDetails = ref(true);
Expand Down Expand Up @@ -158,7 +155,7 @@ function resetPlayer() {
for (const idx in prefetchedBlobUrls) {
try {
URL.revokeObjectURL(prefetchedBlobUrls[parseInt(idx)]);
} catch {
} catch {
// TODO:
}
}
Expand All @@ -174,7 +171,7 @@ function resetPlayer() {

try {
video.pause();
} catch (e) {
} catch {
// TODO:
}

Expand Down Expand Up @@ -233,7 +230,7 @@ async function loadManifest(url: string) {
duration.value = totalDuration;

loadChunk(0, 0);
} catch (e) {
} catch {
isLoading.value = false;
}
}
Expand Down Expand Up @@ -334,18 +331,18 @@ function seekGlobal(targetSeconds: number) {
loadChunk(safeIndex, offsetInChunk);
}

const handleBack = () => {
const video = videoRef.value;
if (video && !video.paused) {
video.pause();
}
if ((window as any)?.shellNavigate) {
(window as any).shellNavigate("/catalog");
} else {
window.location.href = '/catalog';
}
};
const handleBack = () => {
const video = videoRef.value;
if (video && !video.paused) {
video.pause();
}

if ((window as any)?.shellNavigate) {
(window as any).shellNavigate("/catalog");
} else {
window.location.href = '/catalog';
}
};

const handleMouseMove = () => {
showControls.value = true;
Expand Down Expand Up @@ -469,14 +466,14 @@ const handleTimeUpdate = () => {
// Usa tempo global quando há chunks
const globalCurrent = getGlobalCurrentTime();
currentTime.value = globalCurrent;

// Prefetch do próximo chunk quando está próximo do fim
const video = videoRef.value;
if (video && !isNaN(video.currentTime)) {
const remainingInChunk = (video.duration && !isNaN(video.duration))
? (video.duration - video.currentTime)
: (segmentSeconds - (video.currentTime || 0));

if (remainingInChunk < PREFETCH_THRESHOLD) {
const nextIndex = currentChunkIndex + 1;
prefetchChunk(nextIndex);
Expand Down Expand Up @@ -511,23 +508,23 @@ onMounted(() => {
video.addEventListener('timeupdate', handleTimeUpdate);
video.addEventListener('waiting', handleWaiting);
video.addEventListener('canplay', handleCanPlay);

const handleVideoPlay = () => {
isPlaying.value = true;
showDetails.value = false;
};

const handleVideoPause = () => {
isPlaying.value = false;
showDetails.value = true;
};

handleVideoPlayRef.value = handleVideoPlay;
handleVideoPauseRef.value = handleVideoPause;

video.addEventListener('play', handleVideoPlay);
video.addEventListener('pause', handleVideoPause);

// Quando um chunk termina, vai pro próximo automaticamente
const handleChunkEnded = () => {
const nextIndex = currentChunkIndex + 1;
Expand All @@ -543,8 +540,8 @@ onMounted(() => {
document.addEventListener('fullscreenchange', handleFullscreenChange);

// Carrega o manifest se fornecido
if (manifestUrl) {
loadManifest(manifestUrl);
if (manifestUrl.value) {
loadManifest(manifestUrl.value);
}
});

Expand All @@ -566,7 +563,7 @@ onUnmounted(() => {
}

document.removeEventListener('fullscreenchange', handleFullscreenChange);

if (controlsTimeoutRef.value) {
clearTimeout(controlsTimeoutRef.value);
}
Expand Down