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 /> <button @click="neko.video.play()">play stream</button><br />
</template> </template>
<table class="states" v-if="loaded"> <table class="states" v-if="loaded">
<tr><th>is connected</th><td>{{ neko.connected ? 'yes' : 'no' }}</td></tr> <tr>
<tr><th>is contolling</th><td>{{ is_controlling ? 'yes' : 'no' }}</td></tr> <th>is connected</th>
<tr><th>websocket state</th><td>{{ neko.state.websocket }}</td></tr> <td>{{ neko.connected ? 'yes' : 'no' }}</td>
<tr><th>webrtc state</th><td>{{ neko.state.webrtc }}</td></tr> </tr>
</table> <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"> <div ref="container" style="width: 1280px; height: 720px; border: 2px solid red">
<neko-canvas ref="neko" /> <neko-canvas ref="neko" />
@ -36,11 +48,12 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.states { .states {
td, th { td,
th {
border: 1px solid black; border: 1px solid black;
padding: 4px; padding: 4px;
} }
th { th {
text-align: right; text-align: right;
} }
@ -64,11 +77,11 @@
loaded: boolean = false loaded: boolean = false
get is_controlling() { get is_controlling() {
return this.neko.state.is_controlling return this.neko.state.member.is_controlling
} }
get available_screen_sizes() { get available_screen_sizes() {
return this.neko.state.available_screen_sizes return this.neko.state.screen.configurations
} }
connect() { connect() {

View File

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

View File

@ -17,6 +17,7 @@ import {
import EventEmitter from 'eventemitter3' import EventEmitter from 'eventemitter3'
import { NekoWebSocket } from './websocket' import { NekoWebSocket } from './websocket'
import NekoState from '~/types/state'
export interface NekoEvents { export interface NekoEvents {
['system.websocket']: (state: 'connected' | 'connecting' | 'disconnected') => void ['system.websocket']: (state: 'connected' | 'connecting' | 'disconnected') => void
@ -42,9 +43,12 @@ export interface NekoEvents {
} }
export class NekoMessages extends EventEmitter<NekoEvents> { export class NekoMessages extends EventEmitter<NekoEvents> {
constructor(websocket: NekoWebSocket) { state: NekoState
constructor(websocket: NekoWebSocket, state: NekoState) {
super() super()
this.state = state
websocket.on('message', async (event: string, payload: any) => { websocket.on('message', async (event: string, payload: any) => {
// @ts-ignore // @ts-ignore
if (typeof this[event] === 'function') { 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 { export interface ScreenSize {
width: number width: number
height: number height: number
rate: number rate: number
} }
export interface Scroll { /////////////////////////////
sensitivity: number // Member
invert: boolean /////////////////////////////
} export interface Member {
export default interface State {
id: string | null id: string | null
display_name: string | null name: string | null
screen_size: ScreenSize is_admin: boolean
available_screen_sizes: ScreenSize[] is_watching: boolean
scroll: Scroll
is_controlling: boolean is_controlling: boolean
websocket: 'connected' | 'connecting' | 'disconnected' can_watch: boolean
webrtc: 'connected' | 'connecting' | 'disconnected' can_control: boolean
clipboard_access: boolean
} }