Fully converted to full socket
This commit is contained in:
@@ -29,15 +29,16 @@ export default {
|
|||||||
name: 'Admin',
|
name: 'Admin',
|
||||||
computed: {
|
computed: {
|
||||||
usersList () {
|
usersList () {
|
||||||
return this.$store.state.rtc.peers
|
// return this.$store.state.rtc.peers
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
broadcastStatus () {
|
broadcastStatus () {
|
||||||
this.$store.dispatch('rtc/broadcast', { message: this.$store.state.room.roomStatus, type: 'status' })
|
// this.$store.dispatch('rtc/broadcast', { message: this.$store.state.room.roomStatus, type: 'status' })
|
||||||
},
|
},
|
||||||
kickUser (target) {
|
kickUser (target) {
|
||||||
this.$store.dispatch('rtc/kick', target)
|
// this.$store.dispatch('rtc/kick', target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { send } from '@/store/signalPlugin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Player',
|
name: 'Player',
|
||||||
computed: {
|
computed: {
|
||||||
@@ -118,7 +120,7 @@ export default {
|
|||||||
if (this.roomStatus.player.playing) this.player.pauseVideo()
|
if (this.roomStatus.player.playing) this.player.pauseVideo()
|
||||||
else this.player.playVideo()
|
else this.player.playVideo()
|
||||||
} else if (this.roomSettings.userControl) {
|
} else if (this.roomSettings.userControl) {
|
||||||
this.$store.dispatch('rtc/broadcast', { message: { type: 'play' }, type: 'userCommand' })
|
send({ message: { type: 'play' }, type: 'roomUserCommand' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mute () {
|
async mute () {
|
||||||
@@ -130,11 +132,11 @@ export default {
|
|||||||
},
|
},
|
||||||
skip () {
|
skip () {
|
||||||
if (this.isAdmin) this.$store.commit('room/CURRENT_END')
|
if (this.isAdmin) this.$store.commit('room/CURRENT_END')
|
||||||
else if (this.roomSettings.userControl) this.$store.dispatch('rtc/broadcast', { message: { type: 'skip' }, type: 'userCommand' })
|
else if (this.roomSettings.userControl) send({ message: { type: 'skip' }, type: 'roomUserCommand' })
|
||||||
},
|
},
|
||||||
seek (time) {
|
seek (time) {
|
||||||
if (this.isAdmin) this.player.seekTo(time, true)
|
if (this.isAdmin) this.player.seekTo(time, true)
|
||||||
else if (this.roomSettings.userControl) this.$store.dispatch('rtc/broadcast', { message: { type: 'seek', argument: time }, type: 'userCommand' })
|
else if (this.roomSettings.userControl) send({ message: { type: 'seek', argument: time }, type: 'roomUserCommand' })
|
||||||
},
|
},
|
||||||
async updateTimeCode () {
|
async updateTimeCode () {
|
||||||
if (this.localSettings.playLink) this.$store.dispatch('room/setTimeCode', await this.player.getCurrentTime())
|
if (this.localSettings.playLink) this.$store.dispatch('room/setTimeCode', await this.player.getCurrentTime())
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { send } from '@/store/signalPlugin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Playlist',
|
name: 'Playlist',
|
||||||
computed: {
|
computed: {
|
||||||
@@ -70,23 +72,24 @@ export default {
|
|||||||
},
|
},
|
||||||
vote (title, link, linkID, isPositive) {
|
vote (title, link, linkID, isPositive) {
|
||||||
if (this.isAdmin) {
|
if (this.isAdmin) {
|
||||||
this.$store.dispatch('room/vote', { title: title, link: link, linkID: linkID, isPositive: isPositive, voterName: this.$store.state.rtc.name })
|
this.$store.dispatch('room/vote', { title: title, link: link, linkID: linkID, isPositive: isPositive, voterName: this.$store.state.app.name })
|
||||||
} else {
|
} else {
|
||||||
this.sendVote(link, linkID, isPositive)
|
this.sendVote(title, link, linkID, isPositive)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sendVote (link, linkID, isPositive) {
|
sendVote (title, link, linkID, isPositive) {
|
||||||
const message = {
|
const message = {
|
||||||
type: 'vote',
|
type: 'vote',
|
||||||
|
title: title,
|
||||||
link: link,
|
link: link,
|
||||||
linkID: linkID,
|
linkID: linkID,
|
||||||
isPositive: isPositive,
|
isPositive: isPositive,
|
||||||
voterName: this.$store.state.rtc.name
|
voterName: this.$store.state.app.name
|
||||||
}
|
}
|
||||||
this.$store.dispatch('rtc/broadcast', { message: message, type: 'vote' })
|
send({ message: message, type: 'roomVote' })
|
||||||
},
|
},
|
||||||
hasVoted (play) {
|
hasVoted (play) {
|
||||||
return play.voters.includes(this.$store.state.rtc.name)
|
return play.voters.includes(this.$store.state.app.name)
|
||||||
},
|
},
|
||||||
removePlay (linkID) {
|
removePlay (linkID) {
|
||||||
this.$store.dispatch('room/removePlay', linkID)
|
this.$store.dispatch('room/removePlay', linkID)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
import { register } from 'register-service-worker'
|
import { register } from 'register-service-worker'
|
||||||
|
import { ToastProgrammatic as Toast } from 'buefy'
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
register(`${process.env.BASE_URL}service-worker.js`, {
|
register(`${process.env.BASE_URL}service-worker.js`, {
|
||||||
@@ -18,13 +19,16 @@ if (process.env.NODE_ENV === 'production') {
|
|||||||
},
|
},
|
||||||
updatefound () {
|
updatefound () {
|
||||||
console.log('New content is downloading.')
|
console.log('New content is downloading.')
|
||||||
|
Toast.open('Update found, downloading...')
|
||||||
},
|
},
|
||||||
updated () {
|
updated () {
|
||||||
console.log('New content is available; please refresh.')
|
console.log('New content is available; please refresh.')
|
||||||
window.location.reload(true)
|
window.location.reload(true)
|
||||||
|
Toast.open('App updated !')
|
||||||
},
|
},
|
||||||
offline () {
|
offline () {
|
||||||
console.log('No internet connection found. App is running in offline mode.')
|
console.log('No internet connection found. App is running in offline mode.')
|
||||||
|
Toast.open('No internet connection !')
|
||||||
},
|
},
|
||||||
error (error) {
|
error (error) {
|
||||||
console.error('Error during service worker registration:', error)
|
console.error('Error during service worker registration:', error)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import router from '@/router/index'
|
|||||||
const state = {
|
const state = {
|
||||||
signalServerConnected: false,
|
signalServerConnected: false,
|
||||||
loginSuccess: null,
|
loginSuccess: null,
|
||||||
|
name: '',
|
||||||
error: null,
|
error: null,
|
||||||
serverStatus: {}
|
serverStatus: {}
|
||||||
}
|
}
|
||||||
@@ -33,17 +34,15 @@ const actions = {
|
|||||||
serverStatus ({ commit }, serverStatus) {
|
serverStatus ({ commit }, serverStatus) {
|
||||||
commit('SET_SERVERSTATUS', serverStatus)
|
commit('SET_SERVERSTATUS', serverStatus)
|
||||||
},
|
},
|
||||||
createRoom ({ commit, dispatch }, code) {
|
|
||||||
commit('CREATE_ROOM')
|
|
||||||
dispatch('room/setRoomCode', code, { root: true })
|
|
||||||
dispatch('room/setAdmin', null, { root: true })
|
|
||||||
},
|
|
||||||
connectRoom ({ commit, dispatch }, name) {
|
connectRoom ({ commit, dispatch }, name) {
|
||||||
commit('CONNECT_ROOM')
|
commit('CONNECT_ROOM')
|
||||||
dispatch('rtc/makeOffer', name, { root: true })
|
// dispatch('rtc/makeOffer', name, { root: true })
|
||||||
},
|
},
|
||||||
error ({ commit }, error) {
|
error ({ commit }, error) {
|
||||||
commit('ERROR', error)
|
commit('ERROR', error)
|
||||||
|
},
|
||||||
|
setName ({ commit }, name) {
|
||||||
|
commit('SET_NAME', name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,15 +66,15 @@ const mutations = {
|
|||||||
SET_SERVERSTATUS (state, serverStatus) {
|
SET_SERVERSTATUS (state, serverStatus) {
|
||||||
state.serverStatus = serverStatus
|
state.serverStatus = serverStatus
|
||||||
},
|
},
|
||||||
CREATE_ROOM (state) {
|
|
||||||
router.push({ name: 'Room' })
|
|
||||||
},
|
|
||||||
CONNECT_ROOM (state) {
|
CONNECT_ROOM (state) {
|
||||||
router.push({ name: 'Room' })
|
router.push({ name: 'Room' })
|
||||||
},
|
},
|
||||||
ERROR (state, error) {
|
ERROR (state, error) {
|
||||||
state.error = error
|
state.error = error
|
||||||
Dialog.alert(error)
|
Dialog.alert(error)
|
||||||
|
},
|
||||||
|
SET_NAME (state, name) {
|
||||||
|
state.name = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import signal from './signalPlugin'
|
import signal from './signalPlugin'
|
||||||
import rtc from './rtcModule'
|
|
||||||
import room from './roomModule'
|
import room from './roomModule'
|
||||||
import app from './appModule'
|
import app from './appModule'
|
||||||
|
|
||||||
@@ -9,7 +8,6 @@ Vue.use(Vuex)
|
|||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
rtc,
|
|
||||||
app,
|
app,
|
||||||
room
|
room
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { send } from './signalPlugin'
|
||||||
|
import router from '@/router/index'
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
admin: false,
|
admin: false,
|
||||||
roomStatus: {
|
roomStatus: {
|
||||||
@@ -32,6 +35,13 @@ const getters = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
createRoom ({ commit }, roomCode) {
|
||||||
|
commit('SET_ROOMCODE', roomCode)
|
||||||
|
commit('SET_ADMIN')
|
||||||
|
send({ message: state.roomSettings, type: 'roomSettings' })
|
||||||
|
send({ message: state.roomStatus, type: 'roomStatus' })
|
||||||
|
router.push({ name: 'Room' })
|
||||||
|
},
|
||||||
setRoomCode ({ commit }, roomCode) {
|
setRoomCode ({ commit }, roomCode) {
|
||||||
commit('SET_ROOMCODE', roomCode)
|
commit('SET_ROOMCODE', roomCode)
|
||||||
},
|
},
|
||||||
@@ -44,9 +54,9 @@ const actions = {
|
|||||||
setUserCommand ({ commit }, command) {
|
setUserCommand ({ commit }, command) {
|
||||||
commit('SET_USERCOMMAND', command)
|
commit('SET_USERCOMMAND', command)
|
||||||
},
|
},
|
||||||
setRoomSettings ({ commit, dispatch, state }, roomSettings) {
|
setRoomSettings ({ commit, state }, roomSettings) {
|
||||||
commit('SET_ROOMSETTINGS', roomSettings)
|
commit('SET_ROOMSETTINGS', roomSettings)
|
||||||
if (state.admin) dispatch('rtc/broadcast', { message: state.roomSettings, type: 'settings' }, { root: true })
|
if (state.admin) send({ message: state.roomSettings, type: 'roomSettings' })
|
||||||
},
|
},
|
||||||
setLocalSettings ({ commit }, localSettings) {
|
setLocalSettings ({ commit }, localSettings) {
|
||||||
commit('SET_LOCALSETTINGS', localSettings)
|
commit('SET_LOCALSETTINGS', localSettings)
|
||||||
@@ -57,7 +67,7 @@ const actions = {
|
|||||||
setTimeCode ({ commit }, timeCode) {
|
setTimeCode ({ commit }, timeCode) {
|
||||||
commit('SET_TIMECODE', timeCode)
|
commit('SET_TIMECODE', timeCode)
|
||||||
},
|
},
|
||||||
vote ({ commit, dispatch, state }, { title, link, linkID, isPositive, voterName }) {
|
vote ({ commit, state }, { title, link, linkID, isPositive, voterName }) {
|
||||||
console.log('vote on ' + link + ' | ' + linkID + ' (' + isPositive + ') by ' + voterName)
|
console.log('vote on ' + link + ' | ' + linkID + ' (' + isPositive + ') by ' + voterName)
|
||||||
if (isPositive) {
|
if (isPositive) {
|
||||||
commit('ADD_VOTE', {
|
commit('ADD_VOTE', {
|
||||||
@@ -72,13 +82,13 @@ const actions = {
|
|||||||
voterName: voterName
|
voterName: voterName
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
dispatch('rtc/broadcast', { message: state.roomStatus, type: 'status' }, { root: true })
|
send({ message: state.roomStatus, type: 'roomStatus' })
|
||||||
},
|
},
|
||||||
removePlay ({ commit, dispatch, state }, linkID) {
|
removePlay ({ commit, state }, linkID) {
|
||||||
commit('REMOVE_PLAY', linkID)
|
commit('REMOVE_PLAY', linkID)
|
||||||
dispatch('rtc/broadcast', { message: state.roomStatus, type: 'status' }, { root: true })
|
send({ message: state.roomStatus, type: 'roomStatus' })
|
||||||
},
|
},
|
||||||
setCurrent ({ commit, dispatch }, { playerStatus, timeCode, timeLength, title }) {
|
setCurrent ({ commit }, { playerStatus, timeCode, timeLength, title }) {
|
||||||
switch (playerStatus) {
|
switch (playerStatus) {
|
||||||
case 0:
|
case 0:
|
||||||
commit('CURRENT_END')
|
commit('CURRENT_END')
|
||||||
@@ -94,10 +104,10 @@ const actions = {
|
|||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dispatch('rtc/broadcast', { message: state.roomStatus, type: 'status' }, { root: true })
|
send({ message: state.roomStatus, type: 'roomStatus' })
|
||||||
},
|
},
|
||||||
leave ({ commit, dispatch }) {
|
leave ({ commit }) {
|
||||||
dispatch('rtc/leave', null, { root: true })
|
send({ type: 'roomLeave' })
|
||||||
commit('SET_ROOMSTATUS', {
|
commit('SET_ROOMSTATUS', {
|
||||||
roomName: '',
|
roomName: '',
|
||||||
roomCode: '',
|
roomCode: '',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const connection = new WebSocket('ws://localhost:8181/socket')
|
|||||||
// const connection = new WebSocket('wss://echo.websocket.org')
|
// const connection = new WebSocket('wss://echo.websocket.org')
|
||||||
// const connection = new WebSocket('wss://voozik.gltronic.ovh/socket')
|
// const connection = new WebSocket('wss://voozik.gltronic.ovh/socket')
|
||||||
|
|
||||||
// setTimeout(send({ type: 'alive' }), 5000)
|
setTimeout(send({ type: 'alive' }), 5000)
|
||||||
|
|
||||||
export default function createSignalPlugin () {
|
export default function createSignalPlugin () {
|
||||||
return store => {
|
return store => {
|
||||||
@@ -22,20 +22,6 @@ export default function createSignalPlugin () {
|
|||||||
var data = JSON.parse(message.data)
|
var data = JSON.parse(message.data)
|
||||||
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'offer':
|
|
||||||
console.log('offer from ' + data.name)
|
|
||||||
store.dispatch('rtc/offer', { offer: data.data, senderName: data.name })
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'answer':
|
|
||||||
console.log('answer from ' + data.name)
|
|
||||||
store.dispatch('rtc/answer', { answer: data.data, senderName: data.name })
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'candidate':
|
|
||||||
store.dispatch('rtc/candidate', { candidate: data.data, senderName: data.name })
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'leave':
|
case 'leave':
|
||||||
store.dispatch('rtc/leave')
|
store.dispatch('rtc/leave')
|
||||||
break
|
break
|
||||||
@@ -48,11 +34,11 @@ export default function createSignalPlugin () {
|
|||||||
store.dispatch('app/serverStatus', data)
|
store.dispatch('app/serverStatus', data)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'createRoom':
|
case 'roomCreate':
|
||||||
store.dispatch('app/createRoom', data.message)
|
store.dispatch('room/createRoom', data.message)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'connectRoom':
|
case 'roomConnect':
|
||||||
store.dispatch('app/connectRoom', data.message)
|
store.dispatch('app/connectRoom', data.message)
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -60,6 +46,22 @@ export default function createSignalPlugin () {
|
|||||||
store.dispatch('app/error', data.message)
|
store.dispatch('app/error', data.message)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 'roomStatus':
|
||||||
|
if (!store.state.room.admin) store.dispatch('room/setRoomStatus', data.message)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'roomSettings':
|
||||||
|
if (!store.state.room.admin) store.dispatch('room/setRoomSettings', data.message)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'roomVote':
|
||||||
|
store.dispatch('room/vote', { link: data.message.link, linkID: data.message.linkID, isPositive: data.message.isPositive, voterName: data.message.voterName })
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'roomUserCommand':
|
||||||
|
if (store.state.room.roomSettings.userControl) store.dispatch('room/setUserCommand', data.message)
|
||||||
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
<b-button type="is-primary" size="is-large" @click="makeRoomPrompt">Make a room</b-button>
|
<b-button type="is-primary" size="is-large" @click="makeRoomPrompt">Make a room</b-button>
|
||||||
<hr>
|
<hr>
|
||||||
<b-button @click="changeName">Change name</b-button>
|
<b-button @click="changeName">Change name</b-button>
|
||||||
|
<hr>
|
||||||
|
<p>V2.0</p>
|
||||||
<b-modal :active.sync="isQRModalActive" has-modal-card trap-focus>
|
<b-modal :active.sync="isQRModalActive" has-modal-card trap-focus>
|
||||||
<QRReader v-on:get-code="connectToRoom"/>
|
<QRReader v-on:get-code="connectToRoom"/>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
@@ -54,7 +56,7 @@ export default {
|
|||||||
return this.$store.state.app.loginSuccess
|
return this.$store.state.app.loginSuccess
|
||||||
},
|
},
|
||||||
userName () {
|
userName () {
|
||||||
return this.$store.state.rtc.name
|
return this.$store.state.app.name
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -101,7 +103,7 @@ export default {
|
|||||||
type: 'login',
|
type: 'login',
|
||||||
name: name
|
name: name
|
||||||
})
|
})
|
||||||
this.$store.dispatch('rtc/setName', name)
|
this.$store.dispatch('app/setName', name)
|
||||||
},
|
},
|
||||||
makeRoomPrompt () {
|
makeRoomPrompt () {
|
||||||
this.$buefy.dialog.prompt({
|
this.$buefy.dialog.prompt({
|
||||||
@@ -119,8 +121,7 @@ export default {
|
|||||||
},
|
},
|
||||||
makeRoom (name) {
|
makeRoom (name) {
|
||||||
send({
|
send({
|
||||||
type: 'createRoom',
|
type: 'roomCreate'
|
||||||
name: name
|
|
||||||
})
|
})
|
||||||
this.$store.dispatch('room/setRoomName', name)
|
this.$store.dispatch('room/setRoomName', name)
|
||||||
},
|
},
|
||||||
@@ -140,8 +141,8 @@ export default {
|
|||||||
},
|
},
|
||||||
connectToRoom (code) {
|
connectToRoom (code) {
|
||||||
send({
|
send({
|
||||||
type: 'connectRoom',
|
type: 'roomConnect',
|
||||||
name: code
|
code: code
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
changeName () {
|
changeName () {
|
||||||
|
|||||||
@@ -7,10 +7,17 @@ import org.springframework.web.socket.WebSocketSession;
|
|||||||
|
|
||||||
public interface IRoomManager {
|
public interface IRoomManager {
|
||||||
public void login(WebSocketSession session, String name) throws InterruptedException, IOException;
|
public void login(WebSocketSession session, String name) throws InterruptedException, IOException;
|
||||||
public void leave(WebSocketSession session);
|
public void leave(WebSocketSession session) throws InterruptedException, IOException;
|
||||||
|
|
||||||
public void createRoom(WebSocketSession session) throws InterruptedException, IOException;
|
public void createRoom(WebSocketSession session) throws InterruptedException, IOException;
|
||||||
public void connectRoom(WebSocketSession session, String roomName) throws InterruptedException, IOException;
|
public void connectRoom(WebSocketSession session, String roomCode) throws InterruptedException, IOException;
|
||||||
public void followRTC(WebSocketSession session, TextMessage message) throws InterruptedException, IOException;
|
public void leaveRoom(WebSocketSession session) throws InterruptedException, IOException;
|
||||||
|
|
||||||
|
public void setRoomStatus(WebSocketSession session, TextMessage message) throws InterruptedException, IOException;
|
||||||
|
public void setRoomSettings(WebSocketSession session, TextMessage message) throws InterruptedException, IOException;
|
||||||
|
|
||||||
|
public void forwardRoomMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException;
|
||||||
|
|
||||||
public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException;
|
public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException;
|
||||||
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException;
|
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package gltronic.voozik.business;
|
package gltronic.voozik.business;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@@ -8,110 +10,246 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
import gltronic.voozik.model.BiMap;
|
import gltronic.voozik.model.VRoom;
|
||||||
|
import gltronic.voozik.model.VUser;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class RoomManager implements IRoomManager{
|
public class RoomManager implements IRoomManager {
|
||||||
private volatile BiMap<String, WebSocketSession> users = new BiMap<String, WebSocketSession>();
|
private volatile ArrayList<VUser> users = new ArrayList<VUser>();
|
||||||
private volatile BiMap<String, String> rooms = new BiMap<String, String>();
|
private volatile ArrayList<VRoom> rooms = new ArrayList<VRoom>();
|
||||||
|
|
||||||
public void login(WebSocketSession session, String name) throws InterruptedException, IOException {
|
public void login(WebSocketSession session, String name) throws InterruptedException, IOException {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
sendMessage(session, "error", "bad command command");
|
sendMessage(session, "error", "bad command command");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (users.containsKey(name)) {
|
|
||||||
|
if (users.stream().anyMatch(user -> user.getSession().equals(session))) {
|
||||||
sendMessage(session, "login", "false");
|
sendMessage(session, "login", "false");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
users.put(name, session);
|
if (users.stream().anyMatch(user -> user.getName().equals(name))) {
|
||||||
|
sendMessage(session, "login", "false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VUser user = new VUser();
|
||||||
|
user.setName(name);
|
||||||
|
user.setSession(session);
|
||||||
|
|
||||||
|
users.add(user);
|
||||||
|
|
||||||
sendMessage(session, "login", "true");
|
sendMessage(session, "login", "true");
|
||||||
sendServerInfos(session);
|
sendServerInfos(session);
|
||||||
|
|
||||||
System.err.println("[ROOM] Logged "+name);
|
System.err.println("[ROOM] Logged " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leave(WebSocketSession session) {
|
public void leave(WebSocketSession session) throws InterruptedException, IOException {
|
||||||
String name = users.getKey(session);
|
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst();
|
||||||
users.removeValue(session);
|
|
||||||
if(rooms.containsValue(name)) rooms.removeValue(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createRoom(WebSocketSession session) throws InterruptedException, IOException {
|
if (ouser.isEmpty()) {
|
||||||
if (!users.containsValue(session)) {
|
|
||||||
sendMessage(session, "error", "need login");
|
sendMessage(session, "error", "need login");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String userName = users.getKey(session);
|
|
||||||
if (rooms.containsKey(userName)) {
|
VUser user = ouser.get();
|
||||||
sendMessage(session, "error", "no multiple room");
|
|
||||||
|
users.remove(user);
|
||||||
|
Optional<VRoom> oroom = rooms.stream().filter(room -> room.getUsers().contains(user)).findFirst();
|
||||||
|
|
||||||
|
if (oroom.isPresent()) {
|
||||||
|
oroom.get().getUsers().remove(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createRoom(WebSocketSession session) throws InterruptedException, IOException {
|
||||||
|
if (!users.stream().anyMatch(user -> user.getSession().equals(session))) {
|
||||||
|
sendMessage(session, "error", "need login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VUser user = users.stream().filter(suser -> suser.getSession().equals(session)).findFirst().get();
|
||||||
|
|
||||||
|
if (user.getRoom() != null) {
|
||||||
|
sendMessage(session, "error", "no already in room");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
String roomName = Integer.toString(random.nextInt(9999));
|
String roomCode = Integer.toString(random.nextInt(9999));
|
||||||
|
while (roomCode.length() < 4)
|
||||||
|
roomCode += 0 + roomCode;
|
||||||
|
|
||||||
while (roomName.length() < 4) roomName += 0 + roomName;
|
VRoom room = new VRoom();
|
||||||
|
|
||||||
rooms.put(roomName, userName);
|
room.setAdmin(user);
|
||||||
sendMessage(session, "createRoom", roomName);
|
room.setCode(roomCode);
|
||||||
|
room.setPublic(false);
|
||||||
|
room.setUsers(new ArrayList<VUser>());
|
||||||
|
|
||||||
System.err.println("[ROOM] Created room "+roomName+" by "+userName);
|
rooms.add(room);
|
||||||
|
user.setRoom(room);
|
||||||
|
|
||||||
|
sendMessage(session, "roomCreate", roomCode);
|
||||||
|
|
||||||
|
System.err.println("[ROOM] Created room " + roomCode + " by " + user.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectRoom(WebSocketSession session, String roomName) throws InterruptedException, IOException {
|
public void connectRoom(WebSocketSession session, String roomCode) throws InterruptedException, IOException {
|
||||||
if (roomName == null) {
|
if (roomCode == null) {
|
||||||
sendMessage(session, "error", "bad command command");
|
sendMessage(session, "error", "bad command command");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!users.containsValue(session)) {
|
if (!users.stream().anyMatch(user -> user.getSession().equals(session))) {
|
||||||
sendMessage(session, "error", "need login");
|
sendMessage(session, "error", "need login");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!rooms.containsKey(roomName)) {
|
|
||||||
|
Optional<VRoom> oroom = rooms.stream().filter(room -> room.getCode().equals(roomCode)).findFirst();
|
||||||
|
if (oroom.isEmpty()) {
|
||||||
sendMessage(session, "error", "no room");
|
sendMessage(session, "error", "no room");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String roomAdmin = rooms.get(roomName);
|
VRoom room = oroom.get();
|
||||||
sendMessage(session, "connectRoom", roomAdmin);
|
VUser user = users.stream().filter(suser -> suser.getSession().equals(session)).findFirst().get();
|
||||||
|
|
||||||
String userName = users.getKey(session);
|
room.getUsers().add(user);
|
||||||
System.err.println("[ROOM] Connection to room "+roomName+" ("+roomAdmin+") by "+userName);
|
user.setRoom(room);
|
||||||
|
|
||||||
|
sendMessage(session, "roomConnect", "true");
|
||||||
|
forwardMessage(session, "roomStatus", room.getRoomStatus());
|
||||||
|
forwardMessage(session, "roomSettings", room.getRoomSettings());
|
||||||
|
|
||||||
|
System.err
|
||||||
|
.println("[ROOM] Connection to room " + roomCode + " (" + room.getAdmin().getName() + ") by " + user.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void leaveRoom(WebSocketSession session) throws InterruptedException, IOException {
|
||||||
|
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst();
|
||||||
|
|
||||||
|
if (ouser.isEmpty()) {
|
||||||
|
sendMessage(session, "error", "need login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VUser user = ouser.get();
|
||||||
|
|
||||||
|
if (user.getRoom() == null) {
|
||||||
|
sendMessage(session, "error", "no room");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.getRoom().getUsers().remove(user);
|
||||||
|
user.setRoom(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRoomStatus(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
|
||||||
|
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst();
|
||||||
|
|
||||||
|
if (ouser.isEmpty()) {
|
||||||
|
sendMessage(session, "error", "need login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VUser user = ouser.get();
|
||||||
|
|
||||||
|
if (user.getRoom() == null) {
|
||||||
|
sendMessage(session, "error", "no room");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.getRoom().getAdmin().equals(user)) {
|
||||||
|
sendMessage(session, "error", "not admin");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void followRTC(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
|
|
||||||
String payload = message.getPayload();
|
String payload = message.getPayload();
|
||||||
JSONObject jsonObject = new JSONObject(payload);
|
JSONObject jsonObject = new JSONObject(payload);
|
||||||
String target = (String) jsonObject.get("target");
|
|
||||||
|
|
||||||
if (target == null) {
|
user.getRoom().setRoomStatus((JSONObject) jsonObject.get("message"));
|
||||||
sendMessage(session, "error", "no target");
|
broadcast(user.getRoom(), "roomStatus", user.getRoom().getRoomStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRoomSettings(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
|
||||||
|
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst();
|
||||||
|
|
||||||
|
if (ouser.isEmpty()) {
|
||||||
|
sendMessage(session, "error", "need login");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketSession targetSession = users.get(target);
|
VUser user = ouser.get();
|
||||||
|
|
||||||
if (targetSession == null) {
|
if (user.getRoom() == null) {
|
||||||
sendMessage(session, "error", "unknow target");
|
sendMessage(session, "error", "no room");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.err.println("[ROOM] Foward RTC message");
|
if (!user.getRoom().getAdmin().equals(user)) {
|
||||||
followMessage(targetSession, message);
|
sendMessage(session, "error", "not admin");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void followMessage (WebSocketSession session, TextMessage message) throws IOException {
|
String payload = message.getPayload();
|
||||||
session.sendMessage(message);
|
JSONObject jsonObject = new JSONObject(payload);
|
||||||
|
|
||||||
|
user.getRoom().setRoomSettings((JSONObject) jsonObject.get("message"));
|
||||||
|
broadcast(user.getRoom(), "roomSettings", user.getRoom().getRoomSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException {
|
public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException {
|
||||||
session.sendMessage(new TextMessage("{\"type\":\""+type+"\",\"message\":\""+message+"\"}"));
|
session.sendMessage(new TextMessage("{\"type\":\"" + type + "\",\"message\": \"" + message.toString() + "\" }"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forwardMessage(WebSocketSession session, String type, JSONObject message) throws InterruptedException, IOException {
|
||||||
|
session.sendMessage(new TextMessage("{\"type\":\"" + type + "\",\"message\": " + message.toString() + " }"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void broadcast(VRoom room, String type, JSONObject message) {
|
||||||
|
room.getUsers().forEach(user -> {
|
||||||
|
try {
|
||||||
|
forwardMessage(user.getSession(), type, message);
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException {
|
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException {
|
||||||
session.sendMessage(new TextMessage("{\"type\":\"serverInfos\",\"userCount\":\""+users.size()+"\",\"roomCount\":\""+rooms.size()+"\"}"));
|
session.sendMessage(new TextMessage(
|
||||||
|
"{\"type\":\"serverInfos\",\"userCount\":\"" + users.size() + "\",\"roomCount\":\"" + rooms.size() + "\"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forwardRoomMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
|
||||||
|
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst();
|
||||||
|
|
||||||
|
if (ouser.isEmpty()) {
|
||||||
|
sendMessage(session, "error", "need login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VUser user = ouser.get();
|
||||||
|
|
||||||
|
if (user.getRoom() == null) {
|
||||||
|
sendMessage(session, "error", "no room");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String payload = message.getPayload();
|
||||||
|
JSONObject jsonObject = new JSONObject(payload);
|
||||||
|
String type = (String) jsonObject.get("type");
|
||||||
|
JSONObject data = (JSONObject) jsonObject.get("message");
|
||||||
|
|
||||||
|
if (user.getRoom().getAdmin().equals(user)) broadcast(user.getRoom(), type, data);
|
||||||
|
else forwardMessage(user.getRoom().getAdmin().getSession(), type, data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
21
server/src/main/java/gltronic/voozik/model/VRoom.java
Normal file
21
server/src/main/java/gltronic/voozik/model/VRoom.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package gltronic.voozik.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class VRoom {
|
||||||
|
private String code;
|
||||||
|
private boolean isPublic;
|
||||||
|
private JSONObject roomStatus;
|
||||||
|
private JSONObject roomSettings;
|
||||||
|
private VUser admin;
|
||||||
|
private List<VUser> users;
|
||||||
|
}
|
||||||
16
server/src/main/java/gltronic/voozik/model/VUser.java
Normal file
16
server/src/main/java/gltronic/voozik/model/VUser.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package gltronic.voozik.model;
|
||||||
|
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class VUser {
|
||||||
|
private String name;
|
||||||
|
private WebSocketSession session;
|
||||||
|
private VRoom room;
|
||||||
|
}
|
||||||
@@ -22,7 +22,8 @@ public class SocketHandler extends TextWebSocketHandler {
|
|||||||
IRoomManager roomManager;
|
IRoomManager roomManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleTextMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
|
public void handleTextMessage(WebSocketSession session, TextMessage message)
|
||||||
|
throws InterruptedException, IOException {
|
||||||
System.err.println("[WS] message :" + message.getPayload());
|
System.err.println("[WS] message :" + message.getPayload());
|
||||||
|
|
||||||
String payload = message.getPayload();
|
String payload = message.getPayload();
|
||||||
@@ -36,19 +37,27 @@ public class SocketHandler extends TextWebSocketHandler {
|
|||||||
case "login":
|
case "login":
|
||||||
roomManager.login(session, (String) jsonObject.get("name"));
|
roomManager.login(session, (String) jsonObject.get("name"));
|
||||||
break;
|
break;
|
||||||
case "createRoom":
|
|
||||||
roomManager.createRoom(session);
|
|
||||||
break;
|
|
||||||
case "connectRoom":
|
|
||||||
roomManager.connectRoom(session, (String) jsonObject.get("name"));
|
|
||||||
break;
|
|
||||||
case "leave":
|
case "leave":
|
||||||
roomManager.leave(session);
|
roomManager.leave(session);
|
||||||
break;
|
break;
|
||||||
case "offer":
|
case "roomCreate":
|
||||||
case "answer":
|
roomManager.createRoom(session);
|
||||||
case "candidate":
|
break;
|
||||||
roomManager.followRTC(session, message);
|
case "roomConnect":
|
||||||
|
roomManager.connectRoom(session, (String) jsonObject.get("code"));
|
||||||
|
break;
|
||||||
|
case "roomLeave":
|
||||||
|
roomManager.leaveRoom(session);
|
||||||
|
break;
|
||||||
|
case "roomStatus":
|
||||||
|
roomManager.setRoomStatus(session, message);
|
||||||
|
break;
|
||||||
|
case "roomSettings":
|
||||||
|
roomManager.setRoomSettings(session, message);
|
||||||
|
break;
|
||||||
|
case "roomVote":
|
||||||
|
case "roomUserCommand":
|
||||||
|
roomManager.forwardRoomMessage(session, message);
|
||||||
break;
|
break;
|
||||||
case "search":
|
case "search":
|
||||||
break;
|
break;
|
||||||
@@ -66,9 +75,13 @@ public class SocketHandler extends TextWebSocketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus){
|
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
|
||||||
System.err.println("[WS] connection closed");
|
System.err.println("[WS] connection closed");
|
||||||
sessions.remove(session);
|
sessions.remove(session);
|
||||||
|
try {
|
||||||
roomManager.leave(session);
|
roomManager.leave(session);
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user