@daily-co/daily-js
Advanced tools
Comparing version 0.9.993-beta.4 to 0.9.993-beta.5
@@ -15,3 +15,16 @@ // Type definitions for daily-js 0.9.992 | ||
export type DailyLanguage = 'de' | 'en' | 'fi' | 'fr' | 'nl' | 'pt' | 'pl'; | ||
export type DailyLanguage = | ||
| 'de' | ||
| 'en' | ||
| 'fi' | ||
| 'fr' | ||
| 'nl' | ||
| 'pt' | ||
| 'pl' | ||
| 'sv' | ||
| 'es' | ||
| 'tr' | ||
| 'it' | ||
| 'ka' | ||
| 'jp'; | ||
@@ -381,2 +394,4 @@ export type DailyEvent = | ||
export type DailyNativeInCallAudioMode = 'video' | 'voice'; | ||
export interface DailyCallFactory { | ||
@@ -436,4 +451,6 @@ createCallObject(properties?: DailyCallOptions): DailyCall; | ||
getInputDevices(): Promise<DailyDeviceInfos>; | ||
nativeInCallAudioMode(): string; | ||
setNativeInCallAudioMode(inCallAudioMode: 'video' | 'voice'): DailyCall; | ||
nativeInCallAudioMode(): DailyNativeInCallAudioMode; | ||
setNativeInCallAudioMode( | ||
inCallAudioMode: DailyNativeInCallAudioMode | ||
): DailyCall; | ||
load(properties?: DailyLoadOptions): Promise<void>; | ||
@@ -440,0 +457,0 @@ startScreenShare(captureOptions?: DailyScreenCaptureOptions): void; |
{ | ||
"name": "@daily-co/daily-js", | ||
"version": "0.9.993-beta.4", | ||
"version": "0.9.993-beta.5", | ||
"engines": { | ||
@@ -30,5 +30,7 @@ "node": ">=10.0.0" | ||
"@babel/core": "^7.8.3", | ||
"@babel/plugin-proposal-class-properties": "^7.10.4", | ||
"@babel/plugin-transform-modules-commonjs": "^7.8.3", | ||
"@babel/plugin-transform-runtime": "^7.8.3", | ||
"@babel/preset-env": "^7.8.3", | ||
"@rollup/plugin-babel": "^5.2.1", | ||
"@rollup/plugin-replace": "^2.3.2", | ||
@@ -35,0 +37,0 @@ "babel-cli": "^6.26.0", |
import replace from '@rollup/plugin-replace'; | ||
import resolve from 'rollup-plugin-node-resolve'; | ||
import babel from '@rollup/plugin-babel'; | ||
import commonJS from 'rollup-plugin-commonjs'; | ||
@@ -19,2 +20,11 @@ import { terser } from 'rollup-plugin-terser'; | ||
}), | ||
babel({ | ||
exclude: 'node_modules/**', | ||
babelHelpers: 'runtime', | ||
presets: ['@babel/preset-env'], | ||
plugins: [ | ||
'@babel/plugin-transform-runtime', | ||
'@babel/plugin-proposal-class-properties', | ||
], | ||
}), | ||
commonJS({ | ||
@@ -21,0 +31,0 @@ include: 'node_modules/**', |
@@ -146,2 +146,7 @@ import EventEmitter from 'events'; | ||
}, | ||
reactNativeConfig: { | ||
validate: validateReactNativeConfig, | ||
help: | ||
'reactNativeConfig should look like { androidInCallNotification: { title: string, subtitle: string, iconName: string, disableForCustomOverride: boolean } }, all optional', | ||
}, | ||
lang: { | ||
@@ -439,2 +444,28 @@ validate: (lang) => { | ||
// add native event listeners | ||
if (isReactNative()) { | ||
const nativeUtils = this.nativeUtils(); | ||
if ( | ||
!( | ||
nativeUtils.addAudioFocusChangeListener && | ||
nativeUtils.removeAudioFocusChangeListener && | ||
nativeUtils.addAppActiveStateChangeListener && | ||
nativeUtils.removeAppActiveStateChangeListener | ||
) | ||
) { | ||
console.warn( | ||
'expected (add|remove)(AudioFocus|AppActiveState)ChangeListener to be available in React Native' | ||
); | ||
} | ||
// audio focus event, used for auto-muting mic | ||
this._hasNativeAudioFocus = true; | ||
nativeUtils.addAudioFocusChangeListener( | ||
this.handleNativeAudioFocusChange | ||
); | ||
// app active state event, used for auto-muting cam | ||
nativeUtils.addAppActiveStateChangeListener( | ||
this.handleNativeAppActiveStateChange | ||
); | ||
} | ||
this._messageChannel.addListenerForMessagesFromCallMachine( | ||
@@ -467,2 +498,13 @@ this.handleMessageFromCallMachine, | ||
this._messageChannel.removeListener(this.handleMessageFromCallMachine); | ||
// tear down native event listeners | ||
if (isReactNative()) { | ||
const nativeUtils = this.nativeUtils(); | ||
nativeUtils.removeAudioFocusChangeListener( | ||
this.handleNativeAudioFocusChange | ||
); | ||
nativeUtils.removeAppActiveStateChangeListener( | ||
this.handleNativeAppActiveStateChange | ||
); | ||
} | ||
} | ||
@@ -895,2 +937,3 @@ | ||
this._participants[id] = { ...participants[id] }; | ||
this.toggleParticipantAudioBasedOnNativeAudioFocus(); | ||
} | ||
@@ -994,3 +1037,2 @@ } | ||
getNetworkStats() { | ||
methodNotSupportedInReactNative(); | ||
if (this._meetingState !== DAILY_STATE_JOINED) { | ||
@@ -1048,2 +1090,3 @@ let stats = { latest: {} }; | ||
async enumerateDevices() { | ||
methodNotSupportedInReactNative(); | ||
if (this._callObjectMode) { | ||
@@ -1380,2 +1423,3 @@ let raw = await navigator.mediaDevices.enumerateDevices(); | ||
this._participants[id] = { ...msg.participant }; | ||
this.toggleParticipantAudioBasedOnNativeAudioFocus(); | ||
try { | ||
@@ -1856,2 +1900,3 @@ this.emit(msg.action, msg); | ||
this.updateDeviceAudioMode(oldMeetingState); | ||
this.updateShowAndroidOngoingMeetingNotification(oldMeetingState); | ||
} | ||
@@ -1868,3 +1913,2 @@ | ||
} | ||
console.log('[pk][daily-js] updateKeepDeviceAwake: ', keepDeviceAwake); | ||
this.nativeUtils().setKeepDeviceAwake(keepDeviceAwake, this._callFrameId); | ||
@@ -1889,13 +1933,60 @@ } | ||
: NATIVE_AUDIO_MODE_IDLE; | ||
console.log('[pk][daily-js] setAudioMode: ', useInCallAudioMode); | ||
this.nativeUtils().setAudioMode(inCallAudioMode); | ||
} | ||
shouldDeviceStayAwake(meetingState) { | ||
return ![DAILY_STATE_NEW, DAILY_STATE_LEFT, DAILY_STATE_ERROR].includes( | ||
meetingState | ||
// Note: notification properties can't be changed while it is ongoing | ||
updateShowAndroidOngoingMeetingNotification(oldMeetingState) { | ||
// Check that we're React Native and that the Android-only method exists | ||
if ( | ||
!(isReactNative() && this.nativeUtils().setShowOngoingMeetingNotification) | ||
) { | ||
return; | ||
} | ||
const oldShowNotification = this.shouldShowAndroidOngoingMeetingNotification( | ||
oldMeetingState | ||
); | ||
let showNotification = this.shouldShowAndroidOngoingMeetingNotification( | ||
this._meetingState | ||
); | ||
if (oldShowNotification === showNotification) { | ||
return; | ||
} | ||
// Use current this.properties to customize notification behavior | ||
let title, subtitle, iconName, disableForCustomOverride; | ||
if ( | ||
this.properties.reactNativeConfig && | ||
this.properties.reactNativeConfig.androidInCallNotification | ||
) { | ||
({ | ||
title, | ||
subtitle, | ||
iconName, | ||
disableForCustomOverride, | ||
} = this.properties.reactNativeConfig.androidInCallNotification); | ||
} | ||
if (disableForCustomOverride) { | ||
showNotification = false; | ||
} | ||
this.nativeUtils().setShowOngoingMeetingNotification( | ||
showNotification, | ||
title, | ||
subtitle, | ||
iconName, | ||
this._callFrameId | ||
); | ||
} | ||
shouldDeviceStayAwake(meetingState) { | ||
return this.isMeetingPendingOrOngoing(meetingState); | ||
} | ||
shouldDeviceUseInCallAudioMode(meetingState) { | ||
return this.isMeetingPendingOrOngoing(meetingState); | ||
} | ||
shouldShowAndroidOngoingMeetingNotification(meetingState) { | ||
return this.isMeetingPendingOrOngoing(meetingState); | ||
} | ||
isMeetingPendingOrOngoing(meetingState) { | ||
return ![DAILY_STATE_NEW, DAILY_STATE_LEFT, DAILY_STATE_ERROR].includes( | ||
@@ -1906,2 +1997,53 @@ meetingState | ||
handleNativeAppActiveStateChange = (isActive) => { | ||
if (isActive) { | ||
// If cam was unmuted before losing focus, unmute | ||
// (Note this is assumption is not perfect, since theoretically an app | ||
// could unmute while in the background, but it's decent for now) | ||
if (this.camUnmutedBeforeLosingNativeActiveState) { | ||
this.setLocalVideo(true); | ||
} | ||
} else { | ||
this.camUnmutedBeforeLosingNativeActiveState = this.localVideo(); | ||
this.setLocalVideo(false); | ||
} | ||
}; | ||
handleNativeAudioFocusChange = (hasFocus) => { | ||
this._hasNativeAudioFocus = hasFocus; | ||
// toggle participant audio if needed | ||
this.toggleParticipantAudioBasedOnNativeAudioFocus(); | ||
// toggle mic mute if needed | ||
if (this._hasNativeAudioFocus) { | ||
// If mic was unmuted before losing focus, unmute | ||
// (Note this is assumption is not perfect, since theoretically an app | ||
// could unmute while in the background, but it's decent for now) | ||
if (this.micUnmutedBeforeLosingNativeAudioFocus) { | ||
this.setLocalAudio(true); | ||
} | ||
} else { | ||
this.micUnmutedBeforeLosingNativeAudioFocus = this.localAudio(); | ||
this.setLocalAudio(false); | ||
} | ||
}; | ||
toggleParticipantAudioBasedOnNativeAudioFocus() { | ||
if (!isReactNative()) { | ||
return; | ||
} | ||
// Need to access store directly since when participant muted their audio we | ||
// don't have access to their audio tracks in this._participants | ||
const state = store.getState(); | ||
for (const streamId in state.streams) { | ||
const streamData = state.streams[streamId]; | ||
if ( | ||
streamData && | ||
streamData.pendingTrack && | ||
streamData.pendingTrack.kind === 'audio' | ||
) { | ||
streamData.pendingTrack.enabled = this._hasNativeAudioFocus; | ||
} | ||
} | ||
} | ||
absoluteUrl(url) { | ||
@@ -1981,1 +2123,41 @@ if ('undefined' === typeof url) { | ||
} | ||
// Note: this may get more complex in the future, in which case we may want | ||
// to revisit how FRAME_PROPS validation is done. Today it's hard to provide | ||
// validation help messages about unrecognized nested properties. | ||
function validateReactNativeConfig(config) { | ||
for (const key in config) { | ||
switch (key) { | ||
case 'androidInCallNotification': | ||
if (!validateAndroidInCallNotificationConfig(config[key])) { | ||
return false; | ||
} | ||
break; | ||
default: | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
function validateAndroidInCallNotificationConfig(config) { | ||
for (const key in config) { | ||
switch (key) { | ||
case 'disableForCustomOverride': | ||
if (typeof config[key] !== 'boolean') { | ||
return false; | ||
} | ||
break; | ||
case 'title': | ||
case 'subtitle': | ||
case 'iconName': | ||
if (typeof config[key] !== 'string') { | ||
return false; | ||
} | ||
break; | ||
default: | ||
return false; | ||
} | ||
} | ||
return true; | ||
} |
@@ -34,3 +34,6 @@ // todo: add debug target | ||
presets: ['@babel/preset-env'], | ||
plugins: ['@babel/plugin-transform-runtime'], | ||
plugins: [ | ||
'@babel/plugin-transform-runtime', | ||
'@babel/plugin-proposal-class-properties', | ||
], | ||
}, | ||
@@ -37,0 +40,0 @@ }, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
430541
3895
17
13