commit
f08ed0fc28
@ -110,7 +110,7 @@
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class extends Vue {
|
export default class extends Vue {
|
||||||
@Ref('context') readonly context!: any
|
@Ref('context') readonly context!: VueContext
|
||||||
|
|
||||||
get width() {
|
get width() {
|
||||||
return this.$accessor.video.width
|
return this.$accessor.video.width
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul v-if="!fullscreen && !hideControls" class="video-menu top">
|
<ul v-if="!fullscreen && !hideControls" class="video-menu top">
|
||||||
<li><i @click.stop.prevent="requestFullscreen" class="fas fa-expand"></i></li>
|
<li><i @click.stop.prevent="requestFullscreen" class="fas fa-expand"></i></li>
|
||||||
<li v-if="admin"><i @click.stop.prevent="onResolution" class="fas fa-desktop"></i></li>
|
<li v-if="admin"><i @click.stop.prevent="openResolution" class="fas fa-desktop"></i></li>
|
||||||
<li class="request-control">
|
<li class="request-control">
|
||||||
<i
|
<i
|
||||||
:class="[hosted && !hosting ? 'disabled' : '', !hosted && !hosting ? 'faded' : '', 'fas', 'fa-keyboard']"
|
:class="[hosted && !hosting ? 'disabled' : '', !hosted && !hosting ? 'faded' : '', 'fas', 'fa-keyboard']"
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<ul v-if="!fullscreen && !hideControls" class="video-menu bottom">
|
<ul v-if="!fullscreen && !hideControls" class="video-menu bottom">
|
||||||
<li v-if="hosting && (!clipboard_read_available || !clipboard_write_available)">
|
<li v-if="hosting && (!clipboard_read_available || !clipboard_write_available)">
|
||||||
<i @click.stop.prevent="onClipboard" class="fas fa-clipboard"></i>
|
<i @click.stop.prevent="openClipboard" class="fas fa-clipboard"></i>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<i
|
<i
|
||||||
@ -186,6 +186,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Ref, Watch, Vue, Prop } from 'vue-property-decorator'
|
import { Component, Ref, Watch, Vue, Prop } from 'vue-property-decorator'
|
||||||
import ResizeObserver from 'resize-observer-polyfill'
|
import ResizeObserver from 'resize-observer-polyfill'
|
||||||
|
import { elementRequestFullscreen } from '~/utils'
|
||||||
|
|
||||||
import Emote from './emote.vue'
|
import Emote from './emote.vue'
|
||||||
import Resolution from './resolution.vue'
|
import Resolution from './resolution.vue'
|
||||||
@ -211,13 +212,13 @@
|
|||||||
@Ref('aspect') readonly _aspect!: HTMLElement
|
@Ref('aspect') readonly _aspect!: HTMLElement
|
||||||
@Ref('player') readonly _player!: HTMLElement
|
@Ref('player') readonly _player!: HTMLElement
|
||||||
@Ref('video') readonly _video!: HTMLVideoElement
|
@Ref('video') readonly _video!: HTMLVideoElement
|
||||||
@Ref('resolution') readonly _resolution!: any
|
@Ref('resolution') readonly _resolution!: Resolution
|
||||||
@Ref('clipboard') readonly _clipboard!: any
|
@Ref('clipboard') readonly _clipboard!: Clipboard
|
||||||
|
|
||||||
@Prop(Boolean) readonly hideControls!: boolean
|
@Prop(Boolean) readonly hideControls!: boolean
|
||||||
|
|
||||||
private keyboard = GuacamoleKeyboard()
|
private keyboard = GuacamoleKeyboard()
|
||||||
private observer = new ResizeObserver(this.onResise.bind(this))
|
private observer = new ResizeObserver(this.onResize.bind(this))
|
||||||
private focused = false
|
private focused = false
|
||||||
private fullscreen = false
|
private fullscreen = false
|
||||||
private startsMuted = true
|
private startsMuted = true
|
||||||
@ -322,12 +323,12 @@
|
|||||||
|
|
||||||
@Watch('width')
|
@Watch('width')
|
||||||
onWidthChanged(width: number) {
|
onWidthChanged(width: number) {
|
||||||
this.onResise()
|
this.onResize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('height')
|
@Watch('height')
|
||||||
onHeightChanged(height: number) {
|
onHeightChanged(height: number) {
|
||||||
this.onResise()
|
this.onResize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('volume')
|
@Watch('volume')
|
||||||
@ -377,24 +378,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Watch('clipboard')
|
@Watch('clipboard')
|
||||||
onClipboardChanged(clipboard: string) {
|
async onClipboardChanged(clipboard: string) {
|
||||||
if (this.clipboard_write_available) {
|
if (this.clipboard_write_available) {
|
||||||
navigator.clipboard.writeText(clipboard).catch(console.error)
|
try {
|
||||||
|
await navigator.clipboard.writeText(clipboard)
|
||||||
|
this.$accessor.remote.setClipboard(clipboard)
|
||||||
|
} catch (err: any) {
|
||||||
|
this.$log.error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this._container.addEventListener('resize', this.onResise)
|
this._container.addEventListener('resize', this.onResize)
|
||||||
this.onVolumeChanged(this.volume)
|
this.onVolumeChanged(this.volume)
|
||||||
this.onMutedChanged(this.muted)
|
this.onMutedChanged(this.muted)
|
||||||
this.onStreamChanged(this.stream)
|
this.onStreamChanged(this.stream)
|
||||||
this.onResise()
|
this.onResize()
|
||||||
|
|
||||||
this.observer.observe(this._component)
|
this.observer.observe(this._component)
|
||||||
|
|
||||||
this._player.addEventListener('fullscreenchange', () => {
|
this._player.addEventListener('fullscreenchange', () => {
|
||||||
this.fullscreen = document.fullscreenElement !== null
|
this.fullscreen = document.fullscreenElement !== null
|
||||||
this.onResise()
|
this.onResize()
|
||||||
})
|
})
|
||||||
|
|
||||||
this._video.addEventListener('canplaythrough', () => {
|
this._video.addEventListener('canplaythrough', () => {
|
||||||
@ -433,8 +439,6 @@
|
|||||||
this.$accessor.video.pause()
|
this.$accessor.video.pause()
|
||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener('focusin', this.onFocus.bind(this))
|
|
||||||
|
|
||||||
/* Initialize Guacamole Keyboard */
|
/* Initialize Guacamole Keyboard */
|
||||||
this.keyboard.onkeydown = (key: number) => {
|
this.keyboard.onkeydown = (key: number) => {
|
||||||
if (!this.focused || !this.hosting || this.locked) {
|
if (!this.focused || !this.hosting || this.locked) {
|
||||||
@ -457,7 +461,6 @@
|
|||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.observer.disconnect()
|
this.observer.disconnect()
|
||||||
this.$accessor.video.setPlayable(false)
|
this.$accessor.video.setPlayable(false)
|
||||||
document.removeEventListener('focusin', this.onFocus.bind(this))
|
|
||||||
/* Guacamole Keyboard does not provide destroy functions */
|
/* Guacamole Keyboard does not provide destroy functions */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,7 +516,7 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this._video.play()
|
await this._video.play()
|
||||||
this.onResise()
|
this.onResize()
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this.$log.error(err)
|
this.$log.error(err)
|
||||||
}
|
}
|
||||||
@ -551,38 +554,20 @@
|
|||||||
this.$accessor.remote.toggle()
|
this.$accessor.remote.toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
_elementRequestFullscreen(el: HTMLElement) {
|
requestControl() {
|
||||||
if (typeof el.requestFullscreen === 'function') {
|
this.$accessor.remote.request()
|
||||||
el.requestFullscreen()
|
|
||||||
//@ts-ignore
|
|
||||||
} else if (typeof el.webkitRequestFullscreen === 'function') {
|
|
||||||
//@ts-ignore
|
|
||||||
el.webkitRequestFullscreen()
|
|
||||||
//@ts-ignore
|
|
||||||
} else if (typeof el.webkitEnterFullscreen === 'function') {
|
|
||||||
//@ts-ignore
|
|
||||||
el.webkitEnterFullscreen()
|
|
||||||
//@ts-ignore
|
|
||||||
} else if (typeof el.msRequestFullScreen === 'function') {
|
|
||||||
//@ts-ignore
|
|
||||||
el.msRequestFullScreen()
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestFullscreen() {
|
requestFullscreen() {
|
||||||
// try to fullscreen player element
|
// try to fullscreen player element
|
||||||
if (this._elementRequestFullscreen(this._player)) {
|
if (elementRequestFullscreen(this._player)) {
|
||||||
this.onResise()
|
this.onResize()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback to fullscreen video itself (on mobile devices)
|
// fallback to fullscreen video itself (on mobile devices)
|
||||||
if (this._elementRequestFullscreen(this._video)) {
|
if (elementRequestFullscreen(this._video)) {
|
||||||
this.onResise()
|
this.onResize()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,15 +575,19 @@
|
|||||||
requestPictureInPicture() {
|
requestPictureInPicture() {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this._video.requestPictureInPicture()
|
this._video.requestPictureInPicture()
|
||||||
this.onResise()
|
this.onResize()
|
||||||
}
|
}
|
||||||
|
|
||||||
async onFocus() {
|
openResolution(event: MouseEvent) {
|
||||||
if (!document.hasFocus() || !this.$accessor.active) {
|
this._resolution.open(event)
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hosting && this.clipboard_read_available) {
|
openClipboard() {
|
||||||
|
this._clipboard.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
async syncClipboard() {
|
||||||
|
if (this.clipboard_read_available) {
|
||||||
try {
|
try {
|
||||||
const text = await navigator.clipboard.readText()
|
const text = await navigator.clipboard.readText()
|
||||||
if (this.clipboard !== text) {
|
if (this.clipboard !== text) {
|
||||||
@ -611,9 +600,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMousePos(e: MouseEvent) {
|
sendMousePos(e: MouseEvent) {
|
||||||
const { w, h } = this.$accessor.video.resolution
|
const { w, h } = this.$accessor.video.resolution
|
||||||
const rect = this._overlay.getBoundingClientRect()
|
const rect = this._overlay.getBoundingClientRect()
|
||||||
|
|
||||||
this.$client.sendData('mousemove', {
|
this.$client.sendData('mousemove', {
|
||||||
x: Math.round((w / rect.width) * (e.clientX - rect.left)),
|
x: Math.round((w / rect.width) * (e.clientX - rect.left)),
|
||||||
y: Math.round((h / rect.height) * (e.clientY - rect.top)),
|
y: Math.round((h / rect.height) * (e.clientY - rect.top)),
|
||||||
@ -625,7 +615,6 @@
|
|||||||
if (!this.hosting || this.locked) {
|
if (!this.hosting || this.locked) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.onMousePos(e)
|
|
||||||
|
|
||||||
let x = e.deltaX
|
let x = e.deltaX
|
||||||
let y = e.deltaY
|
let y = e.deltaY
|
||||||
@ -648,6 +637,8 @@
|
|||||||
x = Math.min(Math.max(x, -this.scroll), this.scroll)
|
x = Math.min(Math.max(x, -this.scroll), this.scroll)
|
||||||
y = Math.min(Math.max(y, -this.scroll), this.scroll)
|
y = Math.min(Math.max(y, -this.scroll), this.scroll)
|
||||||
|
|
||||||
|
this.sendMousePos(e)
|
||||||
|
|
||||||
if (!this.wheelThrottle) {
|
if (!this.wheelThrottle) {
|
||||||
this.wheelThrottle = true
|
this.wheelThrottle = true
|
||||||
this.$client.sendData('wheel', { x, y })
|
this.$client.sendData('wheel', { x, y })
|
||||||
@ -667,7 +658,7 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onMousePos(e)
|
this.sendMousePos(e)
|
||||||
this.$client.sendData('mousedown', { key: e.button + 1 })
|
this.$client.sendData('mousedown', { key: e.button + 1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,7 +667,7 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onMousePos(e)
|
this.sendMousePos(e)
|
||||||
this.$client.sendData('mouseup', { key: e.button + 1 })
|
this.$client.sendData('mouseup', { key: e.button + 1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,7 +676,7 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onMousePos(e)
|
this.sendMousePos(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnter(e: MouseEvent) {
|
onMouseEnter(e: MouseEvent) {
|
||||||
@ -695,10 +686,11 @@
|
|||||||
numLock: e.getModifierState('NumLock'),
|
numLock: e.getModifierState('NumLock'),
|
||||||
scrollLock: e.getModifierState('ScrollLock'),
|
scrollLock: e.getModifierState('ScrollLock'),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.syncClipboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
this._overlay.focus()
|
this._overlay.focus()
|
||||||
this.onFocus()
|
|
||||||
this.focused = true
|
this.focused = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,7 +707,7 @@
|
|||||||
this.focused = false
|
this.focused = false
|
||||||
}
|
}
|
||||||
|
|
||||||
onResise() {
|
onResize() {
|
||||||
let height = 0
|
let height = 0
|
||||||
if (!this.fullscreen) {
|
if (!this.fullscreen) {
|
||||||
const { offsetWidth, offsetHeight } = this._component
|
const { offsetWidth, offsetHeight } = this._component
|
||||||
@ -730,13 +722,5 @@
|
|||||||
this._container.style.maxWidth = `${(this.horizontal / this.vertical) * height}px`
|
this._container.style.maxWidth = `${(this.horizontal / this.vertical) * height}px`
|
||||||
this._aspect.style.paddingBottom = `${(this.vertical / this.horizontal) * 100}%`
|
this._aspect.style.paddingBottom = `${(this.vertical / this.horizontal) * 100}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
onResolution(event: MouseEvent) {
|
|
||||||
this._resolution.open(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
onClipboard(event: MouseEvent) {
|
|
||||||
this._clipboard.open(event)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -10,6 +10,7 @@ export const EVENT = {
|
|||||||
|
|
||||||
// Websocket Events
|
// Websocket Events
|
||||||
SYSTEM: {
|
SYSTEM: {
|
||||||
|
INIT: 'system/init',
|
||||||
DISCONNECT: 'system/disconnect',
|
DISCONNECT: 'system/disconnect',
|
||||||
ERROR: 'system/error',
|
ERROR: 'system/error',
|
||||||
},
|
},
|
||||||
|
@ -22,6 +22,8 @@ import {
|
|||||||
AdminPayload,
|
AdminPayload,
|
||||||
AdminTargetPayload,
|
AdminTargetPayload,
|
||||||
AdminLockMessage,
|
AdminLockMessage,
|
||||||
|
SystemInitPayload,
|
||||||
|
AdminLockResource,
|
||||||
} from './messages'
|
} from './messages'
|
||||||
|
|
||||||
interface NekoEvents extends BaseEvents {}
|
interface NekoEvents extends BaseEvents {}
|
||||||
@ -131,6 +133,18 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// System Events
|
// System Events
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
protected [EVENT.SYSTEM.INIT]({ implicit_hosting, locks }: SystemInitPayload) {
|
||||||
|
this.$accessor.remote.setImplicitHosting(implicit_hosting)
|
||||||
|
|
||||||
|
for (const resource in locks) {
|
||||||
|
this[EVENT.ADMIN.LOCK]({
|
||||||
|
event: EVENT.ADMIN.LOCK,
|
||||||
|
resource: resource as AdminLockResource,
|
||||||
|
id: locks[resource],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected [EVENT.SYSTEM.DISCONNECT]({ message }: SystemMessagePayload) {
|
protected [EVENT.SYSTEM.DISCONNECT]({ message }: SystemMessagePayload) {
|
||||||
if (message == 'kicked') {
|
if (message == 'kicked') {
|
||||||
this.$accessor.logout()
|
this.$accessor.logout()
|
||||||
|
@ -52,6 +52,15 @@ export interface WebSocketMessage {
|
|||||||
/*
|
/*
|
||||||
SYSTEM MESSAGES/PAYLOADS
|
SYSTEM MESSAGES/PAYLOADS
|
||||||
*/
|
*/
|
||||||
|
// system/init
|
||||||
|
export interface SystemInit extends WebSocketMessage, SystemInitPayload {
|
||||||
|
event: typeof EVENT.SYSTEM.INIT
|
||||||
|
}
|
||||||
|
export interface SystemInitPayload {
|
||||||
|
implicit_hosting: boolean
|
||||||
|
locks: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
// system/disconnect
|
// system/disconnect
|
||||||
// system/error
|
// system/error
|
||||||
export interface SystemMessage extends WebSocketMessage, SystemMessagePayload {
|
export interface SystemMessage extends WebSocketMessage, SystemMessagePayload {
|
||||||
|
@ -12,7 +12,7 @@ export const state = () => ({
|
|||||||
id: '',
|
id: '',
|
||||||
clipboard: '',
|
clipboard: '',
|
||||||
locked: false,
|
locked: false,
|
||||||
|
implicitHosting: true,
|
||||||
keyboardModifierState: -1,
|
keyboardModifierState: -1,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -49,10 +49,15 @@ export const mutations = mutationTree(state, {
|
|||||||
state.locked = locked
|
state.locked = locked
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setImplicitHosting(state, val: boolean) {
|
||||||
|
state.implicitHosting = val
|
||||||
|
},
|
||||||
|
|
||||||
reset(state) {
|
reset(state) {
|
||||||
state.id = ''
|
state.id = ''
|
||||||
state.clipboard = ''
|
state.clipboard = ''
|
||||||
state.locked = false
|
state.locked = false
|
||||||
|
state.implicitHosting = false
|
||||||
state.keyboardModifierState = -1
|
state.keyboardModifierState = -1
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -7,3 +7,24 @@ export function makeid(length: number) {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function elementRequestFullscreen(el: HTMLElement) {
|
||||||
|
if (typeof el.requestFullscreen === 'function') {
|
||||||
|
el.requestFullscreen()
|
||||||
|
//@ts-ignore
|
||||||
|
} else if (typeof el.webkitRequestFullscreen === 'function') {
|
||||||
|
//@ts-ignore
|
||||||
|
el.webkitRequestFullscreen()
|
||||||
|
//@ts-ignore
|
||||||
|
} else if (typeof el.webkitEnterFullscreen === 'function') {
|
||||||
|
//@ts-ignore
|
||||||
|
el.webkitEnterFullscreen()
|
||||||
|
//@ts-ignore
|
||||||
|
} else if (typeof el.msRequestFullScreen === 'function') {
|
||||||
|
//@ts-ignore
|
||||||
|
el.msRequestFullScreen()
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
- Added `m1k1o/neko:microsoft-edge` tag.
|
- Added `m1k1o/neko:microsoft-edge` tag.
|
||||||
|
- Fixed clipboard sync in chromium based browsers.
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- Automatic WebRTC SDP negotiation using onnegotiationneeded handlers. This allows adding/removing track on demand in a session.
|
- Automatic WebRTC SDP negotiation using onnegotiationneeded handlers. This allows adding/removing track on demand in a session.
|
||||||
- Added UDP and TCP mux for WebRTC connection. It should handle multiple peers.
|
- Added UDP and TCP mux for WebRTC connection. It should handle multiple peers.
|
||||||
|
- Broadcast status change is sent to all admins now.
|
||||||
|
|
||||||
## [n.eko v2.5](https://github.com/m1k1o/neko/releases/tag/v2.5)
|
## [n.eko v2.5](https://github.com/m1k1o/neko/releases/tag/v2.5)
|
||||||
|
|
||||||
|
@ -184,6 +184,30 @@ func (manager *SessionManager) Broadcast(v interface{}, exclude interface{}) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *SessionManager) AdminBroadcast(v interface{}, exclude interface{}) error {
|
||||||
|
manager.mu.Lock()
|
||||||
|
defer manager.mu.Unlock()
|
||||||
|
|
||||||
|
for id, session := range manager.members {
|
||||||
|
if !session.connected || !session.admin {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if exclude != nil {
|
||||||
|
if in, _ := utils.ArrayIn(id, exclude); in {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := session.Send(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package event
|
package event
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
SYSTEM_INIT = "system/init"
|
||||||
SYSTEM_DISCONNECT = "system/disconnect"
|
SYSTEM_DISCONNECT = "system/disconnect"
|
||||||
SYSTEM_ERROR = "system/error"
|
SYSTEM_ERROR = "system/error"
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,12 @@ type Message struct {
|
|||||||
Event string `json:"event"`
|
Event string `json:"event"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SystemInit struct {
|
||||||
|
Event string `json:"event"`
|
||||||
|
ImplicitHosting bool `json:"implicit_hosting"`
|
||||||
|
Locks map[string]string `json:"locks"`
|
||||||
|
}
|
||||||
|
|
||||||
type SystemMessage struct {
|
type SystemMessage struct {
|
||||||
Event string `json:"event"`
|
Event string `json:"event"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
@ -43,6 +43,7 @@ type SessionManager interface {
|
|||||||
Destroy(id string)
|
Destroy(id string)
|
||||||
Clear() error
|
Clear() error
|
||||||
Broadcast(v interface{}, exclude interface{}) error
|
Broadcast(v interface{}, exclude interface{}) error
|
||||||
|
AdminBroadcast(v interface{}, exclude interface{}) error
|
||||||
OnHost(listener func(id string))
|
OnHost(listener func(id string))
|
||||||
OnHostCleared(listener func(id string))
|
OnHostCleared(listener func(id string))
|
||||||
OnDestroy(listener func(id string, session Session))
|
OnDestroy(listener func(id string, session Session))
|
||||||
|
@ -25,7 +25,7 @@ func (h *MessageHandler) boradcastCreate(session types.Session, payload *message
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.boradcastStatus(session); err != nil {
|
if err := h.boradcastStatus(nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ func (h *MessageHandler) boradcastDestroy(session types.Session) error {
|
|||||||
|
|
||||||
h.broadcast.Destroy()
|
h.broadcast.Destroy()
|
||||||
|
|
||||||
if err := h.boradcastStatus(session); err != nil {
|
if err := h.boradcastStatus(nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +48,21 @@ func (h *MessageHandler) boradcastDestroy(session types.Session) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) boradcastStatus(session types.Session) error {
|
func (h *MessageHandler) boradcastStatus(session types.Session) error {
|
||||||
|
// if no session, broadcast change
|
||||||
|
if session == nil {
|
||||||
|
if err := h.sessions.AdminBroadcast(
|
||||||
|
message.BroadcastStatus{
|
||||||
|
Event: event.BORADCAST_STATUS,
|
||||||
|
IsActive: h.broadcast.IsActive(),
|
||||||
|
URL: h.broadcast.GetUrl(),
|
||||||
|
}, nil); err != nil {
|
||||||
|
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.BORADCAST_STATUS)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if !session.Admin() {
|
if !session.Admin() {
|
||||||
h.logger.Debug().Msg("user not admin")
|
h.logger.Debug().Msg("user not admin")
|
||||||
return nil
|
return nil
|
||||||
|
@ -12,16 +12,14 @@ func (h *MessageHandler) SessionCreated(id string, session types.Session) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify all about what is locked
|
// send initialization information
|
||||||
for resource, id := range h.locked {
|
if err := session.Send(message.SystemInit{
|
||||||
if err := session.Send(message.AdminLock{
|
Event: event.SYSTEM_INIT,
|
||||||
Event: event.ADMIN_LOCK,
|
ImplicitHosting: true,
|
||||||
ID: id,
|
Locks: h.locked,
|
||||||
Resource: resource,
|
}); err != nil {
|
||||||
}); err != nil {
|
h.logger.Warn().Str("id", id).Err(err).Msgf("sending event %s has failed", event.SYSTEM_INIT)
|
||||||
h.logger.Warn().Str("id", id).Err(err).Msgf("sending event %s has failed", event.ADMIN_LOCK)
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.Admin() {
|
if session.Admin() {
|
||||||
|
Reference in New Issue
Block a user