update states.

This commit is contained in:
Miroslav Šedivý 2020-11-08 21:19:46 +01:00
parent a98866e5cb
commit d6c3c4b2aa
4 changed files with 215 additions and 95 deletions

View File

@ -1,48 +1,146 @@
<template>
<div>
<button @click="connect()">Connect</button>
<button @click="disconnect()">Disonnect</button>
<template v-if="loaded && neko.connected">
<button v-if="!is_controlling" @click="neko.control.request()">request control</button>
<button v-else @click="neko.control.release()">release control</button>
<button @click="neko.video.pause()">pause stream</button>
<button @click="neko.video.play()">play stream</button><br />
</template>
<table class="states" v-if="loaded">
<tr>
<th>is connected</th>
<td>{{ neko.connected ? 'yes' : 'no' }}</td>
</tr>
<tr>
<th>is contolling</th>
<td>{{ is_controlling ? 'yes' : 'no' }}</td>
</tr>
<tr>
<th>websocket state</th>
<td>{{ neko.state.connection.websocket }}</td>
</tr>
<tr>
<th>webrtc state</th>
<td>{{ neko.state.connection.webrtc }}</td>
</tr>
</table>
<div ref="container" style="width: 1280px; height: 720px; border: 2px solid red">
<neko-canvas ref="neko" />
<div style="float: right; max-width: 500px">
<h3>State</h3>
<table class="states" v-if="loaded">
<tr class="ok">
<th>connection.websocket</th>
<td>{{ neko.state.connection.websocket }}</td>
</tr>
<tr class="ok">
<th>connection.webrtc</th>
<td>{{ neko.state.connection.webrtc }}</td>
</tr>
<tr>
<th>connection.type</th>
<td>{{ neko.state.connection.type }}</td>
</tr>
<tr>
<th>connection.can_watch</th>
<td>{{ neko.state.connection.can_watch }}</td>
</tr>
<tr>
<th>connection.can_control</th>
<td>{{ neko.state.connection.can_control }}</td>
</tr>
<tr>
<th>connection.clipboard_access</th>
<td>{{ neko.state.connection.clipboard_access }}</td>
</tr>
<tr class="ok">
<th>video.playable</th>
<td>{{ neko.state.video.playable }}</td>
</tr>
<tr class="ok">
<th>video.playing</th>
<td>{{ neko.state.video.playing }}</td>
</tr>
<tr>
<th>video.volume</th>
<td>{{ neko.state.video.volume }}</td>
</tr>
<tr class="ok">
<th>control.scroll.inverse</th>
<td><input type="checkbox" v-model="neko.state.control.scroll.inverse" /></td>
</tr>
<tr class="ok">
<th>control.scroll.sensitivity</th>
<td><input type="number" v-model="neko.state.control.scroll.sensitivity" /></td>
</tr>
<tr>
<th>control.host</th>
<td>{{ neko.state.control.host }}</td>
</tr>
<tr class="ok">
<th>screen.size.width</th>
<td>{{ neko.state.screen.size.width }}</td>
</tr>
<tr class="ok">
<th>screen.size.height</th>
<td>{{ neko.state.screen.size.height }}</td>
</tr>
<tr class="ok">
<th>screen.size.rate</th>
<td>{{ neko.state.screen.size.rate }}</td>
</tr>
<tr class="ok">
<th>screen.configurations</th>
<td>
<select
:value="Object.values(neko.state.screen.size).join()"
@input="
a = String($event.target.value).split(',')
neko.screen.size(parseInt(a[0]), parseInt(a[1]), parseInt(a[2]))
"
>
<option
v-for="{ width, height, rate } in neko.state.screen.configurations"
:key="width + height + rate"
:value="[width, height, rate].join()"
>
{{ width }}x{{ height }}@{{ rate }}
</option>
</select>
</td>
</tr>
<tr>
<th>screen.is_fullscreen</th>
<td>{{ neko.state.screen.is_fullscreen }}</td>
</tr>
<tr class="ok">
<th>member.id</th>
<td>{{ neko.state.member.id }}</td>
</tr>
<tr class="ok">
<th>member.name</th>
<td>{{ neko.state.member.name }}</td>
</tr>
<tr>
<th>member.is_admin</th>
<td>{{ neko.state.member.is_admin }}</td>
</tr>
<tr>
<th>member.is_watching</th>
<td>{{ neko.state.member.is_watching }}</td>
</tr>
<tr class="ok">
<th>member.is_controlling</th>
<td>{{ neko.state.member.is_controlling }}</td>
</tr>
<tr>
<th>member.can_watch</th>
<td>{{ neko.state.member.can_watch }}</td>
</tr>
<tr>
<th>member.can_control</th>
<td>{{ neko.state.member.can_control }}</td>
</tr>
<tr>
<th>member.clipboard_access</th>
<td>{{ neko.state.member.clipboard_access }}</td>
</tr>
<tr>
<th>members</th>
<td>{{ neko.state.members }}</td>
</tr>
</table>
</div>
<div>
<button @click="connect()">Connect</button>
<button @click="disconnect()">Disonnect</button>
<template v-if="loaded">
<button
v-for="{ width, height, rate } in available_screen_sizes"
:key="width + height + rate"
@click="neko.screen.size(width, height, rate)"
>
{{ width }}x{{ height }}@{{ rate }}
</button>
</template>
<template v-if="loaded && neko.connected">
<button v-if="!is_controlling" @click="neko.control.request()">request control</button>
<button v-else @click="neko.control.release()">release control</button>
<button @click="neko.video.pause()">pause stream</button>
<button @click="neko.video.play()">play stream</button><br />
</template>
<div ref="container" style="width: 1280px; height: 720px; border: 2px solid red">
<neko-canvas ref="neko" />
</div>
</div>
</div>
</template>
@ -55,7 +153,11 @@
}
th {
text-align: right;
text-align: left;
}
.ok {
background: #97f197;
}
}
</style>
@ -80,10 +182,6 @@
return this.neko.state.member.is_controlling
}
get available_screen_sizes() {
return this.neko.state.screen.configurations
}
connect() {
this.neko.connect('ws://192.168.1.20:3000/', 'admin', 'test')
}
@ -128,11 +226,8 @@
this.neko.events.on('clipboard.update', (text) => {
console.log('clipboard.update', text)
})
this.neko.events.on('screen.configuration', (configurations) => {
console.log('screen.configuration', configurations)
})
this.neko.events.on('screen.size', (width, height, rate) => {
console.log('screen.size', width, height, rate)
this.neko.events.on('screen.size', (id) => {
console.log('screen.size', id)
})
this.neko.events.on('broadcast.status', (payload) => {
console.log('broadcast.status', payload)

View File

@ -12,7 +12,7 @@
:screenHeight="state.screen.size.height"
:isControling="state.member.is_controlling"
:scrollSensitivity="state.control.scroll.sensitivity"
:scrollInvert="state.control.scroll.invert"
:scrollInvert="state.control.scroll.inverse"
/>
</div>
</div>
@ -51,6 +51,7 @@
import { NekoWebSocket } from '~/internal/websocket'
import { NekoWebRTC } from '~/internal/webrtc'
import { NekoMessages } from '~/internal/messages'
import { register as VideoRegister } from '~/internal/video'
import NekoState from '~/types/state'
import Overlay from './overlay.vue'
@ -93,7 +94,7 @@
control: {
scroll: {
inverse: true,
sensitivity: 10,
sensitivity: 1,
},
host: null,
},
@ -125,6 +126,11 @@
return this.state.connection.websocket == 'connected' && this.state.connection.webrtc == 'connected'
}
@Watch('state.screen.size')
onScreenSizeChanged() {
this.onResize()
}
public control = {
request: () => {
this.websocket.send('control/request')
@ -174,6 +180,9 @@
Vue.set(this.state.member, 'is_controlling', id != null && id === this.state.member.id)
})
// Video
VideoRegister(this.video, this.state.video)
// WebSocket
this.websocket.on('message', async (event: string, payload: any) => {
switch (event) {
@ -185,40 +194,6 @@
this.websocket.send('signal/answer', { sdp, displayname: this.state.member.name })
} catch (e) {}
break
case 'screen/resolution':
Vue.set(this.state.screen, 'size', payload)
this.onResize()
break
case 'screen/configurations':
let data = []
for (const i of Object.keys(payload.configurations)) {
const { width, height, rates } = payload.configurations[i]
if (width >= 600 && height >= 300) {
for (const j of Object.keys(rates)) {
const rate = rates[j]
if (rate === 30 || rate === 60) {
data.push({
width,
height,
rate,
})
}
}
}
}
let conf = data.sort((a, b) => {
if (b.width === a.width && b.height == a.height) {
return b.rate - a.rate
} else if (b.width === a.width) {
return b.height - a.height
}
return b.width - a.width
})
Vue.set(this.state.screen, 'configurations', conf)
this.onResize()
break
}
})
this.websocket.on('connecting', () => {
@ -261,6 +236,8 @@
this.webrtc.on('disconnected', () => {
Vue.set(this.state.connection, 'webrtc', 'disconnected')
this.events.emit('system.webrtc', 'disconnected')
// @ts-ignore
this.video.src = null
})
}

View File

@ -1,3 +1,4 @@
import Vue from 'vue'
import { Member, ScreenConfigurations } from '../types/structs'
import { EVENT } from '../types/events'
import {
@ -31,8 +32,7 @@ export interface NekoEvents {
['control.request']: (id: string) => void
['control.requesting']: (id: string) => void
['clipboard.update']: (text: string) => void
['screen.configuration']: (configurations: ScreenConfigurations) => void
['screen.size']: (width: number, height: number, rate: number) => void
['screen.size']: (id: string) => void
['broadcast.status']: (url: string, isActive: boolean) => void
['member.ban']: (id: string, target: string) => void
['member.kick']: (id: string, target: string) => void
@ -132,15 +132,38 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
// Screen Events
/////////////////////////////
protected [EVENT.SCREEN.CONFIGURATIONS]({ configurations }: ScreenConfigurationsPayload) {
console.log('EVENT.SCREEN.CONFIGURATIONS')
this.emit('screen.configuration', configurations)
//video.setConfigurations(configurations)
let data = []
for (const i of Object.keys(configurations)) {
const { width, height, rates } = configurations[i]
if (width >= 600 && height >= 300) {
for (const j of Object.keys(rates)) {
const rate = rates[j]
if (rate === 30 || rate === 60) {
data.push({
width,
height,
rate,
})
}
}
}
}
let conf = data.sort((a, b) => {
if (b.width === a.width && b.height == a.height) {
return b.rate - a.rate
} else if (b.width === a.width) {
return b.height - a.height
}
return b.width - a.width
})
Vue.set(this.state.screen, 'configurations', conf)
}
protected [EVENT.SCREEN.RESOLUTION]({ id, width, height, rate }: ScreenResolutionPayload) {
console.log('EVENT.SCREEN.RESOLUTION')
this.emit('screen.size', width, height, rate)
//video.setResolution({ width, height, rate })
Vue.set(this.state.screen, 'size', { width, height, rate })
if (id) this.emit('screen.size', id)
}
/////////////////////////////

25
src/internal/video.ts Normal file
View File

@ -0,0 +1,25 @@
import Vue from 'vue'
import { Video } from '~/types/state'
export function register(el: HTMLVideoElement, state: Video) {
el.addEventListener('canplaythrough', () => {
Vue.set(state, 'playable', true)
})
el.addEventListener('playing', () => {
Vue.set(state, 'playing', true)
})
el.addEventListener('pause', () => {
Vue.set(state, 'playing', false)
})
el.addEventListener('emptied', () => {
Vue.set(state, 'playable', false)
Vue.set(state, 'playing', false)
})
el.addEventListener('error', () => {
Vue.set(state, 'playable', false)
Vue.set(state, 'playing', false)
})
el.addEventListener('volumechange', (value) => {
Vue.set(state, 'volume', value)
})
}