neko/src/page/components/events.vue

507 lines
16 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>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: 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>connection.webrtc.video</th>
<td>{{ neko.state.connection.webrtc.video }}</td>
</tr>
<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" @input="neko.setWebRTCVideo($event.target.value)">
<option v-for="video in neko.state.connection.webrtc.videos" :key="video" :value="video">
{{ video }}
</option>
</select>
2022-11-07 19:40:36 +01:00
or
<input type="text" v-model="bitrate" style="width: 60px" placeholder="Bitrate" />
<button @click="neko.setWebRTCVideo('', Number(bitrate))">Set</button>
2022-07-16 21:30:35 +02:00
</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 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>
<select
:value="Object.values(neko.state.screen.size).join()"
@input="
a = String($event.target.value).split(',')
neko.setScreenSize(parseInt(a[0]), parseInt(a[1]), parseInt(a[2]))
"
>
<option
v-for="{ width, height, rate } in neko.state.screen.configurations"
:key="String(width) + String(height) + String(rate)"
:value="[width, height, rate].join()"
>
{{ width }}x{{ height }}@{{ rate }}
</option>
</select>
<button @click="screenChangingToggle">screenChangingToggle</button>
</td>
</tr>
</template>
<tr v-else>
<th>screen.configurations</th>
<td>Session is not admin.</td>
</tr>
<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>
<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>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>
</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'
@Component({
name: 'neko-events',
})
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
}
}
async updateSettings(settings: any) {
try {
await this.neko.room.settingsSet(settings)
} catch (e: any) {
alert(e.response ? e.response.data.message : e)
}
}
}
</script>