Skip to content

Commit

Permalink
MVP - check consent before joining the call and send to server
Browse files Browse the repository at this point in the history
Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
  • Loading branch information
Antreesy committed Oct 5, 2023
1 parent 8a46f05 commit 4a15b7c
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 12 deletions.
18 changes: 18 additions & 0 deletions src/components/MediaSettings/MediaSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@
type="warning">
<p>{{ t('spreed', 'The call is being recorded.') }}</p>
</NcNoteCard>
<!-- Recording consent warning -->
<NcNoteCard v-if="isRecordingConsentRequired" type="warning">
<p>{{ t('spreed', 'Your consent to be recorded is required before joining the call.') }}</p>
<NcCheckboxRadioSwitch :checked.sync="recordingConsentGiven">
{{ t('spreed', 'Give a consent to be recorded') }}
</NcCheckboxRadioSwitch>
</NcNoteCard>

<!-- buttons bar at the bottom -->
<div class="media-settings__call-buttons">
Expand Down Expand Up @@ -164,6 +171,8 @@
<CallButton v-if="!isInCall"
class="call-button"
:force-join-call="true"
:disabled="isRecordingConsentRequired && !recordingConsentGiven"
:recording-consent-given.sync="recordingConsentGiven"
:silent-call="silentCall" />
<NcButton v-else-if="showUpdateChangesButton" @click="closeModalAndApplySettings">
{{ t('spreed', 'Apply settings') }}
Expand All @@ -182,6 +191,7 @@ import VideoIcon from 'vue-material-design-icons/Video.vue'
import VideoOff from 'vue-material-design-icons/VideoOff.vue'

import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { getCapabilities } from '@nextcloud/capabilities'

import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
Expand All @@ -206,6 +216,8 @@ import BrowserStorage from '../../services/BrowserStorage.js'
import { useGuestNameStore } from '../../stores/guestName.js'
import { localMediaModel } from '../../utils/webrtc/index.js'

const recordingConsent = getCapabilities()?.spreed?.config?.call?.['recording-consent']

export default {
name: 'MediaSettings',

Expand Down Expand Up @@ -255,6 +267,7 @@ export default {
deviceIdChanged: false,
audioDeviceStateChanged: false,
videoDeviceStateChanged: false,
recordingConsentGiven: false,
}
},

Expand Down Expand Up @@ -322,6 +335,11 @@ export default {
|| this.conversation.callRecording === CALL.RECORDING.AUDIO
},

isRecordingConsentRequired() {
return recordingConsent === CALL.RECORDING_CONSENT.REQUIRED
|| (recordingConsent === CALL.RECORDING_CONSENT.OPTIONAL && this.conversation.recordingConsent === CALL.RECORDING_CONSENT.REQUIRED)
},

showSilentCallOption() {
return !(this.hasCall && !this.isInLobby)
},
Expand Down
15 changes: 13 additions & 2 deletions src/components/TopBar/CallButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ export default {
],

props: {
disabled: {
type: Boolean,
default: false,
},

/**
* Skips the media settings dialog and joins or starts the call
* upon clicking the button
Expand All @@ -143,6 +148,11 @@ export default {
type: Boolean,
default: false,
},

recordingConsentGiven: {
type: Boolean,
default: false,
},
},

setup() {
Expand Down Expand Up @@ -197,8 +207,8 @@ export default {
},

startCallButtonDisabled() {
return (!this.conversation.canStartCall
&& !this.hasCall)
return this.disabled
|| (!this.conversation.canStartCall && !this.hasCall)
|| this.isInLobby
|| this.conversation.readOnly
|| this.isNextcloudTalkHashDirty
Expand Down Expand Up @@ -305,6 +315,7 @@ export default {
participantIdentifier: this.$store.getters.getParticipantIdentifier(),
flags,
silent: this.hasCall ? true : this.silentCall,
recordingConsent: this.recordingConsentGiven,
})
this.loading = false
},
Expand Down
5 changes: 3 additions & 2 deletions src/services/callsService.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ import {
* @param {number} flags The available PARTICIPANT.CALL_FLAG for this participants
* @param {boolean} silent Whether the call should trigger a notifications and
* sound for other participants or not
* @param {boolean} recordingConsent Whether the participant gave his consent to be recorded
* @return {number} The actual flags based on the available media
*/
const joinCall = async function(token, flags, silent) {
const joinCall = async function(token, flags, silent, recordingConsent) {
try {
return await signalingJoinCall(token, flags, silent)
return await signalingJoinCall(token, flags, silent, recordingConsent)
} catch (error) {
console.debug('Error while joining call: ', error)
}
Expand Down
4 changes: 2 additions & 2 deletions src/store/participantsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ const actions = {
return false
},

async joinCall({ commit, getters }, { token, participantIdentifier, flags, silent }) {
async joinCall({ commit, getters }, { token, participantIdentifier, flags, silent, recordingConsent }) {
if (!participantIdentifier?.sessionId) {
console.error('Trying to join call without sessionId')
return
Expand All @@ -645,7 +645,7 @@ const actions = {
flags,
})

const actualFlags = await joinCall(token, flags, silent)
const actualFlags = await joinCall(token, flags, silent, recordingConsent)

const updatedData = {
inCall: actualFlags,
Expand Down
3 changes: 2 additions & 1 deletion src/utils/signaling.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,14 @@ Signaling.Base.prototype._joinCallSuccess = function(/* token */) {
// Override in subclasses if necessary.
}

Signaling.Base.prototype.joinCall = function(token, flags, silent) {
Signaling.Base.prototype.joinCall = function(token, flags, silent, recordingConsent) {
return new Promise((resolve, reject) => {
this._trigger('beforeJoinCall', [token])

axios.post(generateOcsUrl('apps/spreed/api/v4/call/{token}', { token }), {
flags,
silent,
recordingConsent,
})
.then(function() {
this.currentCallToken = token
Expand Down
12 changes: 7 additions & 5 deletions src/utils/webrtc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ let failedToStartCall = null
* @param {object} configuration Media to connect with
* @param {boolean} silent Whether the call should trigger a notifications and
* sound for other participants or not
* @param {boolean} recordingConsent Whether the participant gave his consent to be recorded
*/
function startCall(signaling, configuration, silent) {
function startCall(signaling, configuration, silent, recordingConsent) {
let flags = PARTICIPANT.CALL_FLAG.IN_CALL
if (configuration) {
if (configuration.audio) {
Expand All @@ -164,7 +165,7 @@ function startCall(signaling, configuration, silent) {
}
}

signaling.joinCall(pendingJoinCallToken, flags, silent).then(() => {
signaling.joinCall(pendingJoinCallToken, flags, silent, recordingConsent).then(() => {
startedCall(flags)
}).catch(error => {
failedToStartCall(error)
Expand Down Expand Up @@ -209,10 +210,11 @@ async function signalingJoinConversation(token, sessionId) {
* @param {number} flags Bitwise combination of PARTICIPANT.CALL_FLAG
* @param {boolean} silent Whether the call should trigger a notifications and
* sound for other participants or not
* @param {boolean} recordingConsent Whether the participant gave his consent to be recorded
* @return {Promise<void>} Resolved with the actual flags based on the
* available media
*/
async function signalingJoinCall(token, flags, silent) {
async function signalingJoinCall(token, flags, silent, recordingConsent) {
if (tokensInSignaling[token]) {
pendingJoinCallToken = token

Expand Down Expand Up @@ -269,13 +271,13 @@ async function signalingJoinCall(token, flags, silent) {
webRtc.off('localMediaStarted', startCallOnceLocalMediaStarted)
webRtc.off('localMediaError', startCallOnceLocalMediaError)

startCall(_signaling, configuration, silent)
startCall(_signaling, configuration, silent, recordingConsent)
}
const startCallOnceLocalMediaError = () => {
webRtc.off('localMediaStarted', startCallOnceLocalMediaStarted)
webRtc.off('localMediaError', startCallOnceLocalMediaError)

startCall(_signaling, null, silent)
startCall(_signaling, null, silent, recordingConsent)
}

// ".once" can not be used, as both handlers need to be removed when
Expand Down

0 comments on commit 4a15b7c

Please sign in to comment.