fox/resources/views/livewire/widgets/screen-preview.blade.php

83 lines
3.4 KiB
PHP

<div x-data="screenPreview()" class="glass p-4 space-y-3">
<div class="flex items-center justify-between">
<h3 class="text-xs uppercase tracking-widest text-white/50 font-medium">Screen</h3>
@if ($analyzing)
<span class="text-[10px] text-primary flex items-center gap-1">
<span class="typing-dot"></span>
<span>analysiert</span>
</span>
@endif
</div>
<div class="aspect-video bg-black/40 border border-white/10 rounded-lg overflow-hidden relative">
<video x-ref="video" autoplay muted playsinline class="w-full h-full object-contain"
x-show="streaming"></video>
<div x-show="!streaming" class="absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/30">
<svg class="w-8 h-8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<path d="M8 21h8M12 17v4"/>
</svg>
<span class="text-[10px] uppercase tracking-widest">Inactive</span>
</div>
</div>
<div class="flex gap-2">
<button type="button" x-on:click="toggleShare()"
class="flex-1 text-xs px-3 py-1.5 rounded-lg bg-white/5 hover:bg-white/10 border border-white/10 text-white/80 transition">
<span x-show="!streaming">Screen teilen</span>
<span x-show="streaming" x-cloak>Stop</span>
</button>
<button type="button" x-on:click="snapshot()" x-bind:disabled="!streaming"
class="text-xs px-3 py-1.5 rounded-lg bg-primary/20 hover:bg-primary/30 border border-primary/40 text-primary disabled:opacity-30 disabled:hover:bg-primary/20 transition">
Snapshot
</button>
</div>
</div>
@assets
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('screenPreview', () => ({
streaming: false,
stream: null,
async toggleShare() {
if (this.streaming) {
this.stopStream();
return;
}
try {
this.stream = await navigator.mediaDevices.getDisplayMedia({
video: { frameRate: 5 },
audio: false,
});
this.$refs.video.srcObject = this.stream;
this.streaming = true;
this.stream.getVideoTracks()[0].onended = () => this.stopStream();
} catch (err) {
console.warn('Screen share denied:', err);
}
},
stopStream() {
this.stream?.getTracks().forEach(t => t.stop());
this.stream = null;
this.$refs.video.srcObject = null;
this.streaming = false;
},
snapshot() {
if (!this.streaming) return;
const video = this.$refs.video;
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
const base64 = canvas.toDataURL('image/jpeg', 0.7);
this.$wire.dispatch('screen-shot-captured', { base64 });
},
}));
});
</script>
@endassets