Browse Source

Merge pull request #5773 from nextcloud/techdebt/noid/node14-npm7

Techdebt/noid/node14 npm7
pull/5320/head
marco 4 years ago
committed by GitHub
parent
commit
86a5fbfd4e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .eslintrc.js
  2. 15
      .github/workflows/jest.yml
  3. 30
      .github/workflows/lint.yml
  4. 14
      babel.config.js
  5. 2
      lib/AppInfo/Application.php
  6. 2
      lib/Dashboard/TalkWidget.php
  7. 4
      lib/Deck/DeckPluginLoader.php
  8. 2
      lib/Flow/RegisterOperationsListener.php
  9. 35573
      package-lock.json
  10. 43
      package.json
  11. 4
      src/FilesSidebarCallViewApp.vue
  12. 4
      src/components/AdminSettings/HostedSignalingServer.vue
  13. 6
      src/components/AdminSettings/TurnServer.vue
  14. 36
      src/components/CallView/CallView.vue
  15. 5
      src/components/CallView/Grid/Grid.vue
  16. 8
      src/components/CallView/shared/LocalMediaControls.vue
  17. 8
      src/components/CallView/shared/LocalVideo.vue
  18. 4
      src/components/CallView/shared/Screen.vue
  19. 6
      src/components/CallView/shared/Video.vue
  20. 2
      src/components/CallView/shared/VideoBackground.vue
  21. 8
      src/components/CallView/shared/VideoBottomBar.vue
  22. 2
      src/components/ChatView.vue
  23. 2
      src/components/ConversationIcon.vue
  24. 2
      src/components/ConversationSettings/ListableSettings.vue
  25. 3
      src/components/ConversationSettings/Matterbridge/BridgePart.vue
  26. 2
      src/components/ConversationsOptionsList.vue
  27. 2
      src/components/LeftSidebar/ConversationsList/Conversation.spec.js
  28. 6
      src/components/LeftSidebar/ConversationsList/Conversation.vue
  29. 2
      src/components/LeftSidebar/SearchBox/SearchBox.vue
  30. 2
      src/components/LobbyScreen.vue
  31. 6
      src/components/MediaDevicesPreview.vue
  32. 30
      src/components/MessagesList/MessagesGroup/Message/Message.spec.js
  33. 36
      src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js
  34. 2
      src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue
  35. 2
      src/components/MessagesList/MessagesList.vue
  36. 10
      src/components/NewMessageForm/AdvancedInput/AdvancedInput.vue
  37. 2
      src/components/RightSidebar/Participants/ParticipantsList/Participant/Participant.spec.js
  38. 4
      src/components/RightSidebar/Participants/ParticipantsList/Participant/Participant.vue
  39. 4
      src/components/RightSidebar/Participants/ParticipantsTab.vue
  40. 2
      src/components/RightSidebar/RightSidebar.vue
  41. 2
      src/components/TopBar/CallButton.vue
  42. 2
      src/mainFilesSidebarLoader.js
  43. 16
      src/mixins/call.js
  44. 2
      src/mixins/vueAtReparenter.js
  45. 4
      src/services/conversationsService.spec.js
  46. 2
      src/services/filesSharingServices.js
  47. 2
      src/store/callViewStore.js
  48. 2
      src/store/fileUploadStore.js
  49. 2
      src/store/fileUploadStore.spec.js
  50. 8
      src/store/messagesStore.js
  51. 6
      src/store/messagesStore.spec.js
  52. 12
      src/store/participantsStore.js
  53. 4
      src/utils/clipboard.js
  54. 130
      src/utils/signaling.js
  55. 40
      src/utils/webrtc/MediaDevicesManager.js
  56. 20
      src/utils/webrtc/SentVideoQualityThrottler.js
  57. 16
      src/utils/webrtc/SpeakingWhileMutedWarner.js
  58. 18
      src/utils/webrtc/VideoConstrainer.js
  59. 12
      src/utils/webrtc/analyzers/AverageStatValue.js
  60. 20
      src/utils/webrtc/analyzers/CallAnalyzer.js
  61. 42
      src/utils/webrtc/analyzers/ParticipantAnalyzer.js
  62. 128
      src/utils/webrtc/analyzers/PeerConnectionAnalyzer.js
  63. 14
      src/utils/webrtc/models/CallParticipantCollection.js
  64. 40
      src/utils/webrtc/models/CallParticipantModel.js
  65. 22
      src/utils/webrtc/models/LocalCallParticipantModel.js
  66. 68
      src/utils/webrtc/models/LocalMediaModel.js
  67. 6
      src/utils/webrtc/shims/MediaStream.js
  68. 2
      src/utils/webrtc/shims/MediaStreamTrack.js
  69. 18
      src/utils/webrtc/simplewebrtc/getscreenmedia.js
  70. 6
      src/utils/webrtc/simplewebrtc/localmedia.js
  71. 8
      src/utils/webrtc/simplewebrtc/peer.js
  72. 2
      src/utils/webrtc/simplewebrtc/simplewebrtc.js
  73. 2
      src/utils/webrtc/simplewebrtc/webrtc.js
  74. 20
      src/utils/webrtc/webrtc.js
  75. 6
      src/views/Dashboard.vue
  76. 2
      src/views/FlowPostToConversation.vue
  77. 2
      src/views/MainView.vue
  78. 36
      stylelint.config.js
  79. 2
      templates/index.php
  80. 2
      templates/settings/admin-settings.php
  81. 119
      webpack.common.js
  82. 7
      webpack.dev.js
  83. 63
      webpack.js
  84. 7
      webpack.prod.js

2
.eslintrc.js

@ -10,4 +10,4 @@ module.exports = {
}
}
]
}
}

15
.github/workflows/jest.yml

@ -11,18 +11,17 @@ jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-versions: [12.x]
name: node${{ matrix.node-versions }}
name: node
steps:
- uses: actions/checkout@v2
- name: Set up node ${{ matrix.node-versions }}
uses: actions/setup-node@v1
- name: Set up node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-versions }}
node-version: 14
- name: Set up npm7
run: npm i -g npm@7
- name: Install dependencies
run: npm ci

30
.github/workflows/lint.yml

@ -55,18 +55,17 @@ jobs:
node:
runs-on: ubuntu-latest
strategy:
matrix:
node-versions: [12.x]
name: eslint node${{ matrix.node-versions }}
name: eslint node
steps:
- uses: actions/checkout@v2
- name: Set up node ${{ matrix.node-versions }}
uses: actions/setup-node@v1
- name: Set up node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-versions }}
node-version: 14
- name: Set up npm7
run: npm i -g npm@7
- name: Install dependencies
run: npm ci
@ -77,18 +76,17 @@ jobs:
stylelint:
runs-on: ubuntu-latest
strategy:
matrix:
node-versions: [12.x]
name: stylelint node${{ matrix.node-versions }}
name: stylelint node
steps:
- uses: actions/checkout@v2
- name: Set up node ${{ matrix.node-versions }}
uses: actions/setup-node@v1
- name: Set up node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-versions }}
node-version: 14
- name: Set up npm7
run: npm i -g npm@7
- name: Install dependencies
run: npm ci

14
babel.config.js

@ -1,11 +1,3 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
corejs: 3,
useBuiltIns: 'entry',
},
],
],
}
const babelConfig = require('@nextcloud/babel-config')
module.exports = babelConfig

2
lib/AppInfo/Application.php

@ -164,7 +164,7 @@ class Application extends App implements IBootstrap {
$resourceManager = $server->query(IProviderManager::class);
$resourceManager->registerResourceProvider(ConversationProvider::class);
$server->getEventDispatcher()->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', function () {
\OCP\Util::addScript(self::APP_ID, 'collections');
\OCP\Util::addScript(self::APP_ID, 'talk-collections');
});
}

2
lib/Dashboard/TalkWidget.php

@ -85,6 +85,6 @@ class TalkWidget implements IWidget {
*/
public function load(): void {
Util::addStyle('spreed', 'icons');
Util::addScript('spreed', 'dashboard');
Util::addScript('spreed', 'talk-dashboard');
}
}

4
lib/Deck/DeckPluginLoader.php

@ -47,8 +47,8 @@ class DeckPluginLoader implements IEventListener {
}
if (strpos($this->request->getPathInfo(), '/apps/deck') === 0) {
Util::addScript('spreed', 'collections');
Util::addScript('spreed', 'deck');
Util::addScript('spreed', 'talk-collections');
Util::addScript('spreed', 'talk-deck');
}
}
}

2
lib/Flow/RegisterOperationsListener.php

@ -44,6 +44,6 @@ class RegisterOperationsListener implements IEventListener {
}
$event->registerOperation($this->operation);
Util::addScript('spreed', 'flow');
Util::addScript('spreed', 'talk-flow');
}
}

35573
package-lock.json
File diff suppressed because it is too large
View File

43
package.json

@ -5,16 +5,16 @@
"description": "",
"author": "Joas Schilling <coding@schilljs.com>",
"scripts": {
"build": "NODE_ENV=production webpack --progress --config webpack.prod.js",
"build": "NODE_ENV=production webpack --progress --config webpack.js",
"test:unit": "TZ=UTC vue-cli-service test:unit",
"test:coverage": "TZ=UTC vue-cli-service test:unit --coverage",
"test:watch": "TZ=UTC vue-cli-service test:unit --watchAll",
"lint": "eslint --ext .js,.vue src",
"dev": "NODE_ENV=development webpack --config webpack.dev.js",
"dev": "NODE_ENV=development webpack --config webpack.js",
"lint:fix": "eslint --ext .js,.vue src --fix",
"stylelint": "stylelint css/*.css css/*.scss src/**/*.scss src/**/*.vue",
"stylelint:fix": "stylelint css/*.css css/*.scss src/**/*.scss src/**/*.vue --fix",
"watch": "NODE_ENV=development webpack --progress --watch --config webpack.dev.js"
"watch": "NODE_ENV=development webpack --progress --watch --config webpack.js"
},
"dependencies": {
"@juliushaertl/vue-richtext": "^0.3.3",
@ -66,49 +66,20 @@
"wildemitter": "^1.2.1"
},
"devDependencies": {
"@babel/core": "^7.14.5",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.14.5",
"@babel/runtime": "^7.14.0",
"@nextcloud/babel-config": "^1.0.0-beta.1",
"@nextcloud/browserslist-config": "^2.1.0",
"@nextcloud/eslint-config": "^1.2.0",
"@nextcloud/eslint-plugin": "^1.5.0",
"@nextcloud/eslint-config": "^5.1.0",
"@nextcloud/stylelint-config": "^1.0.0-beta.0",
"@nextcloud/webpack-vue-config": "^4.0.3",
"@vue/cli-plugin-unit-jest": "^4.5.13",
"@vue/cli-service": "^4.5.13",
"@vue/test-utils": "^1.2.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"babel-loader-exclude-node-modules-except": "^1.2.1",
"babel-plugin-add-module-exports": "^1.0.4",
"css-loader": "^5.0.1",
"eslint": "^5.16.0",
"eslint-config-standard": "^12.0.0",
"eslint-import-resolver-webpack": "^0.13.1",
"eslint-loader": "^3.0.4",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jest": "^24.3.6",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^5.2.3",
"jest-localstorage-mock": "^2.4.14",
"jest-mock-axios": "^4.4.0",
"jest-mock-console": "^1.1.0",
"node-sass": "^5.0.0",
"regenerator-runtime": "^0.13.7",
"sass": "^1.34.1",
"sass-loader": "^10.1.1",
"style-loader": "^2.0.0",
"stylelint": "^13.13.1",
"stylelint-config-recommended-scss": "^4.2.0",
"stylelint-scss": "^3.19.0",
"stylelint-webpack-plugin": "^2.1.1",
"url-loader": "^4.1.1",
"vue-loader": "^15.9.7",
"vue-template-compiler": "^2.6.14",
"webpack": "^4.46.0",
"webpack-cli": "^4.7.0",
"webpack-merge": "^5.8.0",
"webpack-node-externals": "^3.0.0"
},
"browserslist": [

4
src/FilesSidebarCallViewApp.vue

@ -113,7 +113,7 @@ export default {
},
watch: {
showCallView: function(showCallView) {
showCallView(showCallView) {
if (showCallView) {
this.replaceSidebarHeaderContentsWithCallView()
} else {
@ -132,7 +132,7 @@ export default {
*
* @param {Object} fileInfo the watched FileInfo
*/
fileInfo: function(fileInfo) {
fileInfo(fileInfo) {
if (!fileInfo) {
return
}

4
src/components/AdminSettings/HostedSignalingServer.vue

@ -205,8 +205,8 @@ export default {
this.trialAccount = loadState('spreed', 'hosted_signaling_server_trial_data')
const languagesAndCountries = loadState('spreed', 'hosted_signaling_server_language_data')
this.languages = languagesAndCountries['languages'] // two lists of {code: "es", name: "Español"} - one is in 'commonlanguages' and one in 'languages'
this.countries = languagesAndCountries['countries'] // list of {code: "France", name: "France"}
this.languages = languagesAndCountries.languages // two lists of {code: "es", name: "Español"} - one is in 'commonlanguages' and one in 'languages'
this.countries = languagesAndCountries.countries // list of {code: "France", name: "France"}
const signaling = loadState('spreed', 'signaling_servers')
this.showForm = this.trialAccount.length !== 0

6
src/components/AdminSettings/TurnServer.vue

@ -148,7 +148,7 @@ export default {
},
turnServerClasses() {
return {
'error': this.turnServerError,
error: this.turnServerError,
}
},
testIconClasses() {
@ -205,9 +205,9 @@ export default {
const password = Base64.stringify(hmacSHA1(username, this.secret))
const iceServer = {
username: username,
username,
credential: password,
urls: urls,
urls,
}
// Create a PeerConnection with no streams, but force a m=audio line.

36
src/components/CallView/CallView.vue

@ -168,6 +168,7 @@ import LocalVideo from './shared/LocalVideo'
import Screen from './shared/Screen'
import debounce from 'debounce'
import { EventBus } from '../../services/EventBus'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
export default {
name: 'CallView',
@ -196,8 +197,8 @@ export default {
data() {
return {
screens: [],
localMediaModel: localMediaModel,
localCallParticipantModel: localCallParticipantModel,
localMediaModel,
localCallParticipantModel,
sharedDatas: {},
raisedHandUnwatchers: {},
speakingUnwatchers: {},
@ -207,7 +208,7 @@ export default {
localSharedData: {
screenVisible: true,
},
callParticipantCollection: callParticipantCollection,
callParticipantCollection,
videoContainerAspectRatio: 0,
}
},
@ -334,28 +335,28 @@ export default {
},
},
watch: {
localScreen: function(localScreen) {
localScreen(localScreen) {
this._setScreenAvailable(localCallParticipantModel.attributes.peerId, localScreen)
},
callParticipantModels: function(models) {
callParticipantModels(models) {
this.updateDataFromCallParticipantModels(models)
},
'speakers': function() {
speakers() {
this._setPromotedParticipant()
},
'screenSharingActive': function() {
screenSharingActive() {
this._setPromotedParticipant()
},
'screens': function() {
screens() {
this._setScreenVisible()
},
'callParticipantModelsWithScreen': function(newValue, previousValue) {
callParticipantModelsWithScreen(newValue, previousValue) {
// Everytime a new screen is shared, switch to promoted view
if (newValue.length > previousValue.length) {
this.$store.dispatch('startPresentation')
@ -364,7 +365,7 @@ export default {
this.$store.dispatch('stopPresentation')
}
},
'showLocalScreen': function(showLocalScreen) {
showLocalScreen(showLocalScreen) {
// Everytime the local screen is shared, switch to promoted view
if (showLocalScreen) {
this.$store.dispatch('startPresentation')
@ -372,7 +373,7 @@ export default {
this.$store.dispatch('stopPresentation')
}
},
'hasLocalVideo': function(newValue) {
hasLocalVideo(newValue) {
if (this.$store.getters.selectedVideoPeerId === 'local') {
if (!newValue) {
this.$store.dispatch('selectedVideoPeerId', null)
@ -390,11 +391,15 @@ export default {
EventBus.$on('refreshPeerList', this.debounceFetchPeers)
callParticipantCollection.on('remove', this._lowerHandWhenParticipantLeaves)
subscribe('talk:video:toggled', this.handleToggleVideo)
},
beforeDestroy() {
EventBus.$off('refreshPeerList', this.debounceFetchPeers)
callParticipantCollection.off('remove', this._lowerHandWhenParticipantLeaves)
unsubscribe('talk:video:toggled', this.handleToggleVideo)
},
methods: {
/**
@ -504,7 +509,7 @@ export default {
// sometimes the nick name is not available yet...
if (nickName) {
if (raisedHand?.state) {
showMessage(t('spreed', '{nickName} raised their hand.', { nickName: nickName }))
showMessage(t('spreed', '{nickName} raised their hand.', { nickName }))
}
} else {
if (raisedHand?.state) {
@ -515,7 +520,7 @@ export default {
// update in callViewStore
this.$store.dispatch('setParticipantHandRaised', {
sessionId: callParticipantModel.attributes.nextcloudSessionId,
raisedHand: raisedHand,
raisedHand,
})
},
@ -620,6 +625,11 @@ export default {
console.error(exception)
}
}, 1500),
// Toggles videos on and off
handleToggleVideo({ peerId, value }) {
this.sharedDatas[peerId].videoEnabled = value
},
},
}
</script>

5
src/components/CallView/Grid/Grid.vue

@ -445,7 +445,8 @@ export default {
return {
gridTemplateColumns: `repeat(${columns}, minmax(${this.minWidth}px, 1fr))`,
gridTemplateRows: `repeat(${rows}, minmax(${this.minHeight}px, 1fr))` }
gridTemplateRows: `repeat(${rows}, minmax(${this.minHeight}px, 1fr))`,
}
},
// Check if there's an overflow of videos (videos that don't fit in the grid)
@ -475,7 +476,7 @@ export default {
watch: {
// If the video array size changes, rebuild the grid
'videos.length': function() {
'videos.length'() {
this.makeGrid()
},
// TODO: rebuild the grid to have optimal for last page

8
src/components/CallView/shared/LocalMediaControls.vue

@ -243,7 +243,7 @@ export default {
Hand,
Microphone,
MicrophoneOff,
'VideoIcon': Video,
VideoIcon: Video,
VideoOff,
Monitor,
MonitorOff,
@ -279,7 +279,7 @@ export default {
screenSharingMenuOpen: false,
boundaryElement: document.querySelector('.main-view'),
mouseover: false,
callAnalyzer: callAnalyzer,
callAnalyzer,
qualityWarningInGracePeriodTimeout: null,
audioEnabledBeforeSpacebarKeydown: undefined,
spacebarKeyDown: false,
@ -548,14 +548,14 @@ export default {
},
watch: {
currentVolumeProportion: function() {
currentVolumeProportion() {
// The volume meter is updated directly in the DOM as it is
// more efficient than relying on Vue.js to animate the style property,
// because the latter would also process all neighboring components repeatedly.
this.updateVolumeMeter()
},
senderConnectionQualityIsBad: function(senderConnectionQualityIsBad) {
senderConnectionQualityIsBad(senderConnectionQualityIsBad) {
if (!senderConnectionQualityIsBad) {
return
}

8
src/components/CallView/shared/LocalVideo.vue

@ -141,7 +141,7 @@ export default {
videoContainerClass() {
return {
'speaking': this.localMediaModel.attributes.speaking,
speaking: this.localMediaModel.attributes.speaking,
'video-container-grid': this.isGrid,
'video-container-stripe': this.isStripe,
'video-container-big': this.isBig,
@ -202,7 +202,7 @@ export default {
localCallParticipantModel: {
immediate: true,
handler: function(localCallParticipantModel, oldLocalCallParticipantModel) {
handler(localCallParticipantModel, oldLocalCallParticipantModel) {
if (oldLocalCallParticipantModel) {
oldLocalCallParticipantModel.off('forcedMute', this._handleForcedMute)
}
@ -213,14 +213,14 @@ export default {
},
},
'localMediaModel.attributes.localStream': function(localStream) {
'localMediaModel.attributes.localStream'(localStream) {
this._setLocalStream(localStream)
},
localStreamVideoError: {
immediate: true,
handler: function(error) {
handler(error) {
if (error) {
if (error.name === 'NotAllowedError') {
this.notificationHandle = showError(t('spreed', 'Access to camera was denied'))

4
src/components/CallView/shared/Screen.vue

@ -122,11 +122,11 @@ export default {
watch: {
'localMediaModel.attributes.localScreen': function(localScreen) {
'localMediaModel.attributes.localScreen'(localScreen) {
this._setScreen(localScreen)
},
'callParticipantModel.attributes.screen': function(screen) {
'callParticipantModel.attributes.screen'(screen) {
this._setScreen(screen)
},

6
src/components/CallView/shared/Video.vue

@ -184,8 +184,8 @@ export default {
return {
'videoContainer-dummy': this.placeholderForPromoted,
'not-connected': !this.placeholderForPromoted && this.isNotConnected,
'speaking': !this.placeholderForPromoted && this.model.attributes.speaking,
'promoted': !this.placeholderForPromoted && this.sharedData.promoted && !this.isGrid,
speaking: !this.placeholderForPromoted && this.model.attributes.speaking,
promoted: !this.placeholderForPromoted && this.sharedData.promoted && !this.isGrid,
'video-container-grid': this.isGrid,
'video-container-grid--speaking': this.isSpeaking,
'video-container-big': this.isBig,
@ -395,7 +395,7 @@ export default {
watch: {
'model.attributes.stream': function(stream) {
'model.attributes.stream'(stream) {
this._setStream(stream)
},

2
src/components/CallView/shared/VideoBackground.vue

@ -88,7 +88,7 @@ export default {
// If the prop is empty. We're not checking for the default value
// because the user's displayName might be '?'
if (!this.displayName) {
return `var(--color-text-maxcontrast)`
return 'var(--color-text-maxcontrast)'
} else {
const color = usernameToColor(this.displayName)
return `rgb(${color.r}, ${color.g}, ${color.b})`

8
src/components/CallView/shared/VideoBottomBar.vue

@ -126,6 +126,7 @@ import Video from 'vue-material-design-icons/Video'
import VideoOff from 'vue-material-design-icons/VideoOff'
import { PARTICIPANT } from '../../../constants'
import Hand from 'vue-material-design-icons/Hand'
import { emit } from '@nextcloud/event-bus'
export default {
name: 'VideoBottomBar',
@ -136,7 +137,7 @@ export default {
Microphone,
MicrophoneOff,
Monitor,
'VideoIcon': Video,
VideoIcon: Video,
VideoOff,
},
@ -261,7 +262,10 @@ export default {
},
toggleVideo() {
this.sharedData.videoEnabled = !this.sharedData.videoEnabled
emit('talk:video:toggled', {
peerId: this.peerId,
value: !this.sharedData.videoEnabled,
})
},
switchToScreen() {

2
src/components/ChatView.vue

@ -77,7 +77,7 @@ export default {
},
},
data: function() {
data() {
return {
isDraggingOver: false,
/**

2
src/components/ConversationIcon.vue

@ -67,7 +67,7 @@ export default {
},
item: {
type: Object,
default: function() {
default() {
return {
objectType: '',
type: 0,

2
src/components/ConversationSettings/ListableSettings.vue

@ -126,7 +126,7 @@ export default {
try {
await this.$store.dispatch('setListable', {
token: this.token,
listable: listable,
listable,
})
if (this.lastNotification) {

3
src/components/ConversationSettings/Matterbridge/BridgePart.vue

@ -59,6 +59,8 @@
v-for="(field, key) in displayedFields"
:key="key"
class="field">
<!-- TODO: do not mutate prop `part` directly -->
<!-- eslint-disable -->
<div v-if="field.type === 'checkbox'" class="checkbox-container">
<input
:id="key + '-' + num"
@ -85,6 +87,7 @@
:readonly="readonly || !editing"
@focus="readonly = false">
</div>
<!-- eslint-enable -->
</div>
</div>
</template>

2
src/components/ConversationsOptionsList.vue

@ -27,7 +27,7 @@
:title="item.label"
@click="onClick(item)">
<template
v-slot:icon>
#icon>
<ConversationIcon
:item="iconData(item)" />
</template>

2
src/components/LeftSidebar/ConversationsList/Conversation.spec.js

@ -224,7 +224,7 @@ describe('Conversation.vue', () => {
item.lastMessage = lastMessageFromConversation
messagesMock.mockClear().mockReturnValue({
'100': displayedLastStoreMessage,
100: displayedLastStoreMessage,
})
})

6
src/components/LeftSidebar/ConversationsList/Conversation.vue

@ -26,13 +26,13 @@
:to="item.token ? { name: 'conversation', params: { token: item.token }} : ''"
:class="{ 'has-unread-messages': item.unreadMessages }"
@click="onClick">
<template v-slot:icon>
<template #icon>
<ConversationIcon
:item="item"
:hide-favorite="false"
:hide-call="false" />
</template>
<template v-slot:subtitle>
<template #subtitle>
<strong v-if="item.unreadMessages">
{{ conversationInformation }}
</strong>
@ -133,7 +133,7 @@ export default {
},
item: {
type: Object,
default: function() {
default() {
return {
token: '',
participants: [],

2
src/components/LeftSidebar/SearchBox/SearchBox.vue

@ -66,7 +66,7 @@ export default {
default: false,
},
},
data: function() {
data() {
return {
localValue: '',
}

2
src/components/LobbyScreen.vue

@ -62,7 +62,7 @@ export default {
// PHP timestamp is second-based; JavaScript timestamp is
// millisecond based.
const startTime = moment.unix(this.conversation.lobbyTimer).format('LLL')
message = t('spreed', 'You are currently waiting in the lobby. This meeting is scheduled for {startTime}', { startTime: startTime })
message = t('spreed', 'You are currently waiting in the lobby. This meeting is scheduled for {startTime}', { startTime })
}
return message

6
src/components/MediaDevicesPreview.vue

@ -121,7 +121,7 @@ export default {
MediaDevicesSelector,
Microphone,
MicrophoneOff,
'VideoIcon': Video,
VideoIcon: Video,
VideoOff,
},
@ -135,7 +135,7 @@ export default {
data() {
return {
mounted: false,
mediaDevicesManager: mediaDevicesManager,
mediaDevicesManager,
pendingGetUserMediaAudioCount: 0,
pendingGetUserMediaVideoCount: 0,
audioStream: null,
@ -283,7 +283,7 @@ export default {
watch: {
enabled: {
handler: function(enabled) {
handler(enabled) {
if (this.enabled) {
this.mediaDevicesManager.enableDeviceEvents()
this.updateAudioStream()

30
src/components/MessagesList/MessagesGroup/Message/Message.spec.js

@ -324,12 +324,12 @@ describe('Message.vue', () => {
test('renders file previews', () => {
const params = {
'actor': {
actor: {
id: 'alice',
name: 'Alice',
type: 'user',
},
'file': {
file: {
path: 'some/path',
type: 'file',
},
@ -337,13 +337,13 @@ describe('Message.vue', () => {
renderRichObject(
'{file}',
params, {
'actor': {
actor: {
component: Mention,
props: params['actor'],
props: params.actor,
},
'file': {
file: {
component: FilePreview,
props: params['file'],
props: params.file,
},
}
)
@ -351,7 +351,7 @@ describe('Message.vue', () => {
test('renders deck cards', () => {
const params = {
'actor': {
actor: {
id: 'alice',
name: 'Alice',
type: 'user',
@ -364,9 +364,9 @@ describe('Message.vue', () => {
renderRichObject(
'{deck-card}',
params, {
'actor': {
actor: {
component: Mention,
props: params['actor'],
props: params.actor,
},
'deck-card': {
component: DeckCard,
@ -396,12 +396,12 @@ describe('Message.vue', () => {
test('renders other rich objects', () => {
const params = {
'actor': {
actor: {
id: 'alice',
name: 'Alice',
type: 'user',
},
'unknown': {
unknown: {
path: 'some/path',
type: 'unknown',
},
@ -409,13 +409,13 @@ describe('Message.vue', () => {
renderRichObject(
'{unknown}',
params, {
'actor': {
actor: {
component: Mention,
props: params['actor'],
props: params.actor,
},
'unknown': {
unknown: {
component: DefaultParameter,
props: params['unknown'],
props: params.unknown,
},
}
)

36
src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js

@ -66,7 +66,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -89,7 +89,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -111,7 +111,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -127,7 +127,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -157,7 +157,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -177,7 +177,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
expect(wrapper.element.tagName).toBe('A')
@ -189,7 +189,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onerror()
@ -206,7 +206,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -245,7 +245,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -262,7 +262,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -280,7 +280,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -297,7 +297,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -356,7 +356,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -388,7 +388,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -403,7 +403,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -431,7 +431,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()
@ -472,7 +472,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onerror()
@ -505,7 +505,7 @@ describe('FilePreview.vue', () => {
const wrapper = shallowMount(FilePreview, {
localVue,
store,
propsData: propsData,
propsData,
})
await imageMock.onload()

2
src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue

@ -327,7 +327,7 @@ export default {
// FIXME: use a cleaner way...
const token = this.link.substr(this.link.lastIndexOf('/') + 1)
return generateUrl('/apps/files_sharing/publicpreview/{token}?x=-1&y={height}&a=1', {
token: token,
token,
height: previewSize,
})
} else {

2
src/components/MessagesList/MessagesList.vue

@ -112,7 +112,7 @@ export default {
},
},
data: function() {
data() {
return {
/**
* When scrolling to the top of the div .scroller we start loading previous

10
src/components/NewMessageForm/AdvancedInput/AdvancedInput.vue

@ -29,7 +29,7 @@
:tab-select="true"
:allow-spaces="false"
@at="handleAtEvent">
<template v-slot:item="scope">
<template #item="scope">
<Avatar v-if="isMentionToAll(scope.item.id)"
:size="44"
:icon-class="'icon-group-forced-white'"
@ -57,7 +57,7 @@
</em>
</span>
</template>
<template v-slot:embeddedItem="scope">
<template #embeddedItem="scope">
<!-- The root element itself is ignored, only its contents are taken
into account. -->
<span>
@ -207,7 +207,7 @@ export default {
required: true,
},
},
data: function() {
data() {
return {
text: '',
autoCompleteMentionCandidates: [],
@ -376,8 +376,8 @@ export default {
getGuestAvatarStyle() {
return {
'width': '44px',
'height': '44px',
width: '44px',
height: '44px',
'line-height': '44px',
'background-color': '#b9b9b9',
'text-align': 'center',

2
src/components/RightSidebar/Participants/ParticipantsList/Participant/Participant.spec.js

@ -93,7 +93,7 @@ describe('Participant.vue', () => {
mixins: [{
// force tooltip display for testing
methods: {
forceEnableTooltips: function() {
forceEnableTooltips() {
this.isUserNameTooltipVisible = true
this.isStatusTooltipVisible = true
},

4
src/components/RightSidebar/Participants/ParticipantsList/Participant/Participant.vue

@ -426,7 +426,7 @@ export default {
&& !this.isGroup
},
preloadedUserStatus() {
if (this.participant.hasOwnProperty('statusMessage')) {
if (Object.prototype.hasOwnProperty.call(this.participant, 'statusMessage')) {
// We preloaded the status when via participants API
return {
status: this.participant.status || null,
@ -434,7 +434,7 @@ export default {
icon: this.participant.statusIcon || null,
}
}
if (this.participant.hasOwnProperty('status')) {
if (Object.prototype.hasOwnProperty.call(this.participant, 'status')) {
// We preloaded the status when via search API
return {
status: this.participant.status.status || null,

4
src/components/RightSidebar/Participants/ParticipantsTab.vue

@ -270,13 +270,13 @@ export default {
const hasUserStatuses = !!participants.headers['x-nextcloud-has-user-statuses']
participants.data.ocs.data.forEach(participant => {
this.$store.dispatch('addParticipant', {
token: token,
token,
participant,
})
if (participant.participantType === PARTICIPANT.TYPE.GUEST
|| participant.participantType === PARTICIPANT.TYPE.GUEST_MODERATOR) {
this.$store.dispatch('forceGuestName', {
token: token,
token,
actorId: Hex.stringify(SHA1(participant.sessionIds[0])),
actorDisplayName: participant.displayName,
})

2
src/components/RightSidebar/RightSidebar.vue

@ -244,7 +244,7 @@ export default {
try {
await this.$store.dispatch('setConversationName', {
token: this.token,
name: name,
name,
})
this.dismissEditing()
} catch (exception) {

2
src/components/TopBar/CallButton.vue

@ -191,7 +191,7 @@ export default {
await this.$store.dispatch('joinCall', {
token: this.token,
participantIdentifier: this.$store.getters.getParticipantIdentifier(),
flags: flags,
flags,
})
this.loading = false
},

2
src/mainFilesSidebarLoader.js

@ -34,7 +34,7 @@ const isEnabled = function(fileInfo) {
// left; this must be done here because "setFileInfo" will not get
// called with the new file if the tab can not be displayed.
if (token) {
OCA.Talk.store.dispatch('leaveConversation', { token: token })
OCA.Talk.store.dispatch('leaveConversation', { token })
}
OCA.Talk.store.dispatch('updateTokenAndFileIdForToken', {

16
src/mixins/call.js

@ -26,8 +26,8 @@ const call = {
data() {
return {
screens: [],
localMediaModel: localMediaModel,
localCallParticipantModel: localCallParticipantModel,
localMediaModel,
localCallParticipantModel,
sharedDatas: {},
speakingUnwatchers: {},
screenUnwatchers: {},
@ -36,7 +36,7 @@ const call = {
localSharedData: {
screenVisible: true,
},
callParticipantCollection: callParticipantCollection,
callParticipantCollection,
}
},
@ -196,23 +196,23 @@ const call = {
watch: {
localScreen: function(localScreen) {
localScreen(localScreen) {
this._setScreenAvailable(localCallParticipantModel.attributes.peerId, localScreen)
},
callParticipantModels: function(models) {
callParticipantModels(models) {
this.updateDataFromCallParticipantModels(models)
},
'speakers': function() {
speakers() {
this._setPromotedParticipant()
},
'screenSharingActive': function() {
screenSharingActive() {
this._setPromotedParticipant()
},
'screens': function() {
screens() {
this._setScreenVisible()
},

2
src/mixins/vueAtReparenter.js

@ -36,7 +36,7 @@ import Vue from 'vue'
*/
export default {
data: function() {
data() {
return {
/**
* The selector for the HTML element to reparent the vue-at panel to.

4
src/services/conversationsService.spec.js

@ -13,8 +13,8 @@ describe('conversationsService', () => {
searchPossibleConversations(
{
searchText: 'search-text',
token: token,
onlyUsers: onlyUsers,
token,
onlyUsers,
},
{
dummyOption: true,

2
src/services/filesSharingServices.js

@ -48,7 +48,7 @@ const shareFile = async function(path, token, referenceId, metadata) {
console.error('Error while sharing file: ' + error.response.data.ocs.meta.message)
showError(error.response.data.ocs.meta.message)
} else {
console.error(`Error while sharing file: Unknown error`)
console.error('Error while sharing file: Unknown error')
showError(t('spreed', 'Error while sharing file'))
}
}

2
src/store/callViewStore.js

@ -123,7 +123,7 @@ const actions = {
// BrowserStorage.getItem returns a string instead of a boolean
isGrid = (isGrid === 'true')
}
context.dispatch('setCallViewMode', { isGrid: isGrid, isStripeOpen: true })
context.dispatch('setCallViewMode', { isGrid, isStripeOpen: true })
context.commit('setQualityWarningTooltipDismissed', { qualityWarningTooltipDismissed: false })
},

2
src/store/fileUploadStore.js

@ -309,7 +309,7 @@ const actions = {
commit('markFileAsFailedUpload', { uploadId, index })
dispatch('markTemporaryMessageAsFailed', {
message: temporaryMessage,
reason: reason,
reason,
})
}

2
src/store/fileUploadStore.spec.js

@ -53,7 +53,7 @@ describe('fileUploadStore', () => {
index,
token,
localUrl,
file: file,
file,
},
},
}

8
src/store/messagesStore.js

@ -479,7 +479,7 @@ const actions = {
return
}
// set the id to the last message
context.dispatch('updateLastReadMessage', { token, id: conversation.lastMessage.id, updateVisually: updateVisually })
context.dispatch('updateLastReadMessage', { token, id: conversation.lastMessage.id, updateVisually })
context.dispatch('markConversationRead', token)
},
@ -560,7 +560,7 @@ const actions = {
if (response.headers['x-chat-last-given']) {
context.dispatch('setFirstKnownMessageId', {
token: token,
token,
id: parseInt(response.headers['x-chat-last-given'], 10),
})
}
@ -644,8 +644,8 @@ const actions = {
const conversation = context.getters.conversation(token)
if (conversation && conversation.lastMessage && lastMessage.id > conversation.lastMessage.id) {
context.dispatch('updateConversationLastMessage', {
token: token,
lastMessage: lastMessage,
token,
lastMessage,
})
}

6
src/store/messagesStore.spec.js

@ -143,11 +143,11 @@ describe('messagesStore', () => {
// with messages getter
expect(store.getters.messages(TOKEN)).toStrictEqual({
'1': message1,
'3': message3,
1: message1,
3: message3,
})
expect(store.getters.messages('token-2')).toStrictEqual({
'2': message2,
2: message2,
})
})

12
src/store/participantsStore.js

@ -83,9 +83,9 @@ const getters = {
let index
if (participantIdentifier.hasOwnProperty('attendeeId')) {
if (Object.prototype.hasOwnProperty.call(participantIdentifier, 'attendeeId')) {
index = state.participants[token].findIndex(participant => participant.attendeeId === participantIdentifier.attendeeId)
} else if (participantIdentifier.hasOwnProperty('actorId') && participantIdentifier.hasOwnProperty('actorType')) {
} else if (Object.prototype.hasOwnProperty.call(participantIdentifier, 'actorId') && Object.prototype.hasOwnProperty.call(participantIdentifier, 'actorType')) {
index = state.participants[token].findIndex(participant => participant.actorId === participantIdentifier.actorId && participant.actorType === participantIdentifier.actorType)
} else {
index = state.participants[token].findIndex(participant => participant.sessionId === participantIdentifier.sessionId)
@ -98,7 +98,7 @@ const getters = {
return {}
}
if (state.peers[token].hasOwnProperty(sessionId)) {
if (Object.prototype.hasOwnProperty.call(state.peers[token], sessionId)) {
return state.peers[token][sessionId]
}
@ -130,7 +130,7 @@ const mutations = {
if (state.participants[token] && state.participants[token][index]) {
Vue.delete(state.participants[token], index)
} else {
console.error(`The conversation you are trying to purge doesn't exist`)
console.error('The conversation you are trying to purge doesn\'t exist')
}
},
setInCall(state, { token, sessionId, flags }) {
@ -277,7 +277,7 @@ const actions = {
}
const updatedData = {
sessionId: sessionId,
sessionId,
inCall: PARTICIPANT.CALL_FLAG.DISCONNECTED,
}
commit('updateParticipant', { token, index, updatedData })
@ -382,7 +382,7 @@ const actions = {
context.dispatch('setCurrentParticipant', response.data.ocs.data)
context.dispatch('addConversation', response.data.ocs.data)
context.dispatch('updateSessionId', {
token: token,
token,
participantIdentifier: context.getters.getParticipantIdentifier(),
sessionId: response.data.ocs.data.sessionId,
})

4
src/utils/clipboard.js

@ -31,13 +31,13 @@ const fetchClipboardContent = function(event) {
}
if (files.length > 0) {
return { kind: 'file', files: files }
return { kind: 'file', files }
}
}
const text = clipboardData.getData('text/plain')
return { kind: 'text', text: text }
return { kind: 'text', text }
}
export {

130
src/utils/signaling.js

@ -82,7 +82,7 @@ function Base(settings) {
Signaling.Base = Base
Signaling.Base.prototype.on = function(ev, handler) {
if (!this.handlers.hasOwnProperty(ev)) {
if (!Object.prototype.hasOwnProperty.call(this.handlers, ev)) {
this.handlers[ev] = [handler]
} else {
this.handlers[ev].push(handler)
@ -101,7 +101,7 @@ Signaling.Base.prototype.on = function(ev, handler) {
}
Signaling.Base.prototype.off = function(ev, handler) {
if (!this.handlers.hasOwnProperty(ev)) {
if (!Object.prototype.hasOwnProperty.call(this.handlers, ev)) {
return
}
@ -253,7 +253,7 @@ Signaling.Base.prototype._joinCallSuccess = function(/* token */) {
Signaling.Base.prototype.joinCall = function(token, flags) {
return new Promise((resolve, reject) => {
axios.post(generateOcsUrl('apps/spreed/api/v4/call/{token}', { token }), {
flags: flags,
flags,
})
.then(function() {
this.currentCallToken = token
@ -284,7 +284,7 @@ Signaling.Base.prototype.updateCallFlags = function(token, flags) {
}
axios.put(generateOcsUrl('apps/spreed/api/v4/call/{token}', { token }), {
flags: flags,
flags,
})
.then(function() {
this.currentCallFlags = flags
@ -379,7 +379,7 @@ Signaling.Internal.prototype.forceReconnect = function(newSession, flags) {
Signaling.Internal.prototype._sendMessageWithCallback = function(ev) {
const message = [{
ev: ev,
ev,
}]
this._sendMessages(message)
@ -661,7 +661,7 @@ Signaling.Standalone.prototype.connect = function() {
console.debug('Received', data)
}
const id = data.id
if (id && this.callbacks.hasOwnProperty(id)) {
if (id && Object.prototype.hasOwnProperty.call(this.callbacks, id)) {
const cb = this.callbacks[id]
delete this.callbacks[id]
cb(data)
@ -712,8 +712,8 @@ Signaling.Standalone.prototype.connect = function() {
Signaling.Standalone.prototype.sendBye = function() {
if (this.connected) {
this.doSend({
'type': 'bye',
'bye': {},
type: 'bye',
bye: {},
})
}
this.resumeId = null
@ -774,13 +774,13 @@ Signaling.Standalone.prototype.forceReconnect = function(newSession, flags) {
Signaling.Standalone.prototype.sendCallMessage = function(data) {
if (data.type === 'control') {
this.doSend({
'type': 'control',
'control': {
'recipient': {
'type': 'session',
'sessionid': data.to,
type: 'control',
control: {
recipient: {
type: 'session',
sessionid: data.to,
},
'data': data.payload,
data: data.payload,
},
})
@ -788,13 +788,13 @@ Signaling.Standalone.prototype.sendCallMessage = function(data) {
}
this.doSend({
'type': 'message',
'message': {
'recipient': {
'type': 'session',
'sessionid': data.to,
type: 'message',
message: {
recipient: {
type: 'session',
sessionid: data.to,
},
'data': data,
data,
},
})
}
@ -806,12 +806,12 @@ Signaling.Standalone.prototype.sendRoomMessage = function(data) {
}
this.doSend({
'type': 'message',
'message': {
'recipient': {
'type': 'room',
type: 'message',
message: {
recipient: {
type: 'room',
},
'data': data,
data,
},
})
}
@ -827,7 +827,7 @@ Signaling.Standalone.prototype.doSend = function(msg, callback) {
if (callback) {
const id = this.id++
this.callbacks[id] = callback
msg['id'] = '' + id
msg.id = '' + id
}
if (OC.debug) {
console.debug('Sending', msg)
@ -840,10 +840,10 @@ Signaling.Standalone.prototype.sendHello = function() {
if (this.resumeId) {
console.debug('Trying to resume session', this.sessionId)
msg = {
'type': 'hello',
'hello': {
'version': '1.0',
'resumeid': this.resumeId,
type: 'hello',
hello: {
version: '1.0',
resumeid: this.resumeId,
},
}
} else {
@ -851,14 +851,14 @@ Signaling.Standalone.prototype.sendHello = function() {
this._forceReconnect = false
const url = generateOcsUrl('apps/spreed/api/v3/signaling/backend')
msg = {
'type': 'hello',
'hello': {
'version': '1.0',
'auth': {
'url': url,
'params': {
'userid': this.settings.userId,
'ticket': this.settings.ticket,
type: 'hello',
hello: {
version: '1.0',
auth: {
url,
params: {
userid: this.settings.userId,
ticket: this.settings.ticket,
},
},
},
@ -1001,13 +1001,13 @@ Signaling.Standalone.prototype._joinRoomSuccess = function(token, nextcloudSessi
console.debug('Join room', token)
this.doSend({
'type': 'room',
'room': {
'roomid': token,
type: 'room',
room: {
roomid: token,
// Pass the Nextcloud session id to the signaling server. The
// session id will be passed through to Nextcloud to check if
// the (Nextcloud) user is allowed to join the room.
'sessionid': nextcloudSessionId,
sessionid: nextcloudSessionId,
},
}, function(data) {
this.joinResponseReceived(data, token)
@ -1026,10 +1026,10 @@ Signaling.Standalone.prototype.joinCall = function(token, flags) {
const promise = new Promise((resolve, reject) => {
this.pendingJoinCall = {
token: token,
flags: flags,
resolve: resolve,
reject: reject,
token,
flags,
resolve,
reject,
}
})
@ -1071,9 +1071,9 @@ Signaling.Standalone.prototype.joinResponseReceived = function(data, token) {
Signaling.Standalone.prototype._doLeaveRoom = function(token) {
console.debug('Leave room', token)
this.doSend({
'type': 'room',
'room': {
'roomid': '',
type: 'room',
room: {
roomid: '',
},
}, function(data) {
console.debug('Left', data)
@ -1218,15 +1218,15 @@ Signaling.Standalone.prototype.requestOffer = function(sessionid, roomType) {
}
console.debug('Request offer from', sessionid)
this.doSend({
'type': 'message',
'message': {
'recipient': {
'type': 'session',
'sessionid': sessionid,
type: 'message',
message: {
recipient: {
type: 'session',
sessionid,
},
'data': {
'type': 'requestoffer',
'roomType': roomType,
data: {
type: 'requestoffer',
roomType,
},
},
})
@ -1247,15 +1247,15 @@ Signaling.Standalone.prototype.sendOffer = function(sessionid, roomType) {
}
console.debug('Send offer to', sessionid)
this.doSend({
'type': 'message',
'message': {
'recipient': {
'type': 'session',
'sessionid': sessionid,
type: 'message',
message: {
recipient: {
type: 'session',
sessionid,
},
'data': {
'type': 'sendoffer',
'roomType': roomType,
data: {
type: 'sendoffer',
roomType,
},
},
})

40
src/utils/webrtc/MediaDevicesManager.js

@ -105,11 +105,11 @@ export default function MediaDevicesManager() {
}
MediaDevicesManager.prototype = {
get: function(key) {
get(key) {
return this.attributes[key]
},
set: function(key, value) {
set(key, value) {
this.attributes[key] = value
this._trigger('change:' + key, [value])
@ -117,7 +117,7 @@ MediaDevicesManager.prototype = {
this._storeDeviceId(key, value)
},
_storeDeviceId: function(key, value) {
_storeDeviceId(key, value) {
if (key !== 'audioInputId' && key !== 'videoInputId') {
return
}
@ -133,15 +133,15 @@ MediaDevicesManager.prototype = {
}
},
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -153,7 +153,7 @@ MediaDevicesManager.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -179,11 +179,11 @@ MediaDevicesManager.prototype = {
* @returns {boolean} true if MediaDevices interface is supported, false
* otherwise.
*/
isSupported: function() {
isSupported() {
return navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia && navigator.mediaDevices.enumerateDevices
},
enableDeviceEvents: function() {
enableDeviceEvents() {
if (!this.isSupported()) {
return
}
@ -195,7 +195,7 @@ MediaDevicesManager.prototype = {
navigator.mediaDevices.addEventListener('devicechange', this._updateDevicesBound)
},
disableDeviceEvents: function() {
disableDeviceEvents() {
if (!this.isSupported()) {
return
}
@ -207,7 +207,7 @@ MediaDevicesManager.prototype = {
}
},
_updateDevices: function() {
_updateDevices() {
this._pendingEnumerateDevicesPromise = navigator.mediaDevices.enumerateDevices().then(devices => {
const previousAudioInputId = this.attributes.audioInputId
const previousVideoInputId = this.attributes.videoInputId
@ -243,7 +243,7 @@ MediaDevicesManager.prototype = {
})
},
_removeDevice: function(removedDevice) {
_removeDevice(removedDevice) {
const removedDeviceIndex = this.attributes.devices.findIndex(oldDevice => oldDevice.deviceId === removedDevice.deviceId && oldDevice.kind === removedDevice.kind)
if (removedDeviceIndex >= 0) {
this.attributes.devices.splice(removedDeviceIndex, 1)
@ -268,7 +268,7 @@ MediaDevicesManager.prototype = {
}
},
_updateDevice: function(updatedDevice) {
_updateDevice(updatedDevice) {
const oldDevice = this.attributes.devices.find(oldDevice => oldDevice.deviceId === updatedDevice.deviceId && oldDevice.kind === updatedDevice.kind)
// Only update the label if it has a value, as it may have been
@ -282,7 +282,7 @@ MediaDevicesManager.prototype = {
oldDevice.kind = updatedDevice.kind
},
_addDevice: function(addedDevice) {
_addDevice(addedDevice) {
// Copy the device to add, as its properties are read only and
// thus they can not be updated later.
addedDevice = {
@ -359,7 +359,7 @@ MediaDevicesManager.prototype = {
* @returns {Promise} resolved with a MediaStream object when successful, or
* rejected with a DOMException in case of error
*/
getUserMedia: function(constraints) {
getUserMedia(constraints) {
if (!this.isSupported()) {
return new Promise((resolve, reject) => {
reject(new DOMException('MediaDevicesManager is not supported', 'NotSupportedError'))
@ -377,7 +377,7 @@ MediaDevicesManager.prototype = {
})
},
_getUserMediaInternal: function(constraints) {
_getUserMediaInternal(constraints) {
if (constraints.audio && !constraints.audio.deviceId) {
if (this.attributes.audioInputId) {
if (!(constraints.audio instanceof Object)) {
@ -426,7 +426,7 @@ MediaDevicesManager.prototype = {
})
},
_stopIncompatibleTracks: function(constraints) {
_stopIncompatibleTracks(constraints) {
this._tracks.forEach(track => {
if (constraints.audio && constraints.audio.deviceId && track.kind === 'audio') {
const constraintsAudioDeviceId = constraints.audio.deviceId.exact || constraints.audio.deviceId.ideal || constraints.audio.deviceId
@ -446,13 +446,13 @@ MediaDevicesManager.prototype = {
})
},
_registerStream: function(stream) {
_registerStream(stream) {
stream.getTracks().forEach(track => {
this._registerTrack(track)
})
},
_registerTrack: function(track) {
_registerTrack(track) {
this._tracks.push(track)
track.addEventListener('ended', () => {
@ -467,7 +467,7 @@ MediaDevicesManager.prototype = {
})
},
_updateSelectedDevicesFromGetUserMediaResult: function(stream) {
_updateSelectedDevicesFromGetUserMediaResult(stream) {
if (this.attributes.audioInputId) {
const audioTracks = stream.getAudioTracks()
const audioTrackSettings = audioTracks.length > 0 ? audioTracks[0].getSettings() : null

20
src/utils/webrtc/SentVideoQualityThrottler.js

@ -76,13 +76,13 @@ export default function SentVideoQualityThrottler(localMediaModel, callParticipa
}
SentVideoQualityThrottler.prototype = {
destroy: function() {
destroy() {
this._localMediaModel.off('change:videoAvailable', this._handleLocalVideoAvailableChangeBound)
this._stopListeningToChanges()
},
_handleLocalVideoAvailableChange: function(localMediaModel, videoAvailable) {
_handleLocalVideoAvailableChange(localMediaModel, videoAvailable) {
if (videoAvailable) {
this._startListeningToChanges()
} else {
@ -90,7 +90,7 @@ SentVideoQualityThrottler.prototype = {
}
},
_startListeningToChanges: function() {
_startListeningToChanges() {
this._localMediaModel.on('change:videoEnabled', this._adjustVideoQualityIfNeededBound)
this._localMediaModel.on('change:audioEnabled', this._handleLocalAudioEnabledChangeBound)
this._localMediaModel.on('change:speaking', this._handleLocalSpeakingChangeBound)
@ -109,7 +109,7 @@ SentVideoQualityThrottler.prototype = {
this._adjustVideoQualityIfNeeded()
},
_stopListeningToChanges: function() {
_stopListeningToChanges() {
this._localMediaModel.off('change:videoEnabled', this._adjustVideoQualityIfNeededBound)
this._localMediaModel.off('change:audioEnabled', this._handleLocalAudioEnabledChangeBound)
this._localMediaModel.off('change:speaking', this._handleLocalSpeakingChangeBound)
@ -123,21 +123,21 @@ SentVideoQualityThrottler.prototype = {
})
},
_handleAddParticipant: function(callParticipantCollection, callParticipantModel) {
_handleAddParticipant(callParticipantCollection, callParticipantModel) {
callParticipantModel.on('change:videoAvailable', this._adjustVideoQualityIfNeededBound)
callParticipantModel.on('change:audioAvailable', this._adjustVideoQualityIfNeededBound)
this._adjustVideoQualityIfNeeded()
},
_handleRemoveParticipant: function(callParticipantCollection, callParticipantModel) {
_handleRemoveParticipant(callParticipantCollection, callParticipantModel) {
callParticipantModel.off('change:videoAvailable', this._adjustVideoQualityIfNeededBound)
callParticipantModel.off('change:audioAvailable', this._adjustVideoQualityIfNeededBound)
this._adjustVideoQualityIfNeeded()
},
_handleLocalAudioEnabledChange: function() {
_handleLocalAudioEnabledChange() {
if (this._localMediaModel.get('audioEnabled')) {
return
}
@ -150,7 +150,7 @@ SentVideoQualityThrottler.prototype = {
this._adjustVideoQualityIfNeeded()
},
_handleLocalSpeakingChange: function() {
_handleLocalSpeakingChange() {
if (this._localMediaModel.get('speaking')) {
window.clearTimeout(this._gracePeriodAfterSpeakingTimeout)
this._gracePeriodAfterSpeakingTimeout = null
@ -169,7 +169,7 @@ SentVideoQualityThrottler.prototype = {
}, 5000)
},
_adjustVideoQualityIfNeeded: function() {
_adjustVideoQualityIfNeeded() {
if (!this._localMediaModel.get('videoAvailable') || !this._localMediaModel.get('videoEnabled')) {
return
}
@ -178,7 +178,7 @@ SentVideoQualityThrottler.prototype = {
this._videoConstrainer.applyConstraints(quality)
},
_getQualityForState: function() {
_getQualityForState() {
if (this._speakingOrInGracePeriodAfterSpeaking) {
return QUALITY.HIGH
}

16
src/utils/webrtc/SpeakingWhileMutedWarner.js

@ -55,11 +55,11 @@ export default function SpeakingWhileMutedWarner(model, view) {
}
SpeakingWhileMutedWarner.prototype = {
destroy: function() {
destroy() {
this._model.off('change:speakingWhileMuted', this._handleSpeakingWhileMutedChangeBound)
},
_handleSpeakingWhileMutedChange: function(model, speakingWhileMuted) {
_handleSpeakingWhileMutedChange(model, speakingWhileMuted) {
if (speakingWhileMuted) {
this._handleSpeakingWhileMuted()
} else {
@ -67,7 +67,7 @@ SpeakingWhileMutedWarner.prototype = {
}
},
_handleSpeakingWhileMuted: function() {
_handleSpeakingWhileMuted() {
this._startedSpeakingTimeout = setTimeout(function() {
delete this._startedSpeakingTimeout
@ -75,7 +75,7 @@ SpeakingWhileMutedWarner.prototype = {
}.bind(this), 3000)
},
_handleStoppedSpeakingWhileMuted: function() {
_handleStoppedSpeakingWhileMuted() {
if (this._startedSpeakingTimeout) {
clearTimeout(this._startedSpeakingTimeout)
delete this._startedSpeakingTimeout
@ -84,7 +84,7 @@ SpeakingWhileMutedWarner.prototype = {
this._hideWarning()
},
_showWarning: function() {
_showWarning() {
const message = t('spreed', 'You seem to be talking while muted, please unmute yourself for others to hear you')
if (!document.hidden) {
@ -102,7 +102,7 @@ SpeakingWhileMutedWarner.prototype = {
}
},
_showNotification: function(message) {
_showNotification(message) {
if (this._notification) {
return
}
@ -111,7 +111,7 @@ SpeakingWhileMutedWarner.prototype = {
this._notification = true
},
_showBrowserNotification: function(message) {
_showBrowserNotification(message) {
return new Promise(function(resolve, reject) {
if (this._browserNotification) {
resolve()
@ -154,7 +154,7 @@ SpeakingWhileMutedWarner.prototype = {
}.bind(this))
},
_hideWarning: function() {
_hideWarning() {
this._pendingBrowserNotification = false
if (this._notification) {

18
src/utils/webrtc/VideoConstrainer.js

@ -53,7 +53,7 @@ function VideoConstrainer(localMediaModel) {
}
VideoConstrainer.prototype = {
applyConstraints: async function(quality) {
async applyConstraints(quality) {
if (quality === this._currentQuality) {
return
}
@ -82,7 +82,7 @@ VideoConstrainer.prototype = {
this._currentQuality = quality
},
_applyRoughConstraints: async function(localVideoTrack, quality) {
async _applyRoughConstraints(localVideoTrack, quality) {
let constraints = this._knownValidConstraintsForQuality[quality]
if (!constraints) {
constraints = this._getConstraintsForQuality(quality)
@ -125,7 +125,7 @@ VideoConstrainer.prototype = {
}
},
_applyRoughResolutionConstraints: async function(localVideoTrack, constraints) {
async _applyRoughResolutionConstraints(localVideoTrack, constraints) {
try {
await localVideoTrack.applyConstraints(constraints)
@ -142,7 +142,7 @@ VideoConstrainer.prototype = {
}
},
_applyRoughFrameRateConstraints: async function(localVideoTrack, constraints) {
async _applyRoughFrameRateConstraints(localVideoTrack, constraints) {
try {
await localVideoTrack.applyConstraints(constraints)
@ -159,7 +159,7 @@ VideoConstrainer.prototype = {
}
},
_getConstraintsForQuality: function(quality) {
_getConstraintsForQuality(quality) {
if (quality === QUALITY.HIGH) {
return {
width: {
@ -245,7 +245,7 @@ VideoConstrainer.prototype = {
}
},
_increaseMaxResolution: function(constraints) {
_increaseMaxResolution(constraints) {
let changed = false
if (constraints.width && constraints.width.max) {
@ -263,7 +263,7 @@ VideoConstrainer.prototype = {
return changed
},
_decreaseMinResolution: function(constraints) {
_decreaseMinResolution(constraints) {
let changed = false
if (constraints.width && constraints.width.min) {
@ -281,7 +281,7 @@ VideoConstrainer.prototype = {
return changed
},
_increaseMaxFrameRate: function(constraints) {
_increaseMaxFrameRate(constraints) {
let changed = false
if (constraints.frameRate && constraints.frameRate.max) {
@ -293,7 +293,7 @@ VideoConstrainer.prototype = {
return changed
},
_decreaseMinFrameRate: function(constraints) {
_decreaseMinFrameRate(constraints) {
let changed = false
if (constraints.frameRate && constraints.frameRate.min) {

12
src/utils/webrtc/analyzers/AverageStatValue.js

@ -70,12 +70,12 @@ function AverageStatValue(count, type = STAT_VALUE_TYPE.CUMULATIVE, lastValueWei
}
AverageStatValue.prototype = {
reset: function() {
reset() {
this._rawValues = []
this._relativeValues = []
},
add: function(value) {
add(value) {
if (this._rawValues.length === this._count) {
this._rawValues.shift()
this._relativeValues.shift()
@ -93,7 +93,7 @@ AverageStatValue.prototype = {
this._relativeValues.push(relativeValue)
},
getLastRawValue: function() {
getLastRawValue() {
if (this._rawValues.length < 1) {
return NaN
}
@ -101,7 +101,7 @@ AverageStatValue.prototype = {
return this._rawValues[this._rawValues.length - 1]
},
getLastRelativeValue: function() {
getLastRelativeValue() {
if (this._relativeValues.length < 1) {
return NaN
}
@ -109,11 +109,11 @@ AverageStatValue.prototype = {
return this._relativeValues[this._relativeValues.length - 1]
},
hasEnoughData: function() {
hasEnoughData() {
return this._rawValues.length === this._count
},
getWeightedAverage: function() {
getWeightedAverage() {
let weightedValues = 0
let weightsSum = 0

20
src/utils/webrtc/analyzers/CallAnalyzer.js

@ -77,25 +77,25 @@ export default function CallAnalyzer(localMediaModel, localCallParticipantModel,
}
CallAnalyzer.prototype = {
get: function(key) {
get(key) {
return this.attributes[key]
},
set: function(key, value) {
set(key, value) {
this.attributes[key] = value
this._trigger('change:' + key, [value])
},
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -107,7 +107,7 @@ CallAnalyzer.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -122,7 +122,7 @@ CallAnalyzer.prototype = {
}
},
destroy: function() {
destroy() {
if (this._localParticipantAnalyzer) {
this._localParticipantAnalyzer.off('change:senderConnectionQualityAudio', this._handleSenderConnectionQualityAudioChangeBound)
this._localParticipantAnalyzer.off('change:senderConnectionQualityVideo', this._handleSenderConnectionQualityVideoChangeBound)
@ -132,15 +132,15 @@ CallAnalyzer.prototype = {
}
},
_handleSenderConnectionQualityAudioChange: function(participantAnalyzer, senderConnectionQualityAudio) {
_handleSenderConnectionQualityAudioChange(participantAnalyzer, senderConnectionQualityAudio) {
this.set('senderConnectionQualityAudio', senderConnectionQualityAudio)
},
_handleSenderConnectionQualityVideoChange: function(participantAnalyzer, senderConnectionQualityVideo) {
_handleSenderConnectionQualityVideoChange(participantAnalyzer, senderConnectionQualityVideo) {
this.set('senderConnectionQualityVideo', senderConnectionQualityVideo)
},
_handleSenderConnectionQualityScreenChange: function(participantAnalyzer, senderConnectionQualityScreen) {
_handleSenderConnectionQualityScreenChange(participantAnalyzer, senderConnectionQualityScreen) {
this.set('senderConnectionQualityScreen', senderConnectionQualityScreen)
},

42
src/utils/webrtc/analyzers/ParticipantAnalyzer.js

@ -83,15 +83,15 @@ function ParticipantAnalyzer() {
}
ParticipantAnalyzer.prototype = {
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -103,7 +103,7 @@ ParticipantAnalyzer.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -118,7 +118,7 @@ ParticipantAnalyzer.prototype = {
}
},
destroy: function() {
destroy() {
if (this._localCallParticipantModel) {
this._localCallParticipantModel.off('change:peer', this._handlePeerChangeBound)
this._localCallParticipantModel.off('change:screenPeer', this._handleScreenPeerChangeBound)
@ -145,7 +145,7 @@ ParticipantAnalyzer.prototype = {
this._receiverScreenPeerConnectionAnalyzer = null
},
setSenderParticipant: function(localMediaModel, localCallParticipantModel) {
setSenderParticipant(localMediaModel, localCallParticipantModel) {
this.destroy()
this._localMediaModel = localMediaModel
@ -163,7 +163,7 @@ ParticipantAnalyzer.prototype = {
}
},
setReceiverParticipant: function(callParticipantModel) {
setReceiverParticipant(callParticipantModel) {
this.destroy()
this._callParticipantModel = callParticipantModel
@ -180,7 +180,7 @@ ParticipantAnalyzer.prototype = {
}
},
setSenderReceiverParticipant: function(localMediaModel, callParticipantModel) {
setSenderReceiverParticipant(localMediaModel, callParticipantModel) {
this.destroy()
this._localMediaModel = localMediaModel
@ -200,7 +200,7 @@ ParticipantAnalyzer.prototype = {
}
},
_handlePeerChange: function(model, peer) {
_handlePeerChange(model, peer) {
if (this._peer) {
this._stopListeningToAudioVideoChanges()
}
@ -212,7 +212,7 @@ ParticipantAnalyzer.prototype = {
}
},
_handleScreenPeerChange: function(model, screenPeer) {
_handleScreenPeerChange(model, screenPeer) {
if (this._screenPeer) {
this._stopListeningToScreenChanges()
}
@ -224,7 +224,7 @@ ParticipantAnalyzer.prototype = {
}
},
_startListeningToAudioVideoChanges: function() {
_startListeningToAudioVideoChanges() {
if (this._localMediaModel) {
this._senderPeerConnectionAnalyzer.setPeerConnection(this._peer.pc, PEER_DIRECTION.SENDER)
@ -252,7 +252,7 @@ ParticipantAnalyzer.prototype = {
}
},
_startListeningToScreenChanges: function() {
_startListeningToScreenChanges() {
if (this._localMediaModel) {
this._senderScreenPeerConnectionAnalyzer.setPeerConnection(this._screenPeer.pc, PEER_DIRECTION.SENDER)
@ -272,7 +272,7 @@ ParticipantAnalyzer.prototype = {
}
},
_stopListeningToAudioVideoChanges: function() {
_stopListeningToAudioVideoChanges() {
if (this._localMediaModel) {
this._senderPeerConnectionAnalyzer.setPeerConnection(null)
@ -294,7 +294,7 @@ ParticipantAnalyzer.prototype = {
}
},
_stopListeningToScreenChanges: function() {
_stopListeningToScreenChanges() {
if (this._localMediaModel) {
this._senderScreenPeerConnectionAnalyzer.setPeerConnection(null)
@ -308,7 +308,7 @@ ParticipantAnalyzer.prototype = {
}
},
_handleConnectionQualityAudioChange: function(peerConnectionAnalyzer, connectionQualityAudio) {
_handleConnectionQualityAudioChange(peerConnectionAnalyzer, connectionQualityAudio) {
if (peerConnectionAnalyzer === this._senderPeerConnectionAnalyzer) {
this._trigger('change:senderConnectionQualityAudio', [connectionQualityAudio])
} else if (peerConnectionAnalyzer === this._receiverPeerConnectionAnalyzer) {
@ -316,7 +316,7 @@ ParticipantAnalyzer.prototype = {
}
},
_handleConnectionQualityVideoChange: function(peerConnectionAnalyzer, connectionQualityVideo) {
_handleConnectionQualityVideoChange(peerConnectionAnalyzer, connectionQualityVideo) {
if (peerConnectionAnalyzer === this._senderPeerConnectionAnalyzer) {
this._trigger('change:senderConnectionQualityVideo', [connectionQualityVideo])
} else if (peerConnectionAnalyzer === this._receiverPeerConnectionAnalyzer) {
@ -324,7 +324,7 @@ ParticipantAnalyzer.prototype = {
}
},
_handleConnectionQualityScreenChange: function(peerConnectionAnalyzer, connectionQualityScreen) {
_handleConnectionQualityScreenChange(peerConnectionAnalyzer, connectionQualityScreen) {
if (peerConnectionAnalyzer === this._senderScreenPeerConnectionAnalyzer) {
this._trigger('change:senderConnectionQualityScreen', [connectionQualityScreen])
} else if (peerConnectionAnalyzer === this._receiverScreenPeerConnectionAnalyzer) {
@ -332,19 +332,19 @@ ParticipantAnalyzer.prototype = {
}
},
_handleSenderAudioEnabledChange: function(localMediaModel, audioEnabled) {
_handleSenderAudioEnabledChange(localMediaModel, audioEnabled) {
this._senderPeerConnectionAnalyzer.setAnalysisEnabledAudio(audioEnabled)
},
_handleSenderVideoEnabledChange: function(localMediaModel, videoEnabled) {
_handleSenderVideoEnabledChange(localMediaModel, videoEnabled) {
this._senderPeerConnectionAnalyzer.setAnalysisEnabledVideo(videoEnabled)
},
_handleReceiverAudioAvailableChange: function(callParticipantModel, audioAvailable) {
_handleReceiverAudioAvailableChange(callParticipantModel, audioAvailable) {
this._receiverPeerConnectionAnalyzer.setAnalysisEnabledAudio(audioAvailable)
},
_handleReceiverVideoAvailableChange: function(callParticipantModel, videoAvailable) {
_handleReceiverVideoAvailableChange(callParticipantModel, videoAvailable) {
this._receiverPeerConnectionAnalyzer.setAnalysisEnabledVideo(videoAvailable)
},

128
src/utils/webrtc/analyzers/PeerConnectionAnalyzer.js

@ -73,38 +73,38 @@ const PEER_DIRECTION = {
*/
function PeerConnectionAnalyzer() {
this._packets = {
'audio': new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
'video': new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
audio: new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
video: new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
}
this._packetsLost = {
'audio': new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
'video': new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
audio: new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
video: new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
}
this._packetsLostRatio = {
'audio': new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
'video': new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
audio: new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
video: new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
}
this._packetsPerSecond = {
'audio': new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
'video': new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
audio: new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
video: new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE),
}
// Latest values have a higher weight than the default one to better detect
// sudden changes in the round trip time, which can lead to discarded (but
// not lost) packets.
this._roundTripTime = {
'audio': new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE, 5),
'video': new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE, 5),
audio: new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE, 5),
video: new AverageStatValue(5, STAT_VALUE_TYPE.RELATIVE, 5),
}
// Only the last relative value is used, but as it is a cumulative value the
// previous one is needed as a base to calculate the last one.
this._timestamps = {
'audio': new AverageStatValue(2, STAT_VALUE_TYPE.CUMULATIVE),
'video': new AverageStatValue(2, STAT_VALUE_TYPE.CUMULATIVE),
audio: new AverageStatValue(2, STAT_VALUE_TYPE.CUMULATIVE),
video: new AverageStatValue(2, STAT_VALUE_TYPE.CUMULATIVE),
}
this._analysisEnabled = {
'audio': true,
'video': true,
audio: true,
video: true,
}
this._handlers = []
@ -122,15 +122,15 @@ function PeerConnectionAnalyzer() {
}
PeerConnectionAnalyzer.prototype = {
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -142,7 +142,7 @@ PeerConnectionAnalyzer.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -157,15 +157,15 @@ PeerConnectionAnalyzer.prototype = {
}
},
getConnectionQualityAudio: function() {
getConnectionQualityAudio() {
return this._connectionQualityAudio
},
getConnectionQualityVideo: function() {
getConnectionQualityVideo() {
return this._connectionQualityVideo
},
_setConnectionQualityAudio: function(connectionQualityAudio) {
_setConnectionQualityAudio(connectionQualityAudio) {
if (this._connectionQualityAudio === connectionQualityAudio) {
return
}
@ -174,7 +174,7 @@ PeerConnectionAnalyzer.prototype = {
this._trigger('change:connectionQualityAudio', [connectionQualityAudio])
},
_setConnectionQualityVideo: function(connectionQualityVideo) {
_setConnectionQualityVideo(connectionQualityVideo) {
if (this._connectionQualityVideo === connectionQualityVideo) {
return
}
@ -183,7 +183,7 @@ PeerConnectionAnalyzer.prototype = {
this._trigger('change:connectionQualityVideo', [connectionQualityVideo])
},
setPeerConnection: function(peerConnection, peerDirection = null) {
setPeerConnection(peerConnection, peerDirection = null) {
if (this._peerConnection) {
this._peerConnection.removeEventListener('iceconnectionstatechange', this._handleIceConnectionStateChangedBound)
this._stopGetStatsInterval()
@ -198,8 +198,8 @@ PeerConnectionAnalyzer.prototype = {
}
},
setAnalysisEnabledAudio: function(analysisEnabledAudio) {
this._analysisEnabled['audio'] = analysisEnabledAudio
setAnalysisEnabledAudio(analysisEnabledAudio) {
this._analysisEnabled.audio = analysisEnabledAudio
if (!analysisEnabledAudio) {
this._setConnectionQualityAudio(CONNECTION_QUALITY.UNKNOWN)
@ -208,8 +208,8 @@ PeerConnectionAnalyzer.prototype = {
}
},
setAnalysisEnabledVideo: function(analysisEnabledVideo) {
this._analysisEnabled['video'] = analysisEnabledVideo
setAnalysisEnabledVideo(analysisEnabledVideo) {
this._analysisEnabled.video = analysisEnabledVideo
if (!analysisEnabledVideo) {
this._setConnectionQualityVideo(CONNECTION_QUALITY.UNKNOWN)
@ -218,7 +218,7 @@ PeerConnectionAnalyzer.prototype = {
}
},
_resetStats: function(kind) {
_resetStats(kind) {
this._packets[kind].reset()
this._packetsLost[kind].reset()
this._packetsLostRatio[kind].reset()
@ -226,7 +226,7 @@ PeerConnectionAnalyzer.prototype = {
this._timestamps[kind].reset()
},
_handleIceConnectionStateChanged: function() {
_handleIceConnectionStateChanged() {
// Note that even if the ICE connection state is "disconnected" the
// connection is actually active, media is still transmitted, and the
// stats are properly updated.
@ -260,12 +260,12 @@ PeerConnectionAnalyzer.prototype = {
}, 1000)
},
_stopGetStatsInterval: function() {
_stopGetStatsInterval() {
window.clearInterval(this._getStatsInterval)
this._getStatsInterval = null
},
_processStats: function(stats) {
_processStats(stats) {
if (!this._peerConnection || (this._peerConnection.iceConnectionState !== 'connected' && this._peerConnection.iceConnectionState !== 'completed' && this._peerConnection.iceConnectionState !== 'disconnected')) {
return
}
@ -276,32 +276,32 @@ PeerConnectionAnalyzer.prototype = {
this._processReceiverStats(stats)
}
if (this._analysisEnabled['audio']) {
if (this._analysisEnabled.audio) {
this._setConnectionQualityAudio(this._calculateConnectionQualityAudio())
}
if (this._analysisEnabled['video']) {
if (this._analysisEnabled.video) {
this._setConnectionQualityVideo(this._calculateConnectionQualityVideo())
}
},
_processSenderStats: function(stats) {
_processSenderStats(stats) {
// Packets are calculated as "packetsReceived + packetsLost" or as
// "packetsSent" depending on the browser (see below).
const packets = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
// Packets stats for a sender are checked from the point of view of the
// receiver.
const packetsReceived = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const packetsLost = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
// If "packetsReceived" is not available (like in Chromium) use
@ -309,30 +309,30 @@ PeerConnectionAnalyzer.prototype = {
// the received statistics, so checking "packetsLost" against it may not
// be fully accurate, but it should be close enough.
const packetsSent = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
// Timestamp is set to "timestampReceived" or "timestampSent" depending
// on how "packets" were calculated.
const timestamp = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const timestampReceived = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const timestampSent = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const roundTripTime = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
for (const stat of stats.values()) {
@ -419,26 +419,26 @@ PeerConnectionAnalyzer.prototype = {
}
},
_processReceiverStats: function(stats) {
_processReceiverStats(stats) {
// Packets are calculated as "packetsReceived + packetsLost".
const packets = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const packetsReceived = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const packetsLost = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
const timestamp = {
'audio': -1,
'video': -1,
audio: -1,
video: -1,
}
for (const stat of stats.values()) {
@ -506,15 +506,15 @@ PeerConnectionAnalyzer.prototype = {
}
},
_calculateConnectionQualityAudio: function() {
return this._calculateConnectionQuality(this._packetsLostRatio['audio'], this._packetsPerSecond['audio'], this._roundTripTime['audio'])
_calculateConnectionQualityAudio() {
return this._calculateConnectionQuality(this._packetsLostRatio.audio, this._packetsPerSecond.audio, this._roundTripTime.audio)
},
_calculateConnectionQualityVideo: function() {
return this._calculateConnectionQuality(this._packetsLostRatio['video'], this._packetsPerSecond['video'], this._roundTripTime['video'])
_calculateConnectionQualityVideo() {
return this._calculateConnectionQuality(this._packetsLostRatio.video, this._packetsPerSecond.video, this._roundTripTime.video)
},
_calculateConnectionQuality: function(packetsLostRatio, packetsPerSecond, roundTripTime) {
_calculateConnectionQuality(packetsLostRatio, packetsPerSecond, roundTripTime) {
if (!packetsLostRatio.hasEnoughData() || !packetsPerSecond.hasEnoughData()) {
return CONNECTION_QUALITY.UNKNOWN
}

14
src/utils/webrtc/models/CallParticipantCollection.js

@ -31,15 +31,15 @@ export default function CallParticipantCollection() {
CallParticipantCollection.prototype = {
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -51,7 +51,7 @@ CallParticipantCollection.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -66,7 +66,7 @@ CallParticipantCollection.prototype = {
}
},
add: function(options) {
add(options) {
const callParticipantModel = new CallParticipantModel(options)
this.callParticipantModels.push(callParticipantModel)
@ -75,13 +75,13 @@ CallParticipantCollection.prototype = {
return callParticipantModel
},
get: function(peerId) {
get(peerId) {
return this.callParticipantModels.find(function(callParticipantModel) {
return callParticipantModel.attributes.peerId === peerId
})
},
remove: function(peerId) {
remove(peerId) {
const index = this.callParticipantModels.findIndex(function(callParticipantModel) {
return callParticipantModel.attributes.peerId === peerId
})

40
src/utils/webrtc/models/CallParticipantModel.js

@ -86,7 +86,7 @@ export default function CallParticipantModel(options) {
CallParticipantModel.prototype = {
destroy: function() {
destroy() {
if (this.get('peer')) {
this.get('peer').off('extendedIceConnectionStateChange', this._handleExtendedIceConnectionStateChangeBound)
}
@ -100,25 +100,25 @@ CallParticipantModel.prototype = {
this._webRtc.off('raisedHand', this._handleRaisedHandBound)
},
get: function(key) {
get(key) {
return this.attributes[key]
},
set: function(key, value) {
set(key, value) {
this.attributes[key] = value
this._trigger('change:' + key, [value])
},
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -130,7 +130,7 @@ CallParticipantModel.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -149,7 +149,7 @@ CallParticipantModel.prototype = {
}
},
_handlePeerStreamAdded: function(peer) {
_handlePeerStreamAdded(peer) {
if (this.get('peer') === peer) {
this.set('stream', this.get('peer').stream || null)
this.set('audioElement', attachMediaStream(this.get('stream'), null, { audio: true }))
@ -164,7 +164,7 @@ CallParticipantModel.prototype = {
}
},
_handlePeerStreamRemoved: function(peer) {
_handlePeerStreamRemoved(peer) {
if (this.get('peer') === peer) {
this.get('audioElement').srcObject = null
this.set('audioElement', null)
@ -177,7 +177,7 @@ CallParticipantModel.prototype = {
}
},
_handleNick: function(data) {
_handleNick(data) {
// The nick could be changed even if there is no Peer object.
if (this.get('peerId') !== data.id) {
return
@ -186,7 +186,7 @@ CallParticipantModel.prototype = {
this.set('name', data.name || null)
},
_handleMute: function(data) {
_handleMute(data) {
if (!this.get('peer') || this.get('peer').id !== data.id) {
return
}
@ -202,7 +202,7 @@ CallParticipantModel.prototype = {
}
},
forceMute: function() {
forceMute() {
if (!this.get('peer')) {
return
}
@ -217,7 +217,7 @@ CallParticipantModel.prototype = {
this._handleMute({ id: this.get('peer').id })
},
_handleUnmute: function(data) {
_handleUnmute(data) {
if (!this.get('peer') || this.get('peer').id !== data.id) {
return
}
@ -232,7 +232,7 @@ CallParticipantModel.prototype = {
}
},
_handleChannelMessage: function(peer, label, data) {
_handleChannelMessage(peer, label, data) {
if (!this.get('peer') || this.get('peer').id !== peer.id) {
return
}
@ -248,7 +248,7 @@ CallParticipantModel.prototype = {
}
},
_handleRaisedHand: function(data) {
_handleRaisedHand(data) {
// The hand could be raised even if there is no Peer object.
if (this.get('peerId') !== data.id) {
return
@ -257,7 +257,7 @@ CallParticipantModel.prototype = {
this.set('raisedHand', data.raised)
},
setPeer: function(peer) {
setPeer(peer) {
if (peer && this.get('peerId') !== peer.id) {
console.warn('Mismatch between stored peer ID and ID of given peer: ', this.get('peerId'), peer.id)
}
@ -285,7 +285,7 @@ CallParticipantModel.prototype = {
this.get('peer').on('extendedIceConnectionStateChange', this._handleExtendedIceConnectionStateChangeBound)
},
_handleExtendedIceConnectionStateChange: function(extendedIceConnectionState) {
_handleExtendedIceConnectionStateChange(extendedIceConnectionState) {
// Ensure that the name is set, as when the MCU is not used it will
// not be set later for registered users without microphone nor
// camera.
@ -336,7 +336,7 @@ CallParticipantModel.prototype = {
}
},
setScreenPeer: function(screenPeer) {
setScreenPeer(screenPeer) {
if (screenPeer && this.get('peerId') !== screenPeer.id) {
console.warn('Mismatch between stored peer ID and ID of given screen peer: ', this.get('peerId'), screenPeer.id)
}
@ -347,11 +347,11 @@ CallParticipantModel.prototype = {
this._handlePeerStreamAdded(this.get('screenPeer'))
},
setUserId: function(userId) {
setUserId(userId) {
this.set('userId', userId)
},
setNextcloudSessionId: function(nextcloudSessionId) {
setNextcloudSessionId(nextcloudSessionId) {
this.set('nextcloudSessionId', nextcloudSessionId)
},

22
src/utils/webrtc/models/LocalCallParticipantModel.js

@ -38,25 +38,25 @@ export default function LocalCallParticipantModel() {
LocalCallParticipantModel.prototype = {
get: function(key) {
get(key) {
return this.attributes[key]
},
set: function(key, value) {
set(key, value) {
this.attributes[key] = value
this._trigger('change:' + key, [value])
},
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -68,7 +68,7 @@ LocalCallParticipantModel.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -87,7 +87,7 @@ LocalCallParticipantModel.prototype = {
}
},
setWebRtc: function(webRtc) {
setWebRtc(webRtc) {
if (this._webRtc) {
this._webRtc.off('forcedMute', this._handleForcedMuteBound)
this._unwatchDisplayNameChange()
@ -102,7 +102,7 @@ LocalCallParticipantModel.prototype = {
this._unwatchDisplayNameChange = store.watch(state => state.actorStore.displayName, this.setGuestName.bind(this))
},
setPeer: function(peer) {
setPeer(peer) {
if (peer && this.get('peerId') !== peer.id) {
console.warn('Mismatch between stored peer ID and ID of given peer: ', this.get('peerId'), peer.id)
}
@ -110,7 +110,7 @@ LocalCallParticipantModel.prototype = {
this.set('peer', peer)
},
setScreenPeer: function(screenPeer) {
setScreenPeer(screenPeer) {
if (screenPeer && this.get('peerId') !== screenPeer.id) {
console.warn('Mismatch between stored peer ID and ID of given screen peer: ', this.get('peerId'), screenPeer.id)
}
@ -118,7 +118,7 @@ LocalCallParticipantModel.prototype = {
this.set('screenPeer', screenPeer)
},
setGuestName: function(guestName) {
setGuestName(guestName) {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -128,7 +128,7 @@ LocalCallParticipantModel.prototype = {
this._webRtc.webrtc.emit('nickChanged', guestName)
},
_handleForcedMute: function() {
_handleForcedMute() {
this._trigger('forcedMute')
},

68
src/utils/webrtc/models/LocalMediaModel.js

@ -63,25 +63,25 @@ export default function LocalMediaModel() {
LocalMediaModel.prototype = {
get: function(key) {
get(key) {
return this.attributes[key]
},
set: function(key, value) {
set(key, value) {
this.attributes[key] = value
this._trigger('change:' + key, [value])
},
on: function(event, handler) {
if (!this._handlers.hasOwnProperty(event)) {
on(event, handler) {
if (!Object.prototype.hasOwnProperty.call(this._handlers, event)) {
this._handlers[event] = [handler]
} else {
this._handlers[event].push(handler)
}
},
off: function(event, handler) {
off(event, handler) {
const handlers = this._handlers[event]
if (!handlers) {
return
@ -93,7 +93,7 @@ LocalMediaModel.prototype = {
}
},
_trigger: function(event, args) {
_trigger(event, args) {
let handlers = this._handlers[event]
if (!handlers) {
return
@ -108,11 +108,11 @@ LocalMediaModel.prototype = {
}
},
getWebRtc: function() {
getWebRtc() {
return this._webRtc
},
setWebRtc: function(webRtc) {
setWebRtc(webRtc) {
if (this._webRtc && this._webRtc.webrtc) {
this._webRtc.webrtc.off('localStreamRequested', this._handleLocalStreamRequestedBound)
this._webRtc.webrtc.off('localStream', this._handleLocalStreamBound)
@ -165,13 +165,13 @@ LocalMediaModel.prototype = {
this._webRtc.webrtc.on('localScreenStopped', this._handleLocalScreenStoppedBound)
},
_handleLocalStreamRequested: function(constraints, context) {
_handleLocalStreamRequested(constraints, context) {
if (context !== 'retry-no-video') {
this.set('localStreamRequestVideoError', null)
}
},
_handleLocalStream: function(configuration, localStream) {
_handleLocalStream(configuration, localStream) {
// Although there could be several local streams active at the same
// time (if the local media is started again before stopping it
// first) the methods to control them ("mute", "unmute",
@ -189,7 +189,7 @@ LocalMediaModel.prototype = {
this._setInitialMediaState(configuration)
},
_handleLocalStreamRequestFailedRetryNoVideo: function(constraints, error) {
_handleLocalStreamRequestFailedRetryNoVideo(constraints, error) {
if (!error || error.name === 'NotFoundError') {
return
}
@ -197,13 +197,13 @@ LocalMediaModel.prototype = {
this.set('localStreamRequestVideoError', error)
},
_handleLocalStreamRequestFailed: function() {
_handleLocalStreamRequestFailed() {
this.set('localStream', null)
this._setInitialMediaState({ audio: false, video: false })
},
_setInitialMediaState: function(configuration) {
_setInitialMediaState(configuration) {
if (configuration.audio !== false) {
this.set('audioAvailable', true)
if (this.get('audioEnabled')) {
@ -231,14 +231,14 @@ LocalMediaModel.prototype = {
this.set('raisedHand', { state: false, timestamp: Date.now() })
},
_handleLocalStreamChanged: function(localStream) {
_handleLocalStreamChanged(localStream) {
// Only a single local stream is assumed to be active at the same time.
this.set('localStream', localStream)
this._updateMediaAvailability(localStream)
},
_updateMediaAvailability: function(localStream) {
_updateMediaAvailability(localStream) {
if (localStream && localStream.getAudioTracks().length > 0) {
this.set('audioAvailable', true)
@ -268,7 +268,7 @@ LocalMediaModel.prototype = {
}
},
_handleLocalStreamStopped: function(localStream) {
_handleLocalStreamStopped(localStream) {
if (this.get('localStream') !== localStream) {
return
}
@ -281,7 +281,7 @@ LocalMediaModel.prototype = {
this.set('videoAvailable', false)
},
_handleAudioOn: function() {
_handleAudioOn() {
if (!this.get('audioAvailable')) {
return
}
@ -289,7 +289,7 @@ LocalMediaModel.prototype = {
this.set('audioEnabled', true)
},
_handleAudioOff: function() {
_handleAudioOff() {
if (!this.get('audioAvailable')) {
return
}
@ -297,7 +297,7 @@ LocalMediaModel.prototype = {
this.set('audioEnabled', false)
},
_handleVolumeChange: function(currentVolume, volumeThreshold) {
_handleVolumeChange(currentVolume, volumeThreshold) {
if (!this.get('audioAvailable')) {
return
}
@ -306,7 +306,7 @@ LocalMediaModel.prototype = {
this.set('volumeThreshold', volumeThreshold)
},
_handleSpeaking: function() {
_handleSpeaking() {
if (!this.get('audioAvailable')) {
return
}
@ -314,7 +314,7 @@ LocalMediaModel.prototype = {
this.set('speaking', true)
},
_handleStoppedSpeaking: function() {
_handleStoppedSpeaking() {
if (!this.get('audioAvailable')) {
return
}
@ -322,7 +322,7 @@ LocalMediaModel.prototype = {
this.set('speaking', false)
},
_handleSpeakingWhileMuted: function() {
_handleSpeakingWhileMuted() {
if (!this.get('audioAvailable')) {
return
}
@ -330,7 +330,7 @@ LocalMediaModel.prototype = {
this.set('speakingWhileMuted', true)
},
_handleStoppedSpeakingWhileMuted: function() {
_handleStoppedSpeakingWhileMuted() {
if (!this.get('audioAvailable')) {
return
}
@ -338,7 +338,7 @@ LocalMediaModel.prototype = {
this.set('speakingWhileMuted', false)
},
_handleVideoOn: function() {
_handleVideoOn() {
if (!this.get('videoAvailable')) {
return
}
@ -346,7 +346,7 @@ LocalMediaModel.prototype = {
this.set('videoEnabled', true)
},
_handleVideoOff: function() {
_handleVideoOff() {
if (!this.get('videoAvailable')) {
return
}
@ -354,15 +354,15 @@ LocalMediaModel.prototype = {
this.set('videoEnabled', false)
},
_handleLocalScreen: function(screen) {
_handleLocalScreen(screen) {
this.set('localScreen', screen)
},
_handleLocalScreenStopped: function() {
_handleLocalScreenStopped() {
this.set('localScreen', null)
},
enableAudio: function() {
enableAudio() {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -375,7 +375,7 @@ LocalMediaModel.prototype = {
this._webRtc.unmute()
},
disableAudio: function() {
disableAudio() {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -391,7 +391,7 @@ LocalMediaModel.prototype = {
this._webRtc.mute()
},
enableVideo: function() {
enableVideo() {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -404,7 +404,7 @@ LocalMediaModel.prototype = {
this._webRtc.resumeVideo()
},
disableVideo: function() {
disableVideo() {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -420,7 +420,7 @@ LocalMediaModel.prototype = {
this._webRtc.pauseVideo()
},
shareScreen: function(mode, callback) {
shareScreen(mode, callback) {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -428,7 +428,7 @@ LocalMediaModel.prototype = {
this._webRtc.shareScreen(mode, callback)
},
stopSharingScreen: function() {
stopSharingScreen() {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}
@ -441,7 +441,7 @@ LocalMediaModel.prototype = {
*
* @param {bool} raised true for raised, false for lowered
*/
toggleHandRaised: function(raised) {
toggleHandRaised(raised) {
if (!this._webRtc) {
throw new Error('WebRtc not initialized yet')
}

6
src/utils/webrtc/shims/MediaStream.js

@ -33,7 +33,7 @@ if (window.MediaStream) {
this.removeEventListener('addtrack', testAddTrackEvent)
if (!addTrackEventDispatched) {
this.dispatchEvent(new MediaStreamTrackEvent('addtrack', { track: track }))
this.dispatchEvent(new MediaStreamTrackEvent('addtrack', { track }))
}
}
@ -50,7 +50,7 @@ if (window.MediaStream) {
this.removeEventListener('removetrack', testRemoveTrackEvent)
if (!removeTrackEventDispatched) {
this.dispatchEvent(new MediaStreamTrackEvent('removetrack', { track: track }))
this.dispatchEvent(new MediaStreamTrackEvent('removetrack', { track }))
}
}
@ -90,7 +90,7 @@ if (window.MediaStream) {
this._listeners = []
}
if (!this._listeners.hasOwnProperty(type)) {
if (!Object.prototype.hasOwnProperty.call(this._listeners, type)) {
this._listeners[type] = [listener]
} else if (!this._listeners[type].includes(listener)) {
this._listeners[type].push(listener)

2
src/utils/webrtc/shims/MediaStreamTrack.js

@ -76,7 +76,7 @@ if (window.MediaStreamTrack) {
this._listeners = []
}
if (!this._listeners.hasOwnProperty(type)) {
if (!Object.prototype.hasOwnProperty.call(this._listeners, type)) {
this._listeners[type] = [listener]
} else if (!this._listeners[type].includes(listener)) {
this._listeners[type].push(listener)

18
src/utils/webrtc/simplewebrtc/getscreenmedia.js

@ -63,7 +63,8 @@ module.exports = function(mode, constraints, cb) {
error.name = 'PERMISSION_DENIED'
callback(error)
} else {
constraints = (hasConstraints && constraints) || { audio: false,
constraints = (hasConstraints && constraints) || {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
@ -71,7 +72,8 @@ module.exports = function(mode, constraints, cb) {
maxHeight: window.screen.height,
maxFrameRate: 3,
},
} }
},
}
constraints.video.mandatory.chromeMediaSourceId = data.sourceId
getUserMedia(constraints, callback)
}
@ -85,7 +87,8 @@ module.exports = function(mode, constraints, cb) {
error.name = 'CEF_GETSCREENMEDIA_CANCELED'
callback(error)
} else {
constraints = (hasConstraints && constraints) || { audio: false,
constraints = (hasConstraints && constraints) || {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
@ -97,7 +100,8 @@ module.exports = function(mode, constraints, cb) {
{ googLeakyBucket: true },
{ googTemporalLayeredScreencast: true },
],
} }
},
}
constraints.video.mandatory.chromeMediaSourceId = sourceId
getUserMedia(constraints, callback)
}
@ -180,7 +184,8 @@ typeof window !== 'undefined' && window.addEventListener('message', function(eve
error.name = 'PERMISSION_DENIED'
callback(error)
} else {
constraints = constraints || { audio: false,
constraints = constraints || {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
@ -192,7 +197,8 @@ typeof window !== 'undefined' && window.addEventListener('message', function(eve
{ googLeakyBucket: true },
{ googTemporalLayeredScreencast: true },
],
} }
},
}
constraints.video.mandatory.chromeMediaSourceId = event.data.sourceId
getUserMedia(constraints, callback)
}

6
src/utils/webrtc/simplewebrtc/localmedia.js

@ -37,7 +37,7 @@ function LocalMedia(opts) {
let item
for (item in opts) {
if (opts.hasOwnProperty(item)) {
if (Object.prototype.hasOwnProperty.call(opts, item)) {
this.config[item] = opts[item]
}
}
@ -769,7 +769,7 @@ LocalMedia.prototype._setupAudioMonitor = function(stream, harkOptions) {
self.emit('volumeChange', volume, threshold)
})
this._audioMonitors.push({ audio: audio, stream: stream })
this._audioMonitors.push({ audio, stream })
}
LocalMedia.prototype._stopAudioMonitor = function(stream) {
@ -788,7 +788,7 @@ LocalMedia.prototype._stopAudioMonitor = function(stream) {
// fallback for old .localScreen behaviour
Object.defineProperty(LocalMedia.prototype, 'localScreen', {
get: function() {
get() {
return this.localScreens.length > 0 ? this.localScreens[0] : null
},
})

8
src/utils/webrtc/simplewebrtc/peer.js

@ -263,7 +263,7 @@ Peer.prototype.send = function(messageType, payload) {
broadcaster: this.broadcaster,
roomType: this.type,
type: messageType,
payload: payload,
payload,
}
this.logger.log('sending', messageType, message)
this.parent.emit('message', message)
@ -274,12 +274,12 @@ Peer.prototype.send = function(messageType, payload) {
Peer.prototype.sendDirectly = function(channel, messageType, payload) {
const message = {
type: messageType,
payload: payload,
payload,
}
this.logger.log('sending via datachannel', channel, messageType, message)
const dc = this.getDataChannel(channel)
if (dc.readyState !== 'open') {
if (!this.pendingDCMessages.hasOwnProperty(channel)) {
if (!Object.prototype.hasOwnProperty.call(this.pendingDCMessages, channel)) {
this.pendingDCMessages[channel] = []
}
this.pendingDCMessages[channel].push(message)
@ -300,7 +300,7 @@ Peer.prototype._observeDataChannel = function(channel) {
channel.onopen = function() {
self.emit('channelOpen', channel)
// Check if there are messages that could not be send
if (self.pendingDCMessages.hasOwnProperty(channel.label)) {
if (Object.prototype.hasOwnProperty.call(self.pendingDCMessages, channel.label)) {
const pendingMessages = self.pendingDCMessages[channel.label].slice()
self.pendingDCMessages[channel.label] = []
for (let i = 0; i < pendingMessages.length; i++) {

2
src/utils/webrtc/simplewebrtc/simplewebrtc.js

@ -51,7 +51,7 @@ function SimpleWebRTC(opts) {
// set our config from options
for (item in options) {
if (options.hasOwnProperty(item)) {
if (Object.prototype.hasOwnProperty.call(options, item)) {
this.config[item] = options[item]
}
}

2
src/utils/webrtc/simplewebrtc/webrtc.js

@ -42,7 +42,7 @@ function WebRTC(opts) {
// set options
for (item in options) {
if (options.hasOwnProperty(item)) {
if (Object.prototype.hasOwnProperty.call(options, item)) {
this.config[item] = options[item]
}
}

20
src/utils/webrtc/webrtc.js

@ -196,7 +196,7 @@ function sendCurrentStateWithRepetition(timeout) {
function userHasStreams(user) {
let flags = user
if (flags.hasOwnProperty('inCall')) {
if (Object.prototype.hasOwnProperty.call(flags, 'inCall')) {
flags = flags.inCall
}
flags = flags || PARTICIPANT.CALL_FLAG.DISCONNECTED
@ -378,7 +378,7 @@ function usersInCallChanged(signaling, users) {
selfInCall = PARTICIPANT.CALL_FLAG.DISCONNECTED
let sessionId
for (sessionId in users) {
if (!users.hasOwnProperty(sessionId)) {
if (!Object.prototype.hasOwnProperty.call(users, sessionId)) {
continue
}
const user = users[sessionId]
@ -876,7 +876,7 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
peer.pc.getStats(track).then(function(stats) {
let result = false
stats.forEach(function(statsReport) {
if (result || statsReport.mediaType !== mediaType || !statsReport.hasOwnProperty('bytesReceived')) {
if (result || statsReport.mediaType !== mediaType || !Object.prototype.hasOwnProperty.call(statsReport, 'bytesReceived')) {
return
}
@ -1150,7 +1150,7 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
}
errorNotificationHandle = showError(message, {
timeout: timeout,
timeout,
})
})
@ -1170,7 +1170,7 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
webrtc.emit('mute', { id: peer.id, name: 'video' })
} else if (data.type === 'nickChanged') {
const name = typeof (data.payload) === 'string' ? data.payload : data.payload.name
webrtc.emit('nick', { id: peer.id, name: name })
webrtc.emit('nick', { id: peer.id, name })
} else if (data.type === 'speaking' || data.type === 'stoppedSpeaking') {
// Valid known messages, but handled elsewhere
} else {
@ -1207,7 +1207,7 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
to: sessionId,
roomType: 'video',
type: messageType,
payload: payload,
payload,
}
signaling.emit('message', message)
}
@ -1250,21 +1250,21 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local
payload = name
} else {
payload = {
'name': name,
'userid': signaling.settings.userId,
name,
userid: signaling.settings.userId,
}
}
sendDataChannelToAll('status', 'nickChanged', payload)
webrtc.sendToAll('nickChanged', { name: name })
webrtc.sendToAll('nickChanged', { name })
})
// Local screen added.
webrtc.on('localScreenAdded', function(/* video */) {
const currentSessionId = signaling.getSessionId()
for (const sessionId in usersInCallMapping) {
if (!usersInCallMapping.hasOwnProperty(sessionId)) {
if (!Object.prototype.hasOwnProperty.call(usersInCallMapping, sessionId)) {
continue
} else if (!usersInCallMapping[sessionId].inCall) {
continue

6
src/views/Dashboard.vue

@ -27,14 +27,14 @@
:loading="loading"
:show-items-and-empty-content="!hasImportantConversations"
:half-empty-content-message="t('spreed', 'No unread mentions')">
<template v-slot:default="{ item }">
<template #default="{ item }">
<DashboardWidgetItem
:target-url="getItemTargetUrl(item)"
:main-text="getMainText(item)"
:sub-text="getSubText(item)"
:item="item"
v-on="handlers">
<template v-slot:avatar>
<template #avatar>
<ConversationIcon
:item="item"
:hide-favorite="true"
@ -42,7 +42,7 @@
</template>
</DashboardWidgetItem>
</template>
<template v-slot:empty-content>
<template #empty-content>
<EmptyContent icon="icon-talk">
<template #desc>
{{ t('spreed', 'Say hi to your friends and colleagues!') }}

2
src/views/FlowPostToConversation.vue

@ -25,7 +25,7 @@ export default {
components: { Multiselect },
props: {
value: {
default: JSON.stringify({ 'm': '0', 't': '' }),
default: JSON.stringify({ m: '0', t: '' }),
type: String,
},
},

2
src/views/MainView.vue

@ -57,7 +57,7 @@ export default {
},
watch: {
isInLobby: function(isInLobby) {
isInLobby(isInLobby) {
// User is now blocked by the lobby
if (isInLobby && this.isInCall) {
this.$store.dispatch('leaveCall', {

36
stylelint.config.js

@ -1,31 +1,5 @@
module.exports = {
extends: 'stylelint-config-recommended-scss',
rules: {
indentation: 'tab',
'selector-type-no-unknown': null,
'number-leading-zero': null,
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'inside-block'],
},
],
'declaration-empty-line-before': [
'never',
{
ignore: ['after-declaration'],
},
],
'comment-empty-line-before': null,
'selector-type-case': null,
'selector-list-comma-newline-after': null,
'selector-pseudo-class-no-unknown': true,
'selector-pseudo-element-no-unknown': [true, {
ignorePseudoElements: ['v-deep'],
}],
'no-descending-specificity': null,
'string-quotes': 'single',
},
plugins: ['stylelint-scss'],
ignoreFiles: ['css/At.scss'],
}
const stylelintConfig = require('@nextcloud/stylelint-config')
stylelintConfig.ignoreFiles = ['css/At.scss']
module.exports = stylelintConfig

2
templates/index.php

@ -2,5 +2,5 @@
declare(strict_types=1);
script('spreed', 'talk');
script('spreed', 'talk-main');
style('spreed', 'merged');

2
templates/settings/admin-settings.php

@ -1,7 +1,7 @@
<?php
/** @var array $_ */
/** @var \OCP\IL10N $l */
script('spreed', ['admin-settings']);
script('spreed', ['talk-admin-settings']);
style('spreed', ['settings-admin']);
?>

119
webpack.common.js

@ -1,119 +0,0 @@
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const babelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const webpack = require('webpack')
module.exports = {
entry: {
'admin-settings': path.join(__dirname, 'src', 'mainAdminSettings.js'),
'collections': path.join(__dirname, 'src', 'collections.js'),
'talk': path.join(__dirname, 'src', 'main.js'),
'talk-files-sidebar': [
path.join(__dirname, 'src', 'mainFilesSidebar.js'),
path.join(__dirname, 'src', 'mainFilesSidebarLoader.js'),
],
'talk-public-share-auth-sidebar': path.join(__dirname, 'src', 'mainPublicShareAuthSidebar.js'),
'talk-public-share-sidebar': path.join(__dirname, 'src', 'mainPublicShareSidebar.js'),
'flow': path.join(__dirname, 'src', 'flow.js'),
'dashboard': path.join(__dirname, 'src', 'dashboard.js'),
'deck': path.join(__dirname, 'src', 'deck.js'),
},
output: {
path: path.resolve(__dirname, './js'),
publicPath: '/js/',
filename: '[name].js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(js|vue)$/,
use: 'eslint-loader',
exclude: /node_modules/,
enforce: 'pre',
},
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: babelLoaderExcludeNodeModulesExcept([
'@juliushaertl/vue-richtext',
'@nextcloud/event-bus',
'@nextcloud/vue',
'@nextcloud/vue-dashboard',
'ansi-regex',
'char-regex',
'color.js',
'fast-xml-parser',
'hot-patcher',
'nextcloud-vue-collections',
'semver',
'string-length',
'strip-ansi',
'tributejs',
'vue-resize',
'webdav',
]),
options: {
plugins: ['add-module-exports'],
presets: [
/**
* From "add-module-exports" documentation:
* "webpack doesn't perform commonjs transformation for
* codesplitting. Need to set commonjs conversion."
*/
['@babel/env', { modules: 'commonjs' }],
],
},
},
{
/**
* webrtc-adapter main module does no longer provide
* "module.exports", which is expected by some elements using it
* (like "attachmediastream"), so it needs to be added back with
* a plugin.
*/
test: /node_modules\/webrtc-adapter\/.*\.js$/,
loader: 'babel-loader',
options: {
plugins: ['add-module-exports'],
presets: [
/**
* From "add-module-exports" documentation:
* "webpack doesn't perform commonjs transformation for
* codesplitting. Need to set commonjs conversion."
*/
['@babel/env', { modules: 'commonjs' }],
],
},
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
},
],
},
plugins: [
new VueLoaderPlugin(),
new StyleLintPlugin({
files: ['**/*.vue'],
}),
// Make appName available as a constant
new webpack.DefinePlugin({ appName: JSON.stringify('talk') }),
],
resolve: {
extensions: ['*', '.js', '.vue'],
symlinks: false,
},
}

7
webpack.dev.js

@ -1,7 +0,0 @@
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'development',
devtool: '#cheap-source-map',
})

63
webpack.js

@ -0,0 +1,63 @@
const path = require('path')
const webpackConfig = require('@nextcloud/webpack-vue-config')
const webpackRules = require('@nextcloud/webpack-vue-config/rules')
const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
webpackConfig.entry = {
'admin-settings': path.join(__dirname, 'src', 'mainAdminSettings.js'),
collections: path.join(__dirname, 'src', 'collections.js'),
main: path.join(__dirname, 'src', 'main.js'),
'files-sidebar': [
path.join(__dirname, 'src', 'mainFilesSidebar.js'),
path.join(__dirname, 'src', 'mainFilesSidebarLoader.js'),
],
'public-share-auth-sidebar': path.join(__dirname, 'src', 'mainPublicShareAuthSidebar.js'),
'public-share-sidebar': path.join(__dirname, 'src', 'mainPublicShareSidebar.js'),
flow: path.join(__dirname, 'src', 'flow.js'),
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
deck: path.join(__dirname, 'src', 'deck.js'),
}
// Edit JS rule
webpackRules.RULE_JS.exclude = BabelLoaderExcludeNodeModulesExcept([
'@juliushaertl/vue-richtext',
'@nextcloud/event-bus',
'@nextcloud/vue-dashboard',
'ansi-regex',
'color.js',
'fast-xml-parser',
'hot-patcher',
'nextcloud-vue-collections',
'semver',
'strip-ansi',
'tributejs',
'vue-resize',
'webdav',
])
// Replaces rules array
webpackConfig.module.rules = Object.values(webpackRules)
webpackConfig.module.rules.push({
/**
* webrtc-adapter main module does no longer provide
* "module.exports", which is expected by some elements using it
* (like "attachmediastream"), so it needs to be added back with
* a plugin.
*/
test: /node_modules\/webrtc-adapter\/.*\.js$/,
loader: 'babel-loader',
options: {
plugins: ['add-module-exports'],
presets: [
/**
* From "add-module-exports" documentation:
* "webpack doesn't perform commonjs transformation for
* codesplitting. Need to set commonjs conversion."
*/
['@babel/env', { modules: 'commonjs' }],
],
},
})
module.exports = webpackConfig

7
webpack.prod.js

@ -1,7 +0,0 @@
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production',
devtool: '#source-map',
})
Loading…
Cancel
Save