Skip to content
Merged
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
7 changes: 4 additions & 3 deletions examples/react-native/WhipWhepDemo/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
"ios": {
"enableScreensharing": true,
"supportsPictureInPicture": true,
"appGroupContainerId": "group.com.swmansion.mobilewhepclient",
"iphoneDeploymentTarget": "15.1"
"appGroupContainerId": "group.com.swmansion.mobilewhepclient"
},
"android": {
"enableScreensharing": true,
Expand All @@ -58,7 +57,9 @@
],
"expo-font",
"expo-web-browser",
"expo-audio"
"expo-audio",
"expo-splash-screen",
"expo-status-bar"
],
"experiments": {
"typedRoutes": true
Expand Down
4 changes: 2 additions & 2 deletions examples/react-native/WhipWhepDemo/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tabIconSelected,
tabBarInactiveTintColor: Colors[colorScheme ?? 'light'].tabIconDefault,
tabBarActiveTintColor: Colors[colorScheme].tabIconSelected,
tabBarInactiveTintColor: Colors[colorScheme].tabIconDefault,
headerShown: false,
}}>
<Tabs.Screen
Expand Down
11 changes: 10 additions & 1 deletion examples/react-native/WhipWhepDemo/hooks/useColorScheme.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
export { useColorScheme } from 'react-native';
import { useColorScheme as useRNColorScheme } from 'react-native';

/**
* React Native 0.86 widened `useColorScheme()` to return `'unspecified'` alongside
* `'light' | 'dark'`, and it no longer returns null. `'unspecified'` cannot index the `Colors`
* palette, so collapse it onto the two themes the app actually defines.
*/
export function useColorScheme(): 'light' | 'dark' {
return useRNColorScheme() === 'dark' ? 'dark' : 'light';
}
4 changes: 2 additions & 2 deletions examples/react-native/WhipWhepDemo/hooks/useThemeColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
* https://docs.expo.dev/guides/color-schemes/
*/

import { useColorScheme } from 'react-native';
import { useColorScheme } from '@/hooks/useColorScheme';

import { Colors } from '@/constants/Colors';

export function useThemeColor() {
const theme = useColorScheme() ?? 'light';
const theme = useColorScheme();

return Colors[theme];
}
57 changes: 29 additions & 28 deletions examples/react-native/WhipWhepDemo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,39 @@
"dependencies": {
"@expo/vector-icons": "^15.0.2",
"@react-navigation/native": "^7.0.14",
"expo": "^54.0.25",
"expo-audio": "~1.0.13",
"expo-camera": "~17.0.8",
"expo-constants": "~18.0.9",
"expo-font": "~14.0.9",
"expo-keep-awake": "~15.0.7",
"expo-linking": "~8.0.11",
"expo-router": "~6.0.12",
"expo-splash-screen": "~31.0.10",
"expo-status-bar": "~3.0.8",
"expo-system-ui": "~6.0.8",
"expo-web-browser": "~15.0.10",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.4",
"react-native-gesture-handler": "~2.28.0",
"react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "~5.6.2",
"react-native-screens": "~4.16.0",
"expo": "^57.0.18",
"expo-audio": "~57.0.4",
"expo-camera": "~57.0.4",
"expo-constants": "~57.0.16",
"expo-font": "~57.0.2",
"expo-keep-awake": "~57.0.1",
"expo-linking": "~57.0.8",
"expo-router": "~57.0.17",
"expo-splash-screen": "~57.0.8",
"expo-status-bar": "~57.0.1",
"expo-system-ui": "~57.0.3",
"expo-web-browser": "~57.0.2",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native": "0.86.3",
"react-native-gesture-handler": "~2.32.0",
"react-native-reanimated": "4.5.1",
"react-native-safe-area-context": "~5.7.0",
"react-native-screens": "~4.26.0",
"react-native-web": "^0.21.2",
"react-native-whip-whep": "*",
"react-native-worklets": "0.5.1"
"react-native-worklets": "0.10.1"
},
"devDependencies": {
"@babel/core": "^7.26.10",
"@types/jest": "^29.5.14",
"@types/react": "~19.1.10",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
"jest-expo": "~54.0.12",
"react-test-renderer": "18.3.1",
"typescript": "~5.9.2"
"@babel/core": "^7.29.0",
"@types/jest": "^30.0.0",
"@types/react": "~19.2.4",
"@types/react-test-renderer": "^19.1.0",
"babel-preset-expo": "~57.0.0",
"jest": "^30.5.0",
"jest-expo": "~57.0.5",
"react-test-renderer": "19.2.3",
"typescript": "~6.0.3"
},
"expo": {
"doctor": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"packageManager": "yarn@4.12.0",
"devDependencies": {
"@babel/runtime": "^7.27.0",
"@react-native/eslint-config": "^0.79.1",
"@react-native/eslint-config": "^0.86.3",
"eslint": "8.x",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.6",
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
},
"devDependencies": {
"@types/promise-fs": "^2.1.2",
"@types/react": "~19.1.10",
"expo-module-scripts": "~4.0.5",
"@types/react": "~19.2.4",
"expo-module-scripts": "~56.0.3",
"typedoc": "^0.28.20",
"typescript": "^5.8.3"
},
Expand Down
39 changes: 37 additions & 2 deletions packages/react-native-client/plugin/src/withWhipWhepIos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ export function getSbePodfileSnippet(props: WhipWhepPluginOptions) {

const TARGETED_DEVICE_FAMILY = `"1,2"`; // 1=iPhone, 2=iPad
const IPHONEOS_DEPLOYMENT_TARGET = '15.1'; // Minimum iOS version

/**
* Compares two `MAJOR.MINOR[.PATCH]` deployment targets numerically, so that e.g. '16.4' is
* correctly ordered above '15.10' (a plain string compare gets that backwards).
*/
const isDeploymentTargetLower = (a: string, b: string): boolean => {
const parse = (value: string) => value.split('.').map((part) => Number(part) || 0);
const [left, right] = [parse(a), parse(b)];
for (let i = 0; i < Math.max(left.length, right.length); i++) {
const diff = (left[i] ?? 0) - (right[i] ?? 0);
if (diff !== 0) {
return diff < 0;
}
}
return false;
};
const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm; // Template placeholder for app group
const BUNDLE_IDENTIFIER_TEMPLATE_REGEX = /{{BUNDLE_IDENTIFIER}}/gm; // Template placeholder for bundle ID

Expand Down Expand Up @@ -379,8 +395,27 @@ const withWhipWhepIos: ConfigPlugin<WhipWhepPluginOptions> = (config, props) =>
}

config = withPodfileProperties(config, (configuration) => {
configuration.modResults['ios.deploymentTarget'] =
props?.ios?.iphoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
const explicit = props?.ios?.iphoneDeploymentTarget;
if (explicit) {
configuration.modResults['ios.deploymentTarget'] = explicit;
return configuration;
}

// `IPHONEOS_DEPLOYMENT_TARGET` is the minimum this SDK needs, not the target the app should
// use. When the property is absent the Expo Podfile template supplies its own default (16.4
// on SDK 57), which already clears our minimum - writing ours in would downgrade the app and
// leave `pod install` unable to resolve the Expo pod. So only step an existing, lower value
// up.
const currentRaw = configuration.modResults['ios.deploymentTarget'];
const current =
typeof currentRaw === 'string'
? currentRaw
: typeof currentRaw === 'number'
? String(currentRaw)
: undefined;
if (current && isDeploymentTargetLower(current, IPHONEOS_DEPLOYMENT_TARGET)) {
configuration.modResults['ios.deploymentTarget'] = IPHONEOS_DEPLOYMENT_TARGET;
}
return configuration;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export type WhepClientViewRef = {
/**
* Connects to the WHEP server.
*/
connect: (ConnectOptions) => Promise<void>;
connect: (options: ConnectOptions) => Promise<void>;
/**
* Disconnects from the WHEP server.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import * as React from "react";

import {
PlayerType,
ReactNativeMobileWhepClientViewProps,
WhepClientViewRef,
WhepConfigurationOptions,
ReceiverVideoCodecName,
ReceiverAudioCodecName,
type ReactNativeMobileWhepClientViewProps,
type WhepClientViewRef,
type WhepConfigurationOptions,
type ReceiverVideoCodecName,
type ReceiverAudioCodecName,
} from "./ReactNativeMobileWhepClient.types";

const NativeViewBase: React.ComponentType<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export type ReceivableEventPayloads = {
};

type RNMobileWhepClientViewModule = {
whepPeerConnectionState: PeerConnectionState | null;
// Optional because no native `Property` backs it on either platform yet, so it reads back as
// `undefined` at runtime. `useWhepConnectionState` falls back to "unknown" and then tracks the
// change events.
whepPeerConnectionState?: PeerConnectionState | null;
};

const nativeViewModule = requireNativeModule(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import * as React from "react";

import {
PlayerType,
ReactNativeMobileWhipClientViewProps,
WhipClientViewRef,
WhipConfigurationOptions,
CameraId,
type ReactNativeMobileWhipClientViewProps,
type WhipClientViewRef,
type WhipConfigurationOptions,
type CameraId,
} from "./ReactNativeMobileWhepClient.types";

const NativeViewBase: React.ComponentType<
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { requireNativeModule } from "expo-modules-core";
import type { NativeModule } from "expo-modules-core/types";

import { CameraId } from "./ReactNativeMobileWhepClient.types";
import type { CameraId } from "./ReactNativeMobileWhepClient.types";

/** Describes whether the camera is front-facing or back-facing. */
export type CameraFacingDirection = "front" | "back" | "unspecified";
Expand All @@ -18,6 +18,10 @@ export type Camera = {

type RNMobileWhipClientViewModule = {
cameras: readonly Camera[];
// Optional because no native `Property` backs it on either platform yet - the modules only
// declare `cameras` - so it reads back as `undefined` at runtime. `useWhipConnectionState`
// falls back to "unknown" and then tracks the change events.
whipPeerConnectionState?: PeerConnectionState | null;
};

export const ReceivableEvents = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from "zod";

import {
ReceivableEventPayloads,
type ReceivableEventPayloads,
ReceivableEvents,
} from "../ReactNativeMobileWhepClientViewModule";

Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-client/src/hooks/useConnectionState.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useState, useEffect } from "react";

import ReactNativeMobileWhepClientViewModule, {
PeerConnectionState,
type PeerConnectionState,
ReceivableEvents,
} from "../ReactNativeMobileWhepClientViewModule";
import ReactNativeMobileWhipClientViewModule, {
ReceivableEvents as WhipReceivableEvents,
PeerConnectionState as WhipPeerConnectionState,
type PeerConnectionState as WhipPeerConnectionState,
} from "../ReactNativeMobileWhipClientViewModule";

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-client/src/hooks/useEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect } from "react";
import { ZodError } from "zod";

import nativeModule, {
ReceivableEventPayloads,
type ReceivableEventPayloads,
ReceivableEvents,
} from "../ReactNativeMobileWhepClientViewModule";
import { validateNativeEventPayload } from "./eventPayloadValidator";
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-client/src/hooks/useEventState.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useState } from "react";

import {
ReceivableEventPayloads,
type ReceivableEventPayloads,
ReceivableEvents,
} from "../ReactNativeMobileWhepClientViewModule";
import { useEvent } from "./useEvent";
Expand Down
8 changes: 5 additions & 3 deletions packages/react-native-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { WhipClientView } from "./ReactNativeMobileWhipClientView";
import { initializeWarningListener } from "./utils/errorListener";

export { WhipClientView, WhepClientView };
export {
VideoParameters,
export { VideoParameters } from "./ReactNativeMobileWhepClient.types";
export type {
ReactNativeMobileWhepClientViewProps,
ReactNativeMobileWhipClientViewProps,
WhepClientViewRef,
Expand All @@ -21,9 +21,11 @@ export {

export {
cameras,
ReceivableEvents as WhipReceivableEvents,
} from "./ReactNativeMobileWhipClientViewModule";
export type {
Camera,
CameraFacingDirection,
ReceivableEvents as WhipReceivableEvents,
} from "./ReactNativeMobileWhipClientViewModule";

export { ReceivableEvents as WhepReceivableEvents } from "./ReactNativeMobileWhepClientViewModule";
Expand Down
Loading
Loading