Fix several minor UI issues and refactor download / seed logic
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
9053dbfbef
commit
359b01950c
10
src/App.vue
10
src/App.vue
|
@ -1,6 +1,10 @@
|
|||
<template>
|
||||
<Toast position="top-right" />
|
||||
<MenuBar :model="items" />
|
||||
<MenuBar :model="items">
|
||||
<template #end>
|
||||
<div id="menuBarEnd"></div>
|
||||
</template>
|
||||
</MenuBar>
|
||||
<div class="p-p-6">
|
||||
<router-view />
|
||||
</div>
|
||||
|
@ -30,6 +34,10 @@ export default {
|
|||
color: #2c3e50;
|
||||
}
|
||||
|
||||
#menuBarEnd button {
|
||||
width: 8em
|
||||
}
|
||||
|
||||
a:focus, video:focus {
|
||||
box-shadow: none !important;
|
||||
outline: none !important
|
||||
|
|
|
@ -3,6 +3,15 @@
|
|||
<template #title>
|
||||
Wire statistics
|
||||
</template>
|
||||
<template v-if="downloadSpeed || uploadSpeed" #subtitle>
|
||||
<template v-if="downloadSpeed">
|
||||
<i class="pi pi-arrow-down"></i> <span>{{downloadSpeed}}</span> |
|
||||
</template>
|
||||
<template v-if="uploadSpeed">
|
||||
<i class="pi pi-arrow-up"></i> <span>{{uploadSpeed}}</span>
|
||||
</template>
|
||||
<Divider />
|
||||
</template>
|
||||
<template #content>
|
||||
<DataTable :value="wireStatistics" :sortField="sortField" :sortOrder="sortOrder" :autoLayout="true">
|
||||
<Column field="id" header="Wire ID" :sortable="true" />
|
||||
|
@ -26,18 +35,24 @@ export default {
|
|||
sortOrder: {
|
||||
type: Number,
|
||||
default: -1
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
const columns = [
|
||||
{ field: 'remoteAddress', header: 'Remote address' },
|
||||
{ field: 'uploadSpeed', header: 'Upload speed' },
|
||||
{ field: 'uploaded', header: 'Uploaded' },
|
||||
{ field: 'downloadSpeed', header: 'Download speed' },
|
||||
{ field: 'downloaded', header: 'Downloaded' }
|
||||
]
|
||||
return {
|
||||
columns
|
||||
},
|
||||
downloadSpeed: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
uploadSpeed: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
{ field: 'remoteAddress', header: 'Remote address' },
|
||||
{ field: 'downloadSpeed', header: 'Download speed' },
|
||||
{ field: 'downloaded', header: 'Downloaded' },
|
||||
{ field: 'uploadSpeed', header: 'Upload speed' },
|
||||
{ field: 'uploaded', header: 'Uploaded' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
src/main.js
11
src/main.js
|
@ -12,6 +12,7 @@ import Button from 'primevue/button'
|
|||
import Card from 'primevue/card'
|
||||
import Column from 'primevue/column'
|
||||
import DataTable from 'primevue/datatable'
|
||||
import Divider from 'primevue/divider'
|
||||
import InputText from 'primevue/inputtext'
|
||||
import MenuBar from 'primevue/menubar'
|
||||
import ProgressBar from 'primevue/progressbar'
|
||||
|
@ -34,6 +35,7 @@ app.component('Button', Button)
|
|||
app.component('Card', Card)
|
||||
app.component('Column', Column)
|
||||
app.component('DataTable', DataTable)
|
||||
app.component('Divider', Divider)
|
||||
app.component('InputText', InputText)
|
||||
app.component('MenuBar', MenuBar)
|
||||
app.component('ProgressBar', ProgressBar)
|
||||
|
@ -45,9 +47,7 @@ app.component('FileSelect', FileSelect)
|
|||
app.component('WireStatistics', WireStatistics)
|
||||
|
||||
app.provide('trackers', [
|
||||
'wss://tracker.btorrent.xyz',
|
||||
'wss://tracker.openwebtorrent.com',
|
||||
'wss://tracker.fastcast.nz',
|
||||
'wss://tracker.sloppyta.co:443/announce',
|
||||
'wss://tracker.files.fm:7073/announce',
|
||||
'wss://open.tube:443/tracker/socket',
|
||||
|
@ -63,15 +63,12 @@ app.provide('rtcConfig', {
|
|||
iceServers: [
|
||||
{
|
||||
urls: [
|
||||
'stun:stun.l.google.com:19302',
|
||||
'stun:global.stun.twilio.com:3478'
|
||||
'stun:stun.l.google.com:19302'
|
||||
]
|
||||
},
|
||||
{
|
||||
urls: [
|
||||
'turn:relay.instant.io:443?transport=udp',
|
||||
'turn:relay.instant.io:443?transport=tcp',
|
||||
'turns:relay.instant.io:443?transport=tcp'
|
||||
'turn:relay.instant.io:443?transport=udp'
|
||||
],
|
||||
username: 'relay.instant.io',
|
||||
credential: 'nepal-cheddar-baize-oleander'
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<template>
|
||||
<h1>Host</h1>
|
||||
<FileSelect v-if="!video.file" message="Drag a H.264 encoded MP4 here to start a screen." :disabled="!!video.file" @selected="onFilesSelected" />
|
||||
<Card v-else-if="!state.active">
|
||||
<FileSelect v-if="!video" message="Drag a H.264 encoded MP4 here to start a screen." :disabled="!!video" @selected="onFilesSelected" />
|
||||
<Card v-show="video">
|
||||
<template #content>
|
||||
<video ref="player" controls="true"></video>
|
||||
</template>
|
||||
</Card>
|
||||
<Card v-if="video && !active">
|
||||
<template #content>
|
||||
<div class="p-text-center">
|
||||
<ProgressSpinner />
|
||||
|
@ -9,140 +14,176 @@
|
|||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<div v-show="state.active && !!video.file">
|
||||
<Card>
|
||||
<template #content>
|
||||
<video ref="player"></video>
|
||||
</template>
|
||||
</Card>
|
||||
<div v-if="video && active">
|
||||
<Card>
|
||||
<template #title>
|
||||
Properties
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="p-grid">
|
||||
<div class="p-col-12 p-md-4">
|
||||
<div class="p-col-12 p-md-3">
|
||||
<h5>Filename</h5>
|
||||
<span>{{video.name}}</span>
|
||||
<span>{{stats.name}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Duration</h5>
|
||||
<span>{{video.hDuration}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<div class="p-col-12 p-md-3">
|
||||
<h5>File size</h5>
|
||||
<span>{{video.hSize}}</span>
|
||||
<span>{{stats.size}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-3">
|
||||
<h5>Uploaded</h5>
|
||||
<span>{{stats.uploaded}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-3">
|
||||
<h5>Duration</h5>
|
||||
<span>{{stats.duration}}</span>
|
||||
</div>
|
||||
<div class="p-col-12">
|
||||
<h5>ID</h5>
|
||||
<div class="p-fluid">
|
||||
<InputText class="p-inputtext-sm" :value="state.infoHash" disabled />
|
||||
<InputText class="p-inputtext-sm" :value="stats.infoHash" disabled />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<WireStatistics :wireStatistics="wireStatistics" sortField="uploaded" />
|
||||
<WireStatistics :downloadSpeed="stats.downloadSpeed" :uploadSpeed="stats.uploadSpeed" :wireStatistics="wireStatistics" sortField="uploaded" />
|
||||
<teleport to="#menuBarEnd">
|
||||
<Button class="p-button-secondary" label="Share" icon="pi pi-share-alt" @click="onButtonClick" />
|
||||
</teleport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { inject, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { computed, inject, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { useToast } from 'primevue/usetoast'
|
||||
import WebTorrent from 'webtorrent/webtorrent.min.js'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import prettyMilliseconds from 'pretty-ms'
|
||||
import WebTorrent from 'webtorrent/webtorrent.min.js'
|
||||
import updateWireStatistics from '@/helpers/wire-statistics'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
columns: [
|
||||
{ field: 'remoteAddress', header: 'Remote address' },
|
||||
{ field: 'uploadSpeed', header: 'Upload speed' },
|
||||
{ field: 'uploaded', header: 'Uploaded' }
|
||||
]
|
||||
},
|
||||
setup () {
|
||||
const toast = useToast()
|
||||
const trackers = inject('trackers')
|
||||
const rtcConfig = inject('rtcConfig')
|
||||
|
||||
// State variables.
|
||||
var webTorrent = null
|
||||
var wireUpdateHandle = null
|
||||
const active = ref(false)
|
||||
const player = ref(null)
|
||||
const video = reactive({
|
||||
file: null,
|
||||
name: '',
|
||||
const video = ref(null)
|
||||
const wireStatistics = reactive([])
|
||||
const state = reactive({
|
||||
torrent: null,
|
||||
uploaded: 0,
|
||||
uploadSpeed: 0,
|
||||
size: 0,
|
||||
duration: 0,
|
||||
hSize: '',
|
||||
hDuration: ''
|
||||
wires: computed(() => state.torrent?.wires ?? [])
|
||||
})
|
||||
const state = reactive({
|
||||
active: false,
|
||||
torrent: null,
|
||||
infoHash: '',
|
||||
uploaded: 0,
|
||||
wires: []
|
||||
const stats = reactive({
|
||||
infoHash: computed(() => state.torrent?.infoHash ?? 'Unknown'),
|
||||
uploaded: computed(() => prettyBytes(state.uploaded ?? 0)),
|
||||
uploadSpeed: computed(() => prettyBytes(state.uploadSpeed ?? 0) + 'ps'),
|
||||
name: computed(() => video.value?.name ?? 'Unknown'),
|
||||
size: computed(() => prettyBytes(state.torrent?.length ?? 0)),
|
||||
duration: computed(() => prettyMilliseconds(state.duration ?? 0))
|
||||
})
|
||||
const wireStatistics = reactive([])
|
||||
|
||||
// Events.
|
||||
const statsHandle = setInterval(() => {
|
||||
if (state.torrent) {
|
||||
state.downloaded = state.torrent?.downloaded
|
||||
state.uploaded = state.torrent?.uploaded
|
||||
state.downloadSpeed = state.torrent?.downloadSpeed
|
||||
state.uploadSpeed = state.torrent?.uploadSpeed
|
||||
updateWireStatistics(state.wires, wireStatistics)
|
||||
}
|
||||
}, 500)
|
||||
|
||||
onMounted(() => {
|
||||
webTorrent = new WebTorrent({ tracker: { rtcConfig: rtcConfig } })
|
||||
webTorrent.on('error', () => {})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (webTorrent) {
|
||||
webTorrent.destroy()
|
||||
}
|
||||
if (wireUpdateHandle) {
|
||||
clearInterval(wireUpdateHandle)
|
||||
if (statsHandle) {
|
||||
clearInterval(statsHandle)
|
||||
}
|
||||
})
|
||||
|
||||
const onFilesSelected = (f) => {
|
||||
if (f?.length !== 1 || !f[0].name.endsWith('.mp4') || f[0].type !== 'video/mp4') {
|
||||
toast.add({ severity: 'error', summary: 'Bad file input', detail: 'You must select a single H.264 encoded MP4.', life: 3000 })
|
||||
if (f?.length !== 1 ||
|
||||
!f[0].name.endsWith('.mp4') ||
|
||||
f[0].type !== 'video/mp4') {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Bad file input',
|
||||
detail: 'You must select a single H.264 encoded MP4.',
|
||||
life: 3000
|
||||
})
|
||||
} else {
|
||||
// Load video in DOM.
|
||||
player.value.src = URL.createObjectURL(f[0])
|
||||
|
||||
// Load video information such that it can be rendered.
|
||||
video.file = f[0]
|
||||
video.name = f[0].name
|
||||
video.size = f[0].size
|
||||
video.hSize = prettyBytes(f[0].size)
|
||||
player.value.addEventListener('loadedmetadata', (e) => {
|
||||
video.duration = e.target.duration
|
||||
video.hDuration = prettyMilliseconds(e.target.duration * 1000)
|
||||
video.value = f[0]
|
||||
state.duration = (e.target?.duration ?? 0) * 1000
|
||||
})
|
||||
|
||||
// Seed the video.
|
||||
seedVideo(f[0])
|
||||
seedFile(f[0])
|
||||
}
|
||||
}
|
||||
|
||||
const seedVideo = (video) => {
|
||||
webTorrent.seed(video, { announce: trackers }, torrent => {
|
||||
state.active = true
|
||||
state.infoHash = torrent.infoHash
|
||||
state.wires = torrent.wires
|
||||
|
||||
torrent.on('upload', bytes => {
|
||||
state.uploaded += bytes
|
||||
})
|
||||
const onButtonClick = () => {
|
||||
alert('Not implemented yet!')
|
||||
}
|
||||
|
||||
// Utility functions.
|
||||
const seedFile = (file) => {
|
||||
webTorrent.seed(file, { announce: trackers }, torrent => {
|
||||
torrent.on('error', () => {})
|
||||
torrent.on('warning', () => {})
|
||||
torrent.on('wire', wire => {
|
||||
toast.add({ severity: 'info', summary: 'New watcher', detail: 'Someone has joined your screen.', life: 3000 })
|
||||
toast.add({
|
||||
severity: 'info',
|
||||
summary: 'New watcher',
|
||||
detail: 'Someone has joined your screen.',
|
||||
life: 3000
|
||||
})
|
||||
})
|
||||
|
||||
wireUpdateHandle = setInterval(() => {
|
||||
updateWireStatistics(state.wires, wireStatistics)
|
||||
window.w = wireStatistics
|
||||
wireStatistics.set()
|
||||
}, 250)
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: 'Video added',
|
||||
detail: `You are now sharing ${file.name}`,
|
||||
life: 5000
|
||||
})
|
||||
|
||||
toast.add({ severity: 'success', summary: 'Video added', detail: `You are now sharing ${video.name}`, life: 5000 })
|
||||
state.torrent = torrent
|
||||
active.value = true
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
onFilesSelected,
|
||||
onButtonClick,
|
||||
active,
|
||||
player,
|
||||
video,
|
||||
state,
|
||||
stats,
|
||||
wireStatistics
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
<template>
|
||||
<h1>Watch</h1>
|
||||
<Card class="p-text-center" v-if="!state.active">
|
||||
<Card v-show="active">
|
||||
<template #content>
|
||||
<video ref="player" controls="true"></video>
|
||||
</template>
|
||||
</Card>
|
||||
<Card class="p-text-center" v-if="!active">
|
||||
<template #content>
|
||||
<ProgressSpinner />
|
||||
<h2>Waiting for connections. Please wait...</h2>
|
||||
</template>
|
||||
</Card>
|
||||
<div v-show="state.active">
|
||||
<Card >
|
||||
<template #content>
|
||||
<ProgressBar class="p-mb-2" :value="progress" :showValue="false" />
|
||||
<video ref="player"></video>
|
||||
</template>
|
||||
</Card>
|
||||
<div v-else>
|
||||
<Card>
|
||||
<template #title>
|
||||
Properties
|
||||
|
@ -21,31 +20,51 @@
|
|||
<div class="p-grid">
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Filename</h5>
|
||||
<span>{{video.name}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Duration</h5>
|
||||
<span>{{video.hDuration}}</span>
|
||||
<span>{{stats.name}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>File size</h5>
|
||||
<span>{{video.hSize}}</span>
|
||||
<span>{{stats.size}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Duration</h5>
|
||||
<span>{{stats.duration}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Downloaded</h5>
|
||||
<span>{{stats.downloaded}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Uploaded</h5>
|
||||
<span>{{stats.uploaded}}</span>
|
||||
</div>
|
||||
<div class="p-col-12 p-md-4">
|
||||
<h5>Ratio</h5>
|
||||
<span>{{stats.ratio}}</span>
|
||||
</div>
|
||||
<div class="p-col-12">
|
||||
<h5>ID</h5>
|
||||
<div class="p-fluid">
|
||||
<InputText class="p-inputtext-sm" :value="state.infoHash" disabled />
|
||||
<InputText class="p-inputtext-sm" :value="stats.infoHash" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-col-12">
|
||||
<h5>Progress</h5>
|
||||
<ProgressBar class="p-mb-2" :value="stats.progress" :showValue="false" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
<WireStatistics :wireStatistics="wireStatistics" sortField="downloaded" />
|
||||
<WireStatistics :downloadSpeed="stats.downloadSpeed" :uploadSpeed="stats.uploadSpeed" :wireStatistics="wireStatistics" sortField="downloaded" />
|
||||
<teleport to="#menuBarEnd">
|
||||
<Button class="p-button-secondary" label="Share" icon="pi pi-share-alt" @click="onButtonClick" />
|
||||
<Button class="p-button-secondary p-ml-2" label="Download" icon="pi pi-download" @click="onButtonClick" />
|
||||
</teleport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { inject, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { computed, inject, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useToast } from 'primevue/usetoast'
|
||||
import WebTorrent from 'webtorrent/webtorrent.min.js'
|
||||
|
@ -65,36 +84,62 @@ export default {
|
|||
const toast = useToast()
|
||||
const trackers = inject('trackers')
|
||||
const rtcConfig = inject('rtcConfig')
|
||||
|
||||
// State variables.
|
||||
var webTorrent = null
|
||||
var wireUpdateHandle = null
|
||||
const active = ref(false)
|
||||
const player = ref(null)
|
||||
const progress = ref()
|
||||
const video = reactive({
|
||||
file: null,
|
||||
name: '',
|
||||
const video = ref(null)
|
||||
const wireStatistics = reactive([])
|
||||
const state = reactive({
|
||||
torrent: null,
|
||||
downloaded: 0,
|
||||
uploaded: 0,
|
||||
downloadSpeed: 0,
|
||||
uploadSpeed: 0,
|
||||
size: 0,
|
||||
duration: 0,
|
||||
hSize: '',
|
||||
hDuration: ''
|
||||
wires: computed(() => state.torrent?.wires ?? [])
|
||||
})
|
||||
const state = reactive({
|
||||
active: false,
|
||||
torrent: null,
|
||||
infoHash: '',
|
||||
downloaded: 0,
|
||||
wires: []
|
||||
const stats = reactive({
|
||||
infoHash: computed(() => state.torrent?.infoHash ?? 'Unknown'),
|
||||
downloaded: computed(() => prettyBytes(state.downloaded ?? 0)),
|
||||
uploaded: computed(() => prettyBytes(state.uploaded ?? 0)),
|
||||
downloadSpeed: computed(() => prettyBytes(state.downloadSpeed ?? 0) + 'ps'),
|
||||
uploadSpeed: computed(() => prettyBytes(state.uploadSpeed ?? 0) + 'ps'),
|
||||
ratio: computed(() => (state.uploaded / state.downloaded ?? 0).toFixed(2)),
|
||||
progress: computed(() => (state.downloaded / video.value?.length ?? 0) * 100),
|
||||
name: computed(() => video.value?.name ?? 'Unknown'),
|
||||
size: computed(() => prettyBytes(state.torrent?.length ?? 0)),
|
||||
duration: computed(() => prettyMilliseconds(state.duration ?? 0))
|
||||
})
|
||||
const wireStatistics = reactive([])
|
||||
|
||||
// Events.
|
||||
const statsHandle = setInterval(() => {
|
||||
if (state.torrent) {
|
||||
state.downloaded = state.torrent?.downloaded
|
||||
state.uploaded = state.torrent?.uploaded
|
||||
state.downloadSpeed = state.torrent?.downloadSpeed
|
||||
state.uploadSpeed = state.torrent?.uploadSpeed
|
||||
updateWireStatistics(state.wires, wireStatistics)
|
||||
}
|
||||
}, 500)
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!/^([a-f0-9]{40})$/.test(props.id)) {
|
||||
toast.add({ severity: 'error', summary: 'Bad ID', detail: 'Please enter a valid ID.', life: 3000 })
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Bad ID',
|
||||
detail: 'Please enter a valid ID.',
|
||||
life: 3000
|
||||
})
|
||||
router.push('/join')
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
webTorrent = new WebTorrent({ tracker: { rtcConfig: rtcConfig } })
|
||||
webTorrent.on('error', () => {})
|
||||
downloadVideo(props.id)
|
||||
})
|
||||
|
||||
|
@ -102,66 +147,58 @@ export default {
|
|||
if (webTorrent) {
|
||||
webTorrent.destroy()
|
||||
}
|
||||
if (wireUpdateHandle) {
|
||||
clearInterval(wireUpdateHandle)
|
||||
if (statsHandle) {
|
||||
clearInterval(statsHandle)
|
||||
}
|
||||
})
|
||||
|
||||
const downloadVideo = (infoHash) => {
|
||||
webTorrent.add(infoHash, { announce: trackers }, torrent => {
|
||||
torrent.on('wire', () => {
|
||||
toast.add({ severity: 'info', summary: 'New watcher', detail: 'Someone has joined your screen.', life: 3000 })
|
||||
})
|
||||
|
||||
torrent.on('noPeers', () => {
|
||||
toast.add({ severity: 'warning', summary: 'No peers', detail: 'No one is sharing this video at the moment.', life: 3000 })
|
||||
})
|
||||
|
||||
torrent.on('upload', bytes => {
|
||||
})
|
||||
|
||||
torrent.on('download', bytes => {
|
||||
if (!state.active) {
|
||||
state.active = true
|
||||
initialise(torrent)
|
||||
}
|
||||
state.downloaded += bytes
|
||||
progress.value = state.downloaded / video.size * 100
|
||||
})
|
||||
})
|
||||
const onButtonClick = () => {
|
||||
alert('Not implemented yet!')
|
||||
}
|
||||
|
||||
const initialise = (torrent) => {
|
||||
state.torrent = torrent
|
||||
state.infoHash = torrent.infoHash
|
||||
state.wires = torrent.wires
|
||||
// Utility functions.
|
||||
const downloadVideo = (infoHash) => {
|
||||
webTorrent.add(infoHash, { announce: trackers }, torrent => {
|
||||
torrent.on('error', () => {})
|
||||
torrent.on('warning', () => {})
|
||||
torrent.on('wire', () => {
|
||||
toast.add({
|
||||
severity: 'info',
|
||||
summary: 'New watcher',
|
||||
detail: 'Someone has joined your screen.',
|
||||
life: 3000
|
||||
})
|
||||
})
|
||||
torrent.on('noPeers', () => {
|
||||
toast.add({
|
||||
severity: 'warning',
|
||||
summary: 'No peers',
|
||||
detail: 'No one is sharing this video at the moment.',
|
||||
life: 3000
|
||||
})
|
||||
})
|
||||
|
||||
var file = torrent.files.find(file => {
|
||||
return file.name.endsWith('.mp4')
|
||||
var file = torrent.files.find(file => {
|
||||
return file.name.endsWith('.mp4')
|
||||
})
|
||||
|
||||
player.value.addEventListener('loadedmetadata', (e) => {
|
||||
video.value = file
|
||||
state.duration = (e.target?.duration ?? 0) * 1000
|
||||
})
|
||||
|
||||
file.renderTo(player.value)
|
||||
|
||||
state.torrent = torrent
|
||||
active.value = true
|
||||
})
|
||||
|
||||
video.file = file
|
||||
video.name = file.name
|
||||
video.size = file.length
|
||||
video.hSize = prettyBytes(file.length)
|
||||
player.value.addEventListener('loadedmetadata', (e) => {
|
||||
video.duration = e.target.duration
|
||||
video.hDuration = prettyMilliseconds(e.target.duration * 1000)
|
||||
})
|
||||
|
||||
file.renderTo(player.value)
|
||||
|
||||
wireUpdateHandle = setInterval(() => {
|
||||
window.w = wireStatistics
|
||||
updateWireStatistics(state.wires, wireStatistics)
|
||||
}, 250)
|
||||
}
|
||||
|
||||
return {
|
||||
onButtonClick,
|
||||
active,
|
||||
player,
|
||||
video,
|
||||
state,
|
||||
progress,
|
||||
stats,
|
||||
wireStatistics
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue