diff --git a/src/components/CallView/CallView.vue b/src/components/CallView/CallView.vue index 4e252472dd6..1d494dc3854 100644 --- a/src/components/CallView/CallView.vue +++ b/src/components/CallView/CallView.vue @@ -149,7 +149,7 @@ import VideoVue from './shared/VideoVue.vue' import ViewerOverlayCallView from './shared/ViewerOverlayCallView.vue' import { SIMULCAST } from '../../constants.ts' import BrowserStorage from '../../services/BrowserStorage.js' -import { fetchPeers } from '../../services/callsService.js' +import { fetchPeers } from '../../services/callsService.ts' import { getTalkConfig } from '../../services/CapabilitiesManager.ts' import { EventBus } from '../../services/EventBus.ts' import { useCallViewStore } from '../../stores/callView.ts' diff --git a/src/components/LeftSidebar/CallPhoneDialog/CallPhoneDialog.vue b/src/components/LeftSidebar/CallPhoneDialog/CallPhoneDialog.vue index 1165ec83579..08ac09391c8 100644 --- a/src/components/LeftSidebar/CallPhoneDialog/CallPhoneDialog.vue +++ b/src/components/LeftSidebar/CallPhoneDialog/CallPhoneDialog.vue @@ -52,7 +52,7 @@ import LoadingComponent from '../../LoadingComponent.vue' import SelectPhoneNumber from '../../SelectPhoneNumber.vue' import DialpadPanel from '../../UIShared/DialpadPanel.vue' import { CONVERSATION, PARTICIPANT } from '../../../constants.ts' -import { callSIPDialOut } from '../../../services/callsService.js' +import { callSIPDialOut } from '../../../services/callsService.ts' import { hasTalkFeature } from '../../../services/CapabilitiesManager.ts' import { createLegacyConversation } from '../../../services/conversationsService.ts' import { addParticipant } from '../../../services/participantsService.js' diff --git a/src/components/RightSidebar/Participants/Participant.vue b/src/components/RightSidebar/Participants/Participant.vue index 26c94dd5d18..b934b41cbd4 100644 --- a/src/components/RightSidebar/Participants/Participant.vue +++ b/src/components/RightSidebar/Participants/Participant.vue @@ -352,7 +352,7 @@ import { callSIPMutePhone, callSIPSendDTMF, callSIPUnmutePhone, -} from '../../../services/callsService.js' +} from '../../../services/callsService.ts' import { hasTalkFeature } from '../../../services/CapabilitiesManager.ts' import { useActorStore } from '../../../stores/actor.ts' import { formattedTime } from '../../../utils/formattedTime.ts' diff --git a/src/components/TopBar/CallButton.vue b/src/components/TopBar/CallButton.vue index 81a38037feb..27078b168d5 100644 --- a/src/components/TopBar/CallButton.vue +++ b/src/components/TopBar/CallButton.vue @@ -103,7 +103,7 @@ import IconPhoneOff from 'vue-material-design-icons/PhoneOff.vue' import IconPhoneOutline from 'vue-material-design-icons/PhoneOutline.vue' import { useIsInCall } from '../../composables/useIsInCall.js' import { ATTENDEE, CALL, CONVERSATION, PARTICIPANT } from '../../constants.ts' -import { callSIPDialOut } from '../../services/callsService.js' +import { callSIPDialOut } from '../../services/callsService.ts' import { hasTalkFeature } from '../../services/CapabilitiesManager.ts' import { EventBus } from '../../services/EventBus.ts' import { useActorStore } from '../../stores/actor.ts' diff --git a/src/services/callsService.js b/src/services/callsService.ts similarity index 58% rename from src/services/callsService.js rename to src/services/callsService.ts index ef1fbb12a20..f2bc673feaf 100644 --- a/src/services/callsService.js +++ b/src/services/callsService.ts @@ -3,6 +3,12 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import type { + callSIPDialOutResponse, + CallSIPSendCallMessagePayload, + fetchPeersResponse, +} from '../types/index.ts' + import axios from '@nextcloud/axios' import { generateOcsUrl } from '@nextcloud/router' import { PARTICIPANT } from '../constants.ts' @@ -23,25 +29,25 @@ import { * media is allowed to be sent, but it is not guaranteed to be sent. For * example, if WITH_VIDEO is provided but the device does not have a camera. * - * @param {string} token The token of the call to be joined. - * @param {number} flags The available PARTICIPANT.CALL_FLAG for this participants - * @param {boolean} silent Whether the call should trigger a notifications and + * @param token The token of the call to be joined. + * @param flags The available PARTICIPANT.CALL_FLAG for this participants + * @param silent Whether the call should trigger a notifications and * sound for other participants or not - * @param {boolean} recordingConsent Whether the participant gave their consent to be recorded - * @param {Array} silentFor List of participants that should not receive a notification about the call - * @return {Promise} The actual flags based on the available media + * @param recordingConsent Whether the participant gave their consent to be recorded + * @param silentFor List of participants that should not receive a notification about the call + * @return The actual flags based on the available media */ -const joinCall = async function(token, flags, silent, recordingConsent, silentFor) { +const joinCall = async function(token: string, flags: number, silent: boolean, recordingConsent: boolean, silentFor: string[]): Promise { return signalingJoinCall(token, flags, silent, recordingConsent, silentFor) } /** * Leave a call as participant * - * @param {string} token The token of the call to be left - * @param {boolean} all Whether to end the meeting for all + * @param token The token of the call to be left + * @param all Whether to end the meeting for all */ -const leaveCall = async function(token, all = false) { +const leaveCall = async function(token: string, all: boolean = false) { try { await signalingLeaveCall(token, all) } catch (error) { @@ -49,73 +55,73 @@ const leaveCall = async function(token, all = false) { } } -const fetchPeers = async function(token, options) { +const fetchPeers = async function(token: string, options: object): fetchPeersResponse { return await axios.get(generateOcsUrl('apps/spreed/api/v4/call/{token}', { token }), options) } /** * Call participant via SIP DialOut * - * @param {string} token The token of the conversation - * @param {number} attendeeId The attendee id to call to via SIP + * @param token The token of the conversation + * @param attendeeId The attendee id to call to via SIP */ -const callSIPDialOut = async function(token, attendeeId) { +const callSIPDialOut = async function(token: string, attendeeId: number): callSIPDialOutResponse { return axios.post(generateOcsUrl('apps/spreed/api/v4/call/{token}/dialout/{attendeeId}', { token, attendeeId })) } /** * Hang up for phone participant * - * @param {string} sessionId Session id of receiver + * @param sessionId Session id of receiver */ -const callSIPHangupPhone = async function(sessionId) { +const callSIPHangupPhone = async function(sessionId: string) { await callSIPSendCallMessage(sessionId, { type: 'hangup' }) } /** * Mute phone participant (prevent from speaking) * - * @param {string} sessionId Session id of receiver + * @param sessionId Session id of receiver */ -const callSIPMutePhone = async function(sessionId) { +const callSIPMutePhone = async function(sessionId: string) { await callSIPSendCallMessage(sessionId, { type: 'mute', audio: PARTICIPANT.SIP_DIALOUT_FLAG.MUTE_MICROPHONE }) } /** * Unmute phone participant (allow to speaking and listening) * - * @param {string} sessionId Session id of receiver + * @param sessionId Session id of receiver */ -const callSIPUnmutePhone = async function(sessionId) { +const callSIPUnmutePhone = async function(sessionId: string) { await callSIPSendCallMessage(sessionId, { type: 'mute', audio: PARTICIPANT.SIP_DIALOUT_FLAG.NONE }) } /** * Hold a participant (prevent from listening) * - * @param {string} sessionId Session id of receiver + * @param sessionId Session id of receiver */ -const callSIPHoldPhone = async function(sessionId) { +const callSIPHoldPhone = async function(sessionId: string) { await callSIPSendCallMessage(sessionId, { type: 'mute', audio: PARTICIPANT.SIP_DIALOUT_FLAG.MUTE_MICROPHONE | PARTICIPANT.SIP_DIALOUT_FLAG.MUTE_SPEAKER }) } /** * Send DTMF digits one per message (allowed characters: 0-9, *, #) * - * @param {string} sessionId Session id of receiver - * @param {string} digit DTMF digit to send + * @param sessionId Session id of receiver + * @param digit DTMF digit to send */ -const callSIPSendDTMF = async function(sessionId, digit) { +const callSIPSendDTMF = async function(sessionId: string, digit: string) { await callSIPSendCallMessage(sessionId, { type: 'dtmf', digit }) } /** * Send a message to SIP via signaling * - * @param {string} sessionId Session id of receiver - * @param {object} data Payload for message to be sent + * @param sessionId Session id of receiver + * @param data Payload for message to be sent */ -const callSIPSendCallMessage = async function(sessionId, data) { +const callSIPSendCallMessage = async function(sessionId: string, data: CallSIPSendCallMessagePayload) { if (!sessionId) { console.debug('Session ID has not been provided') return diff --git a/src/store/participantsStore.js b/src/store/participantsStore.js index 574186ab8bc..51b36081b74 100644 --- a/src/store/participantsStore.js +++ b/src/store/participantsStore.js @@ -13,7 +13,7 @@ import { banActor } from '../services/banService.ts' import { joinCall, leaveCall, -} from '../services/callsService.js' +} from '../services/callsService.ts' import { hasTalkFeature, setRemoteCapabilities } from '../services/CapabilitiesManager.ts' import { EventBus } from '../services/EventBus.ts' import { diff --git a/src/store/participantsStore.spec.js b/src/store/participantsStore.spec.js index f8724d362c4..2c6683782bb 100644 --- a/src/store/participantsStore.spec.js +++ b/src/store/participantsStore.spec.js @@ -14,7 +14,7 @@ import { PARTICIPANT } from '../constants.ts' import { joinCall, leaveCall, -} from '../services/callsService.js' +} from '../services/callsService.ts' import { fetchConversation } from '../services/conversationsService.ts' import { EventBus } from '../services/EventBus.ts' import { diff --git a/src/types/index.ts b/src/types/index.ts index b86085d0dd6..6db9bfb03df 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -204,6 +204,10 @@ export type JoinRoomFullResponse = { data: operations['room-join-room']['responses']['200']['content']['application/json'] } +// Call +export type fetchPeersResponse = ApiResponse +export type callSIPDialOutResponse = ApiResponse + // Participants export type ParticipantStatus = { status?: string | null @@ -411,6 +415,14 @@ export type UserFilterObject = { showUserStatus: boolean } +// SIP call message payload +// TODO unify this type +// hint: check TYPE_ENCRYPTION* in "encryption.js" +export type CallSIPSendCallMessagePayload = + | { type: 'control' | 'hangup' } + | { type: 'dtmf', digit: string } + | { type: 'mute', audio: number } + // Autocomplete API export type { AutocompleteParams,