diff --git a/docs/capabilities.md b/docs/capabilities.md index 7fe8e69bd8f..67c8fb5c8a9 100644 --- a/docs/capabilities.md +++ b/docs/capabilities.md @@ -56,8 +56,9 @@ title: Capabilities * `sip-support` - Whether conversations API v3 exists and SIP can be configured and enabled by moderators. The conversations API will come with some new values `sipEnabled` which signals whether this conversation has SIP configured as well as `canEnableSIP` to see if a user can enable it. When it is enabled `attendeePin` will contain the unique dial-in code for this user. ## 11.0 -* `config => previews => max-gif-size` - Maximum size in bytes below which a GIF can be embedded directly in the page at render time. Bigger files will be rendered statically using the preview endpoint instead. Can be set with `occ config:app:set spreed max-gif-size --value=X` where X is the new value in bytes. Defaults to 3 MB. * `chat-read-status` - On conversation API v3 and the chat API the last common read message is exposed which can be used to update the "read status" flag of own chat messages. The info should be shown only when the user also shares their read status. The user's value can be found in `config => chat => read-privacy`. -* `config => chat => read-privacy` - See `chat-read-status` -* `phonebook-search` - Is present when the server has the endpoint to search for phone numbers to find matches in the accounts list * `listable-rooms` - Conversations can searched for even when not joined. A "listable" attribute set on rooms defines the scope of who can find it. +* `phonebook-search` - Is present when the server has the endpoint to search for phone numbers to find matches in the accounts list +* `raise-hand` - Participants can raise or lower hand, the state change is sent through signaling messages. +* `config => chat => read-privacy` - See `chat-read-status` +* `config => previews => max-gif-size` - Maximum size in bytes below which a GIF can be embedded directly in the page at render time. Bigger files will be rendered statically using the preview endpoint instead. Can be set with `occ config:app:set spreed max-gif-size --value=X` where X is the new value in bytes. Defaults to 3 MB. diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 0835a5cdb84..b9faad6cd31 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -84,6 +84,7 @@ public function getCapabilities(): array { 'sip-support', 'chat-read-status', 'phonebook-search', + 'raise-hand', ], 'config' => [ 'attachments' => [ diff --git a/src/components/CallView/CallView.vue b/src/components/CallView/CallView.vue index 2958d82dc7a..66dd526296b 100644 --- a/src/components/CallView/CallView.vue +++ b/src/components/CallView/CallView.vue @@ -144,6 +144,7 @@ import Grid from './Grid/Grid' import { localMediaModel, localCallParticipantModel, callParticipantCollection } from '../../utils/webrtc/index' import { fetchPeers } from '../../services/callsService' +import { showMessage } from '@nextcloud/dialogs' import LocalMediaControls from './shared/LocalMediaControls' import EmptyCallView from './shared/EmptyCallView' import Video from './shared/Video' @@ -182,6 +183,7 @@ export default { localMediaModel: localMediaModel, localCallParticipantModel: localCallParticipantModel, sharedDatas: {}, + raisedHandUnwatchers: {}, speakingUnwatchers: {}, screenUnwatchers: {}, speakers: [], @@ -401,6 +403,11 @@ export default { // Not reactive, but not a problem delete this.screenUnwatchers[removedModelId] + this.raisedHandUnwatchers[removedModelId]() + // Not reactive, but not a problem + delete this.raisedHandUnwatchers[removedModelId] + this.$store.dispatch('setParticipantHandRaised', { peerId: removedModelId, raised: false }) + const index = this.speakers.findIndex(speaker => speaker.id === removedModelId) this.speakers.splice(index, 1) @@ -434,6 +441,13 @@ export default { }, function(screen) { this._setScreenAvailable(addedModel.attributes.peerId, screen) }) + + // Not reactive, but not a problem + this.raisedHandUnwatchers[addedModel.attributes.peerId] = this.$watch(function() { + return addedModel.attributes.raisedHand + }, function(raisedHand) { + this._handleParticipantRaisedHand(addedModel, raisedHand) + }) }) }, @@ -467,6 +481,23 @@ export default { } }, + _handleParticipantRaisedHand(callParticipantModel, raisedHand) { + const nickName = callParticipantModel.attributes.name || callParticipantModel.attributes.userId + // sometimes the nick name is not available yet... + if (nickName) { + if (raisedHand) { + showMessage(t('spreed', 'Participant {nickName} raised their hand.', { nickName: nickName })) + } + } else { + if (raisedHand) { + showMessage(t('spreed', 'A participant raised their hand.')) + } + } + + // update in callViewStore + this.$store.dispatch('setParticipantHandRaised', { peerId: callParticipantModel.attributes.peerId, raised: raisedHand }) + }, + _setScreenAvailable(id, screen) { if (screen) { this.screens.unshift(id) diff --git a/src/components/CallView/shared/LocalMediaControls.vue b/src/components/CallView/shared/LocalMediaControls.vue index ae41e092f6d..29968142915 100644 --- a/src/components/CallView/shared/LocalMediaControls.vue +++ b/src/components/CallView/shared/LocalMediaControls.vue @@ -17,7 +17,6 @@ - along with this program. If not, see . - --> -