diff --git a/src/components/CallView/CallView.vue b/src/components/CallView/CallView.vue index 916952fbcb2..3cac3e1018a 100644 --- a/src/components/CallView/CallView.vue +++ b/src/components/CallView/CallView.vue @@ -138,6 +138,7 @@ import { SIMULCAST } from '../../constants.js' import { fetchPeers } from '../../services/callsService.js' import { getTalkConfig } from '../../services/CapabilitiesManager.ts' import { EventBus } from '../../services/EventBus.js' +import { useSettingsStore } from '../../stores/settings.js' import { localMediaModel, localCallParticipantModel, callParticipantCollection } from '../../utils/webrtc/index.js' import RemoteVideoBlocker from '../../utils/webrtc/RemoteVideoBlocker.js' @@ -173,6 +174,12 @@ export default { }, setup() { + const settingsStore = useSettingsStore() + const startWithoutMediaEnabled = settingsStore.startWithoutMedia + if (startWithoutMediaEnabled) { + localMediaModel.disableAudio() + localMediaModel.disableVideo() + } return { localMediaModel, localCallParticipantModel, diff --git a/src/components/SettingsDialog/SettingsDialog.vue b/src/components/SettingsDialog/SettingsDialog.vue index cc5a6ba5795..2d423d03cd9 100644 --- a/src/components/SettingsDialog/SettingsDialog.vue +++ b/src/components/SettingsDialog/SettingsDialog.vue @@ -20,6 +20,14 @@ :name="t('spreed', 'Choose devices')" class="app-settings-section"> + + {{ t('spreed', 'Turn off camera and microphone by default when joining a call') }} + diff --git a/src/services/settingsService.js b/src/services/settingsService.js index 9d6f768d042..684e8a8babe 100644 --- a/src/services/settingsService.js +++ b/src/services/settingsService.js @@ -74,10 +74,29 @@ const setPlaySounds = async function(hasUserAccount, value) { } } +const setStartWithoutMedia = async function(value) { + await setUserConfig('spreed', 'calls_start_without_media', value ? 'yes' : 'no') +} + +/** + * Set user config using provisioning API + * + * @param {string} appId - app id + * @param {string} configKey - key of the config to set + * @param {string} configValue - value to set + */ +const setUserConfig = async function(appId, configKey, configValue) { + await axios.post(generateOcsUrl('apps/provisioning_api/api/v1/config/users/{appId}/{configKey}', { appId, configKey }), { + configValue, + }) +} + export { setAttachmentFolder, setReadStatusPrivacy, setTypingStatusPrivacy, setSIPSettings, setPlaySounds, + setStartWithoutMedia, + setUserConfig, } diff --git a/src/stores/__tests__/settings.spec.js b/src/stores/__tests__/settings.spec.js index c8f1cf2574d..baa9cbb8ba2 100644 --- a/src/stores/__tests__/settings.spec.js +++ b/src/stores/__tests__/settings.spec.js @@ -70,7 +70,9 @@ describe('settingsStore', () => { // Assert expect(results).toEqual([true, false]) - expect(BrowserStorage.getItem).not.toHaveBeenCalled() + // It's always called at least once : BrowserStorage.getItem('cachedConversations') + // +1 + expect(BrowserStorage.getItem).toHaveBeenCalledTimes(1) }) it('shows correct values received from BrowserStorage', () => { @@ -87,10 +89,11 @@ describe('settingsStore', () => { // Assert expect(results).toEqual([true, true, false]) - expect(BrowserStorage.getItem).toHaveBeenCalledTimes(3) - expect(BrowserStorage.getItem).toHaveBeenNthCalledWith(1, 'showMediaSettings_token-1') - expect(BrowserStorage.getItem).toHaveBeenNthCalledWith(2, 'showMediaSettings_token-2') - expect(BrowserStorage.getItem).toHaveBeenNthCalledWith(3, 'showMediaSettings_token-3') + // It's always called at least once : BrowserStorage.getItem('cachedConversations') + expect(BrowserStorage.getItem).toHaveBeenCalledTimes(4) // 1 + 3 + expect(BrowserStorage.getItem).toHaveBeenNthCalledWith(2, 'showMediaSettings_token-1') + expect(BrowserStorage.getItem).toHaveBeenNthCalledWith(3, 'showMediaSettings_token-2') + expect(BrowserStorage.getItem).toHaveBeenNthCalledWith(4, 'showMediaSettings_token-3') }) it('updates values correctly', async () => { @@ -106,7 +109,8 @@ describe('settingsStore', () => { // Assert expect(results).toEqual([false, true]) - expect(BrowserStorage.getItem).not.toHaveBeenCalled() + // It's always called at least once : BrowserStorage.getItem('cachedConversations') + expect(BrowserStorage.getItem).toHaveBeenCalledTimes(1) expect(BrowserStorage.setItem).toHaveBeenCalledTimes(2) expect(BrowserStorage.setItem).toHaveBeenNthCalledWith(1, 'showMediaSettings_token-1', 'false') expect(BrowserStorage.setItem).toHaveBeenNthCalledWith(2, 'showMediaSettings_token-2', 'true') diff --git a/src/stores/settings.js b/src/stores/settings.js index bfbfa416f20..5eb93f533ef 100644 --- a/src/stores/settings.js +++ b/src/stores/settings.js @@ -10,7 +10,12 @@ import { loadState } from '@nextcloud/initial-state' import { PRIVACY } from '../constants.js' import BrowserStorage from '../services/BrowserStorage.js' -import { setReadStatusPrivacy, setTypingStatusPrivacy } from '../services/settingsService.js' +import { getTalkConfig } from '../services/CapabilitiesManager.ts' +import { + setReadStatusPrivacy, + setTypingStatusPrivacy, + setStartWithoutMedia +} from '../services/settingsService.js' /** * @typedef {string} Token @@ -33,7 +38,8 @@ export const useSettingsStore = defineStore('settings', { state: () => ({ readStatusPrivacy: loadState('spreed', 'read_status_privacy', PRIVACY.PRIVATE), typingStatusPrivacy: loadState('spreed', 'typing_privacy', PRIVACY.PRIVATE), - showMediaSettings: {} + showMediaSettings: {}, + startWithoutMedia: getTalkConfig('local', 'call', 'start-without-media'), }), getters: { @@ -96,5 +102,10 @@ export const useSettingsStore = defineStore('settings', { } Vue.set(this.showMediaSettings, token, value) }, + + async setStartWithoutMedia(value) { + await setStartWithoutMedia(value) + this.startWithoutMedia = value + }, }, })