mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
update states.
This commit is contained in:
parent
a98866e5cb
commit
d6c3c4b2aa
197
src/app.vue
197
src/app.vue
@ -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)
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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
25
src/internal/video.ts
Normal 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)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user