update state.

This commit is contained in:
Miroslav Šedivý 2020-11-08 19:38:14 +01:00
parent b4817b886a
commit a98866e5cb
4 changed files with 152 additions and 59 deletions

View File

@ -11,12 +11,24 @@
<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.websocket }}</td></tr>
<tr><th>webrtc state</th><td>{{ neko.state.webrtc }}</td></tr>
</table>
<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" />
@ -36,7 +48,8 @@
<style lang="scss" scoped>
.states {
td, th {
td,
th {
border: 1px solid black;
padding: 4px;
}
@ -64,11 +77,11 @@
loaded: boolean = false
get is_controlling() {
return this.neko.state.is_controlling
return this.neko.state.member.is_controlling
}
get available_screen_sizes() {
return this.neko.state.available_screen_sizes
return this.neko.state.screen.configurations
}
connect() {

View File

@ -3,16 +3,16 @@
<div
ref="container"
class="player-container"
v-show="state.websocket == 'connected' && state.webrtc == 'connected'"
v-show="state.connection.websocket == 'connected' && state.connection.webrtc == 'connected'"
>
<video ref="video" />
<neko-overlay
:webrtc="webrtc"
:screenWidth="state.screen_size.width"
:screenHeight="state.screen_size.height"
:isControling="state.is_controlling"
:scrollSensitivity="state.scroll.sensitivity"
:scrollInvert="state.scroll.invert"
:screenWidth="state.screen.size.width"
:screenHeight="state.screen.size.height"
:isControling="state.member.is_controlling"
:scrollSensitivity="state.control.scroll.sensitivity"
:scrollInvert="state.control.scroll.invert"
/>
</div>
</div>
@ -76,27 +76,53 @@
private webrtc = new NekoWebRTC()
private observer = new ResizeObserver(this.onResize.bind(this))
public events = new NekoMessages(this.websocket)
public state = {
id: null,
display_name: null,
screen_size: {
width: 1280,
height: 720,
rate: 30,
connection: {
websocket: 'disconnected',
webrtc: 'disconnected',
type: 'none',
can_watch: false,
can_control: false,
clipboard_access: false,
},
available_screen_sizes: [],
scroll: {
sensitivity: 10,
invert: true,
video: {
playable: false,
playing: false,
volume: 0,
},
is_controlling: false,
websocket: 'disconnected',
webrtc: 'disconnected',
control: {
scroll: {
inverse: true,
sensitivity: 10,
},
host: null,
},
screen: {
size: {
width: 1280,
height: 720,
rate: 30,
},
configurations: [],
is_fullscreen: false,
},
member: {
id: null,
name: null,
is_admin: false,
is_watching: false,
is_controlling: false,
can_watch: false,
can_control: false,
clipboard_access: false,
},
members: [],
} as NekoState
public events = new NekoMessages(this.websocket, this.state)
public get connected() {
return this.state.websocket == 'connected' && this.state.webrtc == 'connected'
return this.state.connection.websocket == 'connected' && this.state.connection.webrtc == 'connected'
}
public control = {
@ -116,10 +142,10 @@
public scroll = {
sensitivity: (sensitivity: number) => {
Vue.set(this.state.scroll, 'sensitivity', sensitivity)
Vue.set(this.state.control.scroll, 'sensitivity', sensitivity)
},
inverse: (inverse: boolean) => {
Vue.set(this.state.scroll, 'inverse', inverse)
Vue.set(this.state.control.scroll, 'inverse', inverse)
},
}
@ -128,7 +154,7 @@
throw new Error('client already connected')
}
Vue.set(this.state, 'display_name', name)
Vue.set(this.state.member, 'name', name)
this.websocket.connect(url, password)
}
@ -145,22 +171,22 @@
this.observer.observe(this._component)
this.events.on('control.host', (id: string | null) => {
Vue.set(this.state, 'is_controlling', id != null && id === this.state.id)
Vue.set(this.state.member, 'is_controlling', id != null && id === this.state.member.id)
})
// WebSocket
this.websocket.on('message', async (event: string, payload: any) => {
switch (event) {
case 'signal/provide':
Vue.set(this.state, 'id', payload.id)
Vue.set(this.state.member, 'id', payload.id)
try {
let sdp = await this.webrtc.connect(payload.sdp, payload.lite, payload.ice)
this.websocket.send('signal/answer', { sdp, displayname: this.state.display_name })
this.websocket.send('signal/answer', { sdp, displayname: this.state.member.name })
} catch (e) {}
break
case 'screen/resolution':
Vue.set(this.state, 'screen_size', payload)
Vue.set(this.state.screen, 'size', payload)
this.onResize()
break
case 'screen/configurations':
@ -190,21 +216,21 @@
return b.width - a.width
})
Vue.set(this.state, 'available_screen_sizes', conf)
Vue.set(this.state.screen, 'configurations', conf)
this.onResize()
break
}
})
this.websocket.on('connecting', () => {
Vue.set(this.state, 'websocket', 'connecting')
Vue.set(this.state.connection, 'websocket', 'connecting')
this.events.emit('system.websocket', 'connecting')
})
this.websocket.on('connected', () => {
Vue.set(this.state, 'websocket', 'connected')
Vue.set(this.state.connection, 'websocket', 'connected')
this.events.emit('system.websocket', 'connected')
})
this.websocket.on('disconnected', () => {
Vue.set(this.state, 'websocket', 'disconnected')
Vue.set(this.state.connection, 'websocket', 'disconnected')
this.events.emit('system.websocket', 'disconnected')
this.webrtc.disconnect()
})
@ -225,15 +251,15 @@
this.video.play()
})
this.webrtc.on('connecting', () => {
Vue.set(this.state, 'webrtc', 'connecting')
Vue.set(this.state.connection, 'webrtc', 'connecting')
this.events.emit('system.webrtc', 'connecting')
})
this.webrtc.on('connected', () => {
Vue.set(this.state, 'webrtc', 'connected')
Vue.set(this.state.connection, 'webrtc', 'connected')
this.events.emit('system.webrtc', 'connected')
})
this.webrtc.on('disconnected', () => {
Vue.set(this.state, 'webrtc', 'disconnected')
Vue.set(this.state.connection, 'webrtc', 'disconnected')
this.events.emit('system.webrtc', 'disconnected')
})
}
@ -247,7 +273,7 @@
private onResize() {
console.log('Resize event triggered.')
const { width, height } = this.state.screen_size
const { width, height } = this.state.screen.size
const screen_ratio = width / height
const { offsetWidth, offsetHeight } = this._component

View File

@ -17,6 +17,7 @@ import {
import EventEmitter from 'eventemitter3'
import { NekoWebSocket } from './websocket'
import NekoState from '~/types/state'
export interface NekoEvents {
['system.websocket']: (state: 'connected' | 'connecting' | 'disconnected') => void
@ -42,9 +43,12 @@ export interface NekoEvents {
}
export class NekoMessages extends EventEmitter<NekoEvents> {
constructor(websocket: NekoWebSocket) {
state: NekoState
constructor(websocket: NekoWebSocket, state: NekoState) {
super()
this.state = state
websocket.on('message', async (event: string, payload: any) => {
// @ts-ignore
if (typeof this[event] === 'function') {

View File

@ -1,21 +1,71 @@
export default interface State {
connection: Connection
video: Video
control: Control
screen: Screen
member: Member
members: Member[]
}
/////////////////////////////
// Connection
/////////////////////////////
export interface Connection {
websocket: 'disconnected' | 'connecting' | 'connected'
webrtc: 'disconnected' | 'connecting' | 'connected'
type: 'webrtc' | 'fallback' | 'none'
can_watch: boolean
can_control: boolean
clipboard_access: boolean
}
/////////////////////////////
// Video
/////////////////////////////
export interface Video {
playable: boolean
playing: boolean
volume: number
}
/////////////////////////////
// Control
/////////////////////////////
export interface Control {
scroll: Scroll
host: Member | null
}
export interface Scroll {
inverse: boolean
sensitivity: number
}
/////////////////////////////
// Screen
/////////////////////////////
export interface Screen {
size: ScreenSize
configurations: ScreenSize[]
is_fullscreen: boolean
}
export interface ScreenSize {
width: number
height: number
rate: number
}
export interface Scroll {
sensitivity: number
invert: boolean
}
export default interface State {
/////////////////////////////
// Member
/////////////////////////////
export interface Member {
id: string | null
display_name: string | null
screen_size: ScreenSize
available_screen_sizes: ScreenSize[]
scroll: Scroll
name: string | null
is_admin: boolean
is_watching: boolean
is_controlling: boolean
websocket: 'connected' | 'connecting' | 'disconnected'
webrtc: 'connected' | 'connecting' | 'disconnected'
can_watch: boolean
can_control: boolean
clipboard_access: boolean
}