Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions packages/mobile-client/src/constraints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Google-specific audio processing constraints (legacy Chrome constraints).
* These are not part of the standard MediaTrackConstraints type but are supported by WebRTC implementations.
*/
interface GoogleAudioConstraints {
googEchoCancellation?: string | boolean;
googAutoGainControl?: string | boolean;
googNoiseSuppression?: string | boolean;
googTypingNoiseDetection?: string | boolean;
googHighpassFilter?: string | boolean;
}
Comment on lines +5 to +11
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GoogleAudioConstraints interface allows both string and boolean values (e.g., googEchoCancellation?: string | boolean), but the DEFAULT_MOBILE_AUDIO_CONSTRAINTS only uses boolean values (all set to true). If string values are not needed or supported, consider simplifying the interface to only accept boolean values for clarity. If string values are needed, the comment should explain when and why string values would be used instead of boolean.

Copilot uses AI. Check for mistakes.

/**
* Extended MediaTrackConstraints that includes Google-specific audio processing properties.
*/
export type ExtendedMediaTrackConstraints = MediaTrackConstraints & GoogleAudioConstraints;

/**
* Default audio constraints for mobile-client with Google audio processing features enabled.
* These constraints can be overridden by passing custom audio constraints to FishjamProvider.
*/
export const DEFAULT_MOBILE_AUDIO_CONSTRAINTS: ExtendedMediaTrackConstraints = {
googEchoCancellation: true,
googAutoGainControl: true,
googNoiseSuppression: true,
googTypingNoiseDetection: true,
googHighpassFilter: true,
};

/**
* Merges default mobile audio constraints with user-provided constraints.
* User-provided constraints take precedence over defaults.
*
* @param userConstraints - User-provided audio constraints (can be boolean or MediaTrackConstraints)
* @returns Merged audio constraints
*/
export function mergeMobileAudioConstraints(
userConstraints?: ExtendedMediaTrackConstraints | boolean,
): ExtendedMediaTrackConstraints | boolean {
if (userConstraints === false) {
return false;
}

if (userConstraints === true || userConstraints === undefined) {
return DEFAULT_MOBILE_AUDIO_CONSTRAINTS;
}

return {
...DEFAULT_MOBILE_AUDIO_CONSTRAINTS,
...userConstraints,
};
}
Comment on lines +1 to +52
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ExtendedMediaTrackConstraints type and DEFAULT_MOBILE_AUDIO_CONSTRAINTS constant are not exported from the module. Users who want to reference these defaults or understand the type structure for their custom constraints cannot access them. Consider exporting these to improve developer experience and API discoverability. For example, add these exports to index.ts:
export type { ExtendedMediaTrackConstraints } from './constraints';
export { DEFAULT_MOBILE_AUDIO_CONSTRAINTS } from './constraints';

Copilot uses AI. Check for mistakes.
12 changes: 12 additions & 0 deletions packages/mobile-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
} from '@fishjam-cloud/react-client';
import { FishjamClient } from '@fishjam-cloud/ts-client';

import { mergeMobileAudioConstraints } from './constraints';

export { RTCView, RTCPIPView, type RTCVideoViewProps, type RTCPIPViewProps } from './overrides/RTCView';

export {
ScreenCapturePickerView,
startPIP,
Expand Down Expand Up @@ -90,8 +93,17 @@ export type {
export type FishjamProviderProps = Omit<ReactClientFishjamProviderProps, 'persistLastDevice' | 'fishjamClient'>;
export function FishjamProvider(props: FishjamProviderProps) {
const fishjamClient = new FishjamClient({ reconnect: props.reconnect, debug: props.debug, clientType: 'mobile' });

const mergedConstraints = React.useMemo(() => {
return {
...props.constraints,
audio: mergeMobileAudioConstraints(props.constraints?.audio),
};
}, [props.constraints]);
Comment on lines +97 to +102
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useMemo dependency array includes props.constraints which is an object reference. This will cause the memo to recompute on every render if the parent component doesn't memoize the constraints object, defeating the purpose of using useMemo. Consider using individual properties as dependencies (e.g., props.constraints?.audio, props.constraints?.video) or document that users should memoize their constraints object. Alternatively, follow the pattern used in react-client's FishjamProvider which directly passes props.constraints without wrapping in useMemo.

Suggested change
const mergedConstraints = React.useMemo(() => {
return {
...props.constraints,
audio: mergeMobileAudioConstraints(props.constraints?.audio),
};
}, [props.constraints]);
const mergedConstraints = {
...props.constraints,
audio: mergeMobileAudioConstraints(props.constraints?.audio),
};

Copilot uses AI. Check for mistakes.

return React.createElement(ReactClientFishjamProvider, {
...props,
constraints: mergedConstraints,
persistLastDevice: false,
fishjamClient,
});
Expand Down
Loading