+
+
+
+
+
+
+ {{ localParticipant.displayName }}
+
+
+
+
+
+
+
diff --git a/src/components/pages/Conference/CscConferenceParticipants.vue b/src/components/pages/Conference/CscConferenceParticipants.vue
new file mode 100644
index 00000000..355aaff5
--- /dev/null
+++ b/src/components/pages/Conference/CscConferenceParticipants.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
diff --git a/src/components/pages/Conference/CscConferenceRemoteParticipant.vue b/src/components/pages/Conference/CscConferenceRemoteParticipant.vue
new file mode 100644
index 00000000..e2799de3
--- /dev/null
+++ b/src/components/pages/Conference/CscConferenceRemoteParticipant.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+ {{remoteParticipant(participantId).displayName}}
+
+
+
+
+
+
+
diff --git a/src/plugins/conference.js b/src/plugins/conference.js
index 2cf7f506..780c8164 100644
--- a/src/plugins/conference.js
+++ b/src/plugins/conference.js
@@ -47,6 +47,7 @@ export class ConferencePlugin {
return new Promise((resolve, reject)=>{
options.localMediaStream = this.getLocalMediaStream();
this.getNetwork().joinConference(options).then((conference)=>{
+ this.conference = conference;
resolve(conference);
}).catch((err)=>{
reject(err);
@@ -146,12 +147,13 @@ export class ConferencePlugin {
}
getLocalParticipant() {
- this.conference.getLocalParticipant();
+ return this.conference.getLocalParticipant();
}
getRemoteParticipant(id) {
- this.conference.getRemoteParticipant(id);
+ return this.conference.getRemoteParticipant(id);
}
+
}
export default {
diff --git a/src/statics/avatar.png b/src/statics/avatar.png
new file mode 100644
index 00000000..a1a75249
Binary files /dev/null and b/src/statics/avatar.png differ
diff --git a/src/store/conference.js b/src/store/conference.js
index c6ce2768..f1ab4e18 100644
--- a/src/store/conference.js
+++ b/src/store/conference.js
@@ -25,7 +25,8 @@ export default {
joinError: null,
leaveState: RequestState.initiated,
leaveError: null,
- participants: []
+ participants: [],
+ remoteMediaStreams: []
},
getters: {
username(state, getters, rootState, rootGetters) {
@@ -78,7 +79,33 @@ export default {
hasLocalMediaStream(state) {
return (state.localMediaState === RequestState.succeeded ||
state.localMediaState === RequestState.requesting) && Vue.$conference.hasLocalMediaStream();
+ },
+ localParticipant(state) {
+ if(state.joinState === RequestState.succeeded){
+ return Vue.$conference.getLocalParticipant();
+ }
+ },
+ remoteParticipant: () => (participantId) => {
+ return Vue.$conference.getRemoteParticipant(participantId);
+ },
+ remoteMediaStream: (state) => (participantId) => {
+ if(state.remoteMediaStreams.includes(participantId)){
+ const participant = Vue.$conference.getRemoteParticipant(participantId);
+ return participant.mediaStream ? participant.mediaStream.getStream() : null;
+ }
+ return null;
+
+ },
+ participantsList(state) {
+ return state.participants;
+ },
+ remoteMediaStreams(state) {
+ return state.remoteMediaStreams;
+ },
+ hasRemoteMediaStream: (state) => (participantId) => {
+ return state.remoteMediaStreams.includes(participantId)
}
+
},
mutations: {
enableConferencing(state) {
@@ -126,6 +153,20 @@ export default {
state.microphoneEnabled = false;
state.screenEnabled = false;
},
+ addRemoteMedia(state, participantId) {
+ if(state.remoteMediaStreams.includes(participantId)){
+ state.remoteMediaStreams = state.remoteMediaStreams.filter(($participant)=>{
+ return participantId !== $participant;
+ });
+ }
+ state.remoteMediaStreams.push(participantId);
+
+ },
+ removeRemoteMedia(state, participant) {
+ state.remoteMediaStreams = state.remoteMediaStreams.filter(($participant)=>{
+ return participant !== $participant;
+ });
+ },
joinRequesting(state) {
state.joinState = RequestState.requesting;
state.joinError = null;
@@ -133,6 +174,7 @@ export default {
joinSucceeded(state) {
state.joinState = RequestState.succeeded;
state.joinError = null;
+ state.leaveState = null;
},
joinFailed(state, error) {
state.joinState = RequestState.failed;
@@ -141,6 +183,7 @@ export default {
leaveRequesting(state) {
state.leaveState = RequestState.requesting;
state.leaveError = null;
+ state.joinState = null;
},
leaveSucceeded(state) {
state.leaveState = RequestState.succeeded;
@@ -153,12 +196,16 @@ export default {
state.leaveError = error;
},
participantJoined(state, participant) {
- state.participants.push(participant.getId());
-
+ if(state.participants.includes(participant.getId())){
+ state.participants = state.participants.filter(($participant)=>{
+ return participant.getId() !== $participant;
+ });
+ }
+ state.participants.push(participant.getId())
},
participantLeft(state, participant) {
state.participants = state.participants.filter(($participant)=>{
- return participant.getId() !== $participant.getId();
+ return participant.getId() !== $participant;
});
}
},
diff --git a/src/store/index.js b/src/store/index.js
index d1cf3dbd..e17a247c 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -121,6 +121,19 @@ export const store = new Vuex.Store({
store.commit('conference/leftSuccessfully', conference);
}).onConferenceParticipantJoined((participant)=>{
store.commit('conference/participantJoined', participant);
+ participant.onMediaStream(()=>{
+ store.commit('conference/addRemoteMedia', participant.id);
+ })
+ participant.onMediaStarted(()=>{
+ store.commit('conference/addRemoteMedia', participant.id);
+ })
+ participant.onMediaRecovered(()=>{
+ store.commit('conference/addRemoteMedia', participant.id);
+ })
+ participant.onMediaEnded(()=>{
+ store.commit('conference/removeRemoteMedia', participant.id);
+ })
+
}).onConferenceParticipantLeft((participant)=>{
store.commit('conference/participantLeft', participant);
}).onConferenceEvent((event)=>{
diff --git a/src/themes/app.common.styl b/src/themes/app.common.styl
index bad4384e..4b6e057c 100644
--- a/src/themes/app.common.styl
+++ b/src/themes/app.common.styl
@@ -247,3 +247,27 @@ input.q-input-target
i
margin 0
+.csc-conf-participant-cont
+ margin-bottom 20px
+ width 115px
+ height 115px
+ background white
+ .csc-conf-participants-item-title
+ position relative
+ background white
+ bottom 24px
+ text-align center
+ padding 0
+ background rgba(0, 0, 0, 0.5)
+ .q-card-title
+ color $primary
+ font-size 12px
+ line-height 24px
+ .csc-avatar-cont
+ height 100%
+ top 6px
+ .csc-media-cont
+ height 100% !important
+ width 100% !important
+ video
+ height: 100%;