neko/src/page/components/events.vue

691 lines
22 KiB
Vue
Raw Normal View History

2022-07-16 21:30:35 +02:00
<template>
<div class="tab-states">
<table class="states">
<tr>
<th style="width: 50%">authenticated</th>
<td :style="!neko.state.authenticated ? 'background: red;' : ''">{{ neko.state.authenticated }}</td>
</tr>
<tr>
<th>connection.url</th>
<td style="word-break: break-all">{{ neko.state.connection.url }}</td>
</tr>
<tr>
<th>connection.token</th>
<td>{{ neko.state.connection.token ? 'yes' : 'no' }}</td>
</tr>
<tr>
<th>connection.status</th>
<td
:style="
neko.state.connection.status == 'disconnected'
? 'background: red;'
: neko.state.connection.status == 'connecting'
? 'background: #17448a;'
: ''
"
>
{{ neko.state.connection.status }}
</td>
</tr>
<tr>
<th title="connection.websocket.connected">connection.websocket.con...</th>
<td>{{ neko.state.connection.websocket.connected }}</td>
</tr>
<tr>
<th>connection.websocket.config</th>
<td>
<details>
<summary>Show</summary>
<table class="states">
<tr>
<th style="width: 40%">max_reconnects</th>
<td>
{{ neko.state.connection.websocket.config.max_reconnects }}
</td>
</tr>
<tr>
<th style="width: 40%">timeout_ms</th>
<td>
{{ neko.state.connection.websocket.config.timeout_ms }}
</td>
</tr>
<tr>
<th style="width: 40%">backoff_ms</th>
<td>
{{ neko.state.connection.websocket.config.backoff_ms }}
</td>
</tr>
</table>
</details>
</td>
</tr>
<tr>
<th title="connection.webrtc.connected">connection.webrtc.connect...</th>
<td>{{ neko.state.connection.webrtc.connected }}</td>
</tr>
<tr>
<th>connection.webrtc.stable</th>
<td>{{ neko.state.connection.webrtc.stable }}</td>
</tr>
<tr>
<th>connection.webrtc.config</th>
<td>
<details>
<summary>Show</summary>
<table class="states">
<tr>
<th style="width: 40%">max_reconnects</th>
<td>
{{ neko.state.connection.webrtc.config.max_reconnects }}
</td>
</tr>
<tr>
<th style="width: 40%">timeout_ms</th>
<td>
{{ neko.state.connection.webrtc.config.timeout_ms }}
</td>
</tr>
<tr>
<th style="width: 40%">backoff_ms</th>
<td>
{{ neko.state.connection.webrtc.config.backoff_ms }}
</td>
</tr>
</table>
</details>
</td>
</tr>
<tr>
<th>connection.webrtc.stats</th>
<td>
<table class="states" v-if="neko.state.connection.webrtc.stats != null">
<tr>
<th style="width: 40%">muted</th>
<td :style="neko.state.connection.webrtc.stats.muted ? 'background: red' : ''">
{{ neko.state.connection.webrtc.stats.muted }}
</td>
</tr>
<tr>
<th style="width: 40%">bitrate</th>
<td>{{ Math.floor(neko.state.connection.webrtc.stats.bitrate / 1024 / 8) }} KB/s</td>
</tr>
<tr>
<th style="width: 40%">latency</th>
<td
:title="
'request: ' +
neko.state.connection.webrtc.stats.requestLatency +
'ms, response: ' +
neko.state.connection.webrtc.stats.responseLatency +
'ms'
"
>
{{ neko.state.connection.webrtc.stats.latency }}ms
</td>
</tr>
2022-07-16 21:30:35 +02:00
<tr>
<th>loss</th>
<td :style="neko.state.connection.webrtc.stats.packetLoss >= 1 ? 'background: red' : ''">
{{ Math.floor(neko.state.connection.webrtc.stats.packetLoss) }}%
</td>
</tr>
<tr>
<td
colspan="2"
style="background: green; text-align: center"
v-if="neko.state.connection.webrtc.stats.paused"
>
webrtc is paused
</td>
<td
colspan="2"
style="background: darkviolet; text-align: center"
v-else-if="neko.state.connection.webrtc.video.disabled"
>
video is disabled
</td>
2022-07-16 21:30:35 +02:00
<td
colspan="2"
style="background: red; text-align: center"
v-else-if="!neko.state.connection.webrtc.stats.fps"
>
frame rate is zero
</td>
<td colspan="2" v-else>
{{
neko.state.connection.webrtc.stats.width +
'x' +
neko.state.connection.webrtc.stats.height +
'@' +
Math.floor(neko.state.connection.webrtc.stats.fps * 100) / 100
}}
</td>
</tr>
</table>
</td>
</tr>
<tr>
<th title="connection.webrtc.video.disabled">connection.webrtc.video.disab..</th>
<td>
<div class="space-between">
<span>{{ neko.state.connection.webrtc.video.disabled }}</span>
<button @click="neko.setWebRTCVideo({ disabled: !neko.state.connection.webrtc.video.disabled })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
<tr>
<th>connection.webrtc.video.id</th>
<td>{{ neko.state.connection.webrtc.video.id }}</td>
</tr>
<tr>
<th>connection.webrtc.video.auto</th>
<td>
<div class="space-between">
<span>{{ neko.state.connection.webrtc.video.auto }}</span>
<button @click="neko.setWebRTCVideo({ auto: !neko.state.connection.webrtc.video.auto })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
2022-07-16 21:30:35 +02:00
</tr>
<tr>
<th title="connection.webrtc.audio.disabled">connection.webrtc.audio.disab..</th>
<td>
<div class="space-between">
<span>{{ neko.state.connection.webrtc.audio.disabled }}</span>
<button @click="neko.setWebRTCAudio({ disabled: !neko.state.connection.webrtc.audio.disabled })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
2022-07-16 21:30:35 +02:00
<tr>
<th rowspan="2">connection.webrtc.videos</th>
<td>Total {{ neko.state.connection.webrtc.videos.length }} videos.</td>
</tr>
<tr>
<td>
<select
:value="neko.state.connection.webrtc.video.id"
@input="neko.setWebRTCVideo({ selector: { id: $event.target.value } })"
>
2022-07-16 21:30:35 +02:00
<option v-for="video in neko.state.connection.webrtc.videos" :key="video" :value="video">
{{ video }}
</option>
</select>
</td>
</tr>
<tr>
<th>connection.screencast</th>
<td>{{ neko.state.connection.screencast }}</td>
</tr>
<tr>
<th>connection.type</th>
<td :style="neko.state.connection.type == 'fallback' ? 'background: #17448a;' : ''">
{{ neko.state.connection.type }}
</td>
</tr>
<tr>
<th>video.playable</th>
<td>{{ neko.state.video.playable }}</td>
</tr>
<tr>
<th rowspan="2">video.playing</th>
<td>{{ neko.state.video.playing }}</td>
</tr>
<tr>
<td>
<button v-if="!neko.state.video.playing" @click="neko.play()">play</button>
<button v-else @click="neko.pause()">pause</button>
</td>
</tr>
<tr>
<th rowspan="2">video.volume</th>
<td>{{ neko.state.video.volume }}</td>
</tr>
<tr>
<td>
<input
type="range"
min="0"
max="1"
:value="neko.state.video.volume"
@input="neko.setVolume(Number($event.target.value))"
step="0.01"
/>
</td>
</tr>
<tr>
<th rowspan="2">video.muted</th>
<td>{{ neko.state.video.muted }}</td>
</tr>
<tr>
<td>
<button v-if="!neko.state.video.muted" @click="neko.mute()">mute</button>
<button v-else @click="neko.unmute()">unmute</button>
</td>
</tr>
<tr>
<th>control.scroll.inverse</th>
<td>
<div class="space-between">
<span>{{ neko.state.control.scroll.inverse }}</span>
<button @click="neko.setScrollInverse(!neko.state.control.scroll.inverse)">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
<tr>
<th rowspan="2">control.scroll.sensitivity</th>
<td>{{ neko.state.control.scroll.sensitivity }}</td>
</tr>
<tr>
<td>
<input
type="range"
min="-5"
max="5"
:value="neko.state.control.scroll.sensitivity"
@input="neko.setScrollSensitivity(Number($event.target.value))"
step="1"
/>
</td>
</tr>
<tr>
<th>control.clipboard</th>
<td>
<textarea
:readonly="!neko.controlling"
:value="neko.state.control.clipboard ? neko.state.control.clipboard.text : ''"
@input="clipboardText = $event.target.value"
></textarea>
<button :disabled="!neko.controlling" @click="neko.room.clipboardSetText({ text: clipboardText })">
send clipboard
</button>
</td>
</tr>
<tr>
<th rowspan="2">control.keyboard</th>
<td>
{{
neko.state.control.keyboard.layout +
(neko.state.control.keyboard.variant ? ' (' + neko.state.control.keyboard.variant + ')' : '')
}}
</td>
</tr>
<tr>
<td>
<input
type="text"
placeholder="Layout"
:value="neko.state.control.keyboard.layout"
@input="neko.setKeyboard($event.target.value, neko.state.control.keyboard.variant)"
style="width: 50%; box-sizing: border-box"
/>
<input
type="text"
placeholder="Variant"
:value="neko.state.control.keyboard.variant"
@input="neko.setKeyboard(neko.state.control.keyboard.layout, $event.target.value)"
style="width: 50%; box-sizing: border-box"
/>
</td>
</tr>
<tr>
<th>control.touch.enabled</th>
<td>
<div class="space-between">
<span>{{ neko.state.control.touch.enabled }}</span>
<button @click="neko.setTouchEnabled(!neko.state.control.touch.enabled)">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
<tr>
<th>control.touch.supported</th>
<td>{{ neko.state.control.touch.supported }}</td>
</tr>
2022-07-16 21:30:35 +02:00
<tr>
<th rowspan="2">control.host_id</th>
<td>{{ neko.state.control.host_id }}</td>
</tr>
<tr>
<td>
<button v-if="!neko.controlling" @click="neko.room.controlRequest()">request control</button>
<button v-else @click="neko.room.controlRelease()">release control</button>
</td>
</tr>
<tr>
<th>screen.size</th>
<td>
{{ neko.state.screen.size.width }}x{{ neko.state.screen.size.height }}@{{ neko.state.screen.size.rate }}
</td>
</tr>
<template v-if="neko.is_admin">
<tr>
<th rowspan="2">screen.configurations</th>
<td>Total {{ neko.state.screen.configurations.length }} configurations.</td>
</tr>
<tr>
<td>
<input
list="screen-configuration"
v-model="screenConfiguration"
style="width: 100%; box-sizing: border-box"
/>
<datalist id="screen-configuration">
2022-07-16 21:30:35 +02:00
<option
v-for="{ width, height, rate } in neko.state.screen.configurations"
:key="String(width) + 'x' + String(height) + '@' + String(rate)"
:value="String(width) + 'x' + String(height) + '@' + String(rate)"
/>
</datalist>
<button @click="setScreenConfiguration">set</button>
</td>
</tr>
<tr>
<th class="middle">screen.sync.enabled</th>
<td>
<div class="space-between">
<span>{{ neko.state.screen.sync.enabled }}</span>
<button @click="neko.state.screen.sync.enabled = !neko.state.screen.sync.enabled">
<i class="fas fa-toggle-on"></i>
</button>
</div>
2022-07-16 21:30:35 +02:00
</td>
</tr>
<tr>
<th rowspan="2">screen.sync.multiplier</th>
<td>{{ neko.state.screen.sync.multiplier || 'use device pixel ratio' }}</td>
</tr>
<tr>
<td>
<input
type="range"
min="0"
max="10"
:value="neko.state.screen.sync.multiplier"
@input="neko.state.screen.sync.multiplier = Number($event.target.value)"
step="0.1"
/>
</td>
</tr>
<tr>
<th rowspan="2">screen.sync.rate</th>
<td>{{ neko.state.screen.sync.rate }}</td>
</tr>
<tr>
<td>
<input
type="range"
min="5"
max="60"
:value="neko.state.screen.sync.rate"
@input="neko.state.screen.sync.rate = Number($event.target.value)"
step="5"
/>
</td>
</tr>
2022-07-16 21:30:35 +02:00
</template>
<template v-else>
<tr>
<th>screen.configurations</th>
<td rowspan="2" style="vertical-align: middle">Session is not admin.</td>
</tr>
<tr>
<th>screen.sync</th>
</tr>
</template>
2022-07-16 21:30:35 +02:00
<tr>
<th>session_id</th>
<td>{{ neko.state.session_id }}</td>
</tr>
<tr>
<th>sessions</th>
<td>Total {{ Object.values(neko.state.sessions).length }} sessions.</td>
</tr>
<tr>
<th class="middle">settings.private_mode</th>
<td>
<div class="space-between">
<span>{{ neko.state.settings.private_mode }}</span>
<button @click="updateSettings({ private_mode: !neko.state.settings.private_mode })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
2023-05-14 22:51:45 +02:00
<tr>
<th class="middle">settings.locked_controls</th>
<td>
<div class="space-between">
<span>{{ neko.state.settings.locked_controls }}</span>
<button @click="updateSettings({ locked_controls: !neko.state.settings.locked_controls })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
2022-07-16 21:30:35 +02:00
<tr>
<th class="middle">settings.implicit_hosting</th>
<td>
<div class="space-between">
<span>{{ neko.state.settings.implicit_hosting }}</span>
<button @click="updateSettings({ implicit_hosting: !neko.state.settings.implicit_hosting })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
<tr>
<th class="middle">settings.inactive_cursors</th>
<td>
<div class="space-between">
<span>{{ neko.state.settings.inactive_cursors }}</span>
<button @click="updateSettings({ inactive_cursors: !neko.state.settings.inactive_cursors })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
<tr>
<th class="middle">settings.merciful_reconnect</th>
<td>
<div class="space-between">
<span>{{ neko.state.settings.merciful_reconnect }}</span>
<button @click="updateSettings({ merciful_reconnect: !neko.state.settings.merciful_reconnect })">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
<tr>
<th>cursors</th>
<td>{{ neko.state.cursors }}</td>
</tr>
<tr>
<th>mobile_keyboard_open</th>
<td>
<div class="space-between">
<span>{{ neko.state.mobile_keyboard_open }}</span>
<button @click="neko.mobileKeyboardToggle">
<i class="fas fa-toggle-on"></i>
</button>
</div>
</td>
</tr>
2022-07-16 21:30:35 +02:00
<tr>
<th>control actions</th>
<td>
<button title="cut" @click="neko.control.cut()"><i class="fas fa-cut" /></button>
<button title="copy" @click="neko.control.copy()"><i class="fas fa-copy" /></button>
<button title="paste" @click="neko.control.paste()"><i class="fas fa-paste" /></button>
<button title="select all" @click="neko.control.selectAll()"><i class="fas fa-i-cursor" /></button>
</td>
</tr>
<tr>
<th>control keypress</th>
<td style="text-align: center">
<button style="width: 20px" v-for="l in letters" :key="l" @click="neko.control.keyPress(l)">
{{ String.fromCharCode(l) }}
</button>
<div style="display: flex">
<button title="shift" @click="shift = !shift">
<i v-if="shift" class="fas fa-caret-square-up" />
<i v-else class="far fa-caret-square-up" />
</button>
<button style="width: 100%" @click="neko.control.keyPress(' '.charCodeAt(0))">space</button>
<button title="shift" @click="shift = !shift">
<i v-if="shift" class="fas fa-caret-square-up" />
<i v-else class="far fa-caret-square-up" />
</button>
</div>
</td>
</tr>
<tr>
<th>chaos monkey</th>
<td>
<button @click="cursorMovingToggle">cursor moving</button>
<button @click="screenChangingToggle">screen cfg changing</button>
</td>
</tr>
2023-02-18 21:52:57 +01:00
<tr>
<th>click on color</th>
<td>
<NekoColor @colorChange="neko.control.buttonPress(1, $event)" />
</td>
</tr>
2022-07-16 21:30:35 +02:00
</table>
</div>
</template>
<style lang="scss">
.tab-states {
&,
.states {
width: 100%;
}
td,
th {
border: 1px solid #ccc;
padding: 4px;
}
th {
text-align: left;
}
.middle {
vertical-align: middle;
}
.space-between {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
}
</style>
<script lang="ts">
2022-11-07 19:40:36 +01:00
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
2022-07-16 21:30:35 +02:00
import Neko from '~/component/main.vue'
2023-02-18 21:52:57 +01:00
import NekoColor from './color.vue'
2022-07-16 21:30:35 +02:00
@Component({
name: 'neko-events',
2023-02-18 21:52:57 +01:00
components: {
NekoColor,
},
2022-07-16 21:30:35 +02:00
})
export default class extends Vue {
@Prop() readonly neko!: Neko
clipboardText: string = ''
2022-11-07 19:40:36 +01:00
bitrate: number | null = null
@Watch('neko.state.connection.webrtc.bitrate')
onBitrateChange(val: number) {
this.bitrate = val
}
2022-07-16 21:30:35 +02:00
shift = false
get letters(): number[] {
let letters = [] as number[]
for (let i = (this.shift ? 'A' : 'a').charCodeAt(0); i <= (this.shift ? 'Z' : 'z').charCodeAt(0); i++) {
letters.push(i)
}
return letters
}
// fast sceen changing test
screen_interval = null
screenChangingToggle() {
if (this.screen_interval === null) {
let sizes = this.neko.state.screen.configurations
let len = sizes.length
//@ts-ignore
this.screen_interval = setInterval(() => {
let { width, height, rate } = sizes[Math.floor(Math.random() * len)]
this.neko.setScreenSize(width, height, rate)
}, 10)
} else {
//@ts-ignore
clearInterval(this.screen_interval)
this.screen_interval = null
}
}
screenConfiguration = ''
setScreenConfiguration() {
let [width, height, rate] = this.screenConfiguration.split(/[@x]/)
this.neko.setScreenSize(parseInt(width), parseInt(height), parseInt(rate))
}
@Watch('neko.state.screen.size', { immediate: true })
onScreenSizeChange(val: any) {
this.screenConfiguration = `${val.width}x${val.height}@${val.rate}`
}
// fast cursor moving test
cursor_interval = null
cursorMovingToggle() {
if (this.cursor_interval === null) {
let len = this.neko.state.screen.size.width
//@ts-ignore
this.cursor_interval = setInterval(() => {
let x = Math.floor(Math.random() * len)
let y = Math.floor(Math.random() * len)
this.neko.control.move({ x, y })
}, 10)
} else {
//@ts-ignore
clearInterval(this.cursor_interval)
this.cursor_interval = null
}
}
2022-07-16 21:30:35 +02:00
async updateSettings(settings: any) {
try {
await this.neko.room.settingsSet(settings)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
}
</script>