diff --git a/docs/explanation/data-channels.mdx b/docs/explanation/data-channels.mdx
index bd559ec..31d5124 100644
--- a/docs/explanation/data-channels.mdx
+++ b/docs/explanation/data-channels.mdx
@@ -42,7 +42,22 @@ This separation allows you to use both channels simultaneously for different pur
## Using Data Channels
-Use the [`useDataChannel`](../api/web/functions/useDataChannel) hook to work with data channels. The typical flow is:
+Use the `useDataChannel` hook to work with data channels. The hook is available in both the web and mobile SDKs with the same API:
+
+
+
+
+Use [`useDataChannel`](../api/web/functions/useDataChannel) from `@fishjam-cloud/react-client`.
+
+
+
+
+Use [`useDataChannel`](../api/mobile/functions/useDataChannel) from `@fishjam-cloud/react-native-client`.
+
+
+
+
+The typical flow is:
1. Initialize the data channel after connecting to a room
2. Subscribe to incoming messages
diff --git a/docs/how-to/client/installation.mdx b/docs/how-to/client/installation.mdx
index 14cf23d..9bfb5e9 100644
--- a/docs/how-to/client/installation.mdx
+++ b/docs/how-to/client/installation.mdx
@@ -77,23 +77,45 @@ You can also follow more detailed [Expo instructions](https://docs.expo.dev/get-
## Step 1: Install the Package
-Install `@fishjam-cloud/react-native-client` with your preferred package manager.
+
+
+
+
+Install `@fishjam-cloud/react-native-client` and `react-native-get-random-values` with your preferred package manager.
+
+```bash npm2yarn
+npm install @fishjam-cloud/react-native-client react-native-get-random-values@1.11.0
+```
+
+Expo SDK 54+ resolves native dependencies recursively, so `@fishjam-cloud/react-native-webrtc` (a transitive dependency) is autolinked automatically.
+
+
+
+
+Install `@fishjam-cloud/react-native-client`, `@fishjam-cloud/react-native-webrtc`, and `react-native-get-random-values`:
```bash npm2yarn
-npm install @fishjam-cloud/react-native-client
+npm install @fishjam-cloud/react-native-client @fishjam-cloud/react-native-webrtc react-native-get-random-values@1.11.0
```
+Bare React Native and Expo SDK versions below 54 only autolink direct dependencies.
+`@fishjam-cloud/react-native-webrtc` must be in your app's `package.json` for its native code to be linked.
+
+
+
+
## Step 2: Configure App Permissions
Your app needs to have permissions configured in order to use the microphone and camera.
### Android
-These permissions are required to stream audio and video with Fishjam on Android:
+The following Android permissions are required by Fishjam:
- `android.permission.CAMERA`
- `android.permission.RECORD_AUDIO`
- `android.permission.MODIFY_AUDIO_SETTINGS`
+- `android.permission.ACCESS_NETWORK_STATE`
@@ -110,7 +132,8 @@ Add required permissions to the `app.json` file.
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
- "android.permission.MODIFY_AUDIO_SETTINGS"
+ "android.permission.MODIFY_AUDIO_SETTINGS",
+ "android.permission.ACCESS_NETWORK_STATE"
]
}
}
@@ -128,6 +151,7 @@ Add required permissions to the `AndroidManifest.xml` file.
+
...
```
diff --git a/docs/how-to/client/migration-guide.mdx b/docs/how-to/client/migration-guide.mdx
index 270813b..891a6ec 100644
--- a/docs/how-to/client/migration-guide.mdx
+++ b/docs/how-to/client/migration-guide.mdx
@@ -24,7 +24,8 @@ Add the following WebRTC permissions to your Android configuration in `app.json`
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
- "android.permission.MODIFY_AUDIO_SETTINGS"
+ "android.permission.MODIFY_AUDIO_SETTINGS",
+ "android.permission.ACCESS_NETWORK_STATE"
]
}
}
diff --git a/docs/how-to/features/text-chat.mdx b/docs/how-to/features/text-chat.mdx
index 635f114..b979571 100644
--- a/docs/how-to/features/text-chat.mdx
+++ b/docs/how-to/features/text-chat.mdx
@@ -22,7 +22,7 @@ For a deeper understanding of how data channels work, including channel types an
## Step 1 — Set up the chat hook
-Use the [`useDataChannel`](/api/web/functions/useDataChannel) hook to work with data channels. The typical flow is:
+Use the [`useDataChannel`](/api/web/functions/useDataChannel) (web) or [`useDataChannel`](/api/mobile/functions/useDataChannel) (mobile) hook to work with data channels. The typical flow is:
1. Initialize the data channel after connecting to a room
2. Subscribe to incoming messages
@@ -84,9 +84,67 @@ export function useChat() {
```
-
+
-Mobile SDK support for data channels will be available in a future release.
+```tsx
+import {
+ useConnection,
+ useDataChannel,
+} from "@fishjam-cloud/react-native-client";
+import { useCallback, useEffect, useState } from "react";
+
+export function useChat() {
+ const { peerStatus } = useConnection();
+ const {
+ initializeDataChannel,
+ publishData,
+ subscribeData,
+ dataChannelReady,
+ dataChannelLoading,
+ dataChannelError,
+ } = useDataChannel();
+
+ const [messages, setMessages] = useState([]);
+
+ useEffect(() => {
+ if (peerStatus === "connected") {
+ initializeDataChannel();
+ }
+ }, [peerStatus, initializeDataChannel]);
+
+ useEffect(() => {
+ if (dataChannelLoading || !dataChannelReady) return;
+
+ const unsubscribe = subscribeData(
+ (data: Uint8Array) => {
+ const message = new TextDecoder().decode(data);
+ setMessages((prev) => [...prev, message]);
+ },
+ { reliable: true },
+ );
+
+ return unsubscribe;
+ }, [dataChannelReady, dataChannelLoading, subscribeData]);
+
+ const sendMessage = useCallback(
+ (text: string) => {
+ if (!dataChannelReady) return;
+
+ const encoded = new TextEncoder().encode(text);
+ publishData(encoded, { reliable: true });
+ },
+ [publishData, dataChannelReady],
+ );
+
+ return {
+ messages,
+ sendMessage,
+ ready: dataChannelReady,
+ loading: dataChannelLoading,
+ error: dataChannelError,
+ };
+}
+```
@@ -185,9 +243,97 @@ function ChatPanel() {
```
-
+
+
+```tsx
+import React, { useState, useEffect, useCallback } from "react";
+import { View, Text, TextInput, FlatList, Pressable } from "react-native";
+import {
+ useConnection,
+ useDataChannel,
+} from "@fishjam-cloud/react-native-client";
+
+function useChat() {
+ const { peerStatus } = useConnection();
+ const {
+ initializeDataChannel,
+ publishData,
+ subscribeData,
+ dataChannelReady,
+ } = useDataChannel();
+
+ const [messages, setMessages] = useState([]);
+
+ useEffect(() => {
+ if (peerStatus === "connected") {
+ initializeDataChannel();
+ }
+ }, [peerStatus, initializeDataChannel]);
-Mobile SDK support for data channels will be available in a future release.
+ useEffect(() => {
+ if (!dataChannelReady) return;
+
+ const unsubscribe = subscribeData(
+ (data: Uint8Array) => {
+ const message = new TextDecoder().decode(data);
+ setMessages((prev) => [...prev, message]);
+ },
+ { reliable: true },
+ );
+
+ return unsubscribe;
+ }, [subscribeData, dataChannelReady]);
+
+ const sendMessage = useCallback(
+ (text: string) => {
+ if (!dataChannelReady) return;
+
+ const encoded = new TextEncoder().encode(text);
+ publishData(encoded, { reliable: true });
+ },
+ [publishData, dataChannelReady],
+ );
+
+ return { messages, sendMessage, ready: dataChannelReady };
+}
+
+// ---cut---
+
+function ChatPanel() {
+ const { messages, sendMessage, ready } = useChat();
+ const [input, setInput] = useState("");
+
+ const handleSend = () => {
+ if (input.trim()) {
+ sendMessage(input);
+ setInput("");
+ }
+ };
+
+ if (!ready) {
+ return Connecting to chat...;
+ }
+
+ return (
+
+ String(i)}
+ renderItem={({ item }) => {item}}
+ />
+
+
+ Send
+
+
+ );
+}
+```
@@ -209,4 +355,5 @@ This ensures no chat messages are lost or arrive out of order.
- [Data Channels](../../explanation/data-channels) — detailed explanation of channel types and broadcast behavior
- [Connecting to a room](../../how-to/client/connecting) — prerequisite for using data channels
-- [`useDataChannel` API reference](../../api/web/functions/useDataChannel)
+- [`useDataChannel` API reference (Web)](../../api/web/functions/useDataChannel)
+- [`useDataChannel` API reference (Mobile)](../../api/mobile/functions/useDataChannel)
diff --git a/docs/tutorials/react-native-quick-start.mdx b/docs/tutorials/react-native-quick-start.mdx
index 722b430..c3e845b 100644
--- a/docs/tutorials/react-native-quick-start.mdx
+++ b/docs/tutorials/react-native-quick-start.mdx
@@ -53,7 +53,8 @@ Add required permissions to the `app.json` file:
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
- "android.permission.MODIFY_AUDIO_SETTINGS"
+ "android.permission.MODIFY_AUDIO_SETTINGS",
+ "android.permission.ACCESS_NETWORK_STATE"
]
}
}
diff --git a/packages/web-client-sdk b/packages/web-client-sdk
index b73a7b1..2b23a8f 160000
--- a/packages/web-client-sdk
+++ b/packages/web-client-sdk
@@ -1 +1 @@
-Subproject commit b73a7b1d96c4a63909b2bb641aa3285b51a01999
+Subproject commit 2b23a8fa8f8da3ccee29eb2093031fa6a2943286
diff --git a/versioned_docs/version-0.25.0/explanation/data-channels.mdx b/versioned_docs/version-0.25.0/explanation/data-channels.mdx
index bd559ec..31d5124 100644
--- a/versioned_docs/version-0.25.0/explanation/data-channels.mdx
+++ b/versioned_docs/version-0.25.0/explanation/data-channels.mdx
@@ -42,7 +42,22 @@ This separation allows you to use both channels simultaneously for different pur
## Using Data Channels
-Use the [`useDataChannel`](../api/web/functions/useDataChannel) hook to work with data channels. The typical flow is:
+Use the `useDataChannel` hook to work with data channels. The hook is available in both the web and mobile SDKs with the same API:
+
+
+
+
+Use [`useDataChannel`](../api/web/functions/useDataChannel) from `@fishjam-cloud/react-client`.
+
+
+
+
+Use [`useDataChannel`](../api/mobile/functions/useDataChannel) from `@fishjam-cloud/react-native-client`.
+
+
+
+
+The typical flow is:
1. Initialize the data channel after connecting to a room
2. Subscribe to incoming messages
diff --git a/versioned_docs/version-0.25.0/how-to/client/installation.mdx b/versioned_docs/version-0.25.0/how-to/client/installation.mdx
index 14cf23d..9bfb5e9 100644
--- a/versioned_docs/version-0.25.0/how-to/client/installation.mdx
+++ b/versioned_docs/version-0.25.0/how-to/client/installation.mdx
@@ -77,23 +77,45 @@ You can also follow more detailed [Expo instructions](https://docs.expo.dev/get-
## Step 1: Install the Package
-Install `@fishjam-cloud/react-native-client` with your preferred package manager.
+
+
+
+
+Install `@fishjam-cloud/react-native-client` and `react-native-get-random-values` with your preferred package manager.
+
+```bash npm2yarn
+npm install @fishjam-cloud/react-native-client react-native-get-random-values@1.11.0
+```
+
+Expo SDK 54+ resolves native dependencies recursively, so `@fishjam-cloud/react-native-webrtc` (a transitive dependency) is autolinked automatically.
+
+
+
+
+Install `@fishjam-cloud/react-native-client`, `@fishjam-cloud/react-native-webrtc`, and `react-native-get-random-values`:
```bash npm2yarn
-npm install @fishjam-cloud/react-native-client
+npm install @fishjam-cloud/react-native-client @fishjam-cloud/react-native-webrtc react-native-get-random-values@1.11.0
```
+Bare React Native and Expo SDK versions below 54 only autolink direct dependencies.
+`@fishjam-cloud/react-native-webrtc` must be in your app's `package.json` for its native code to be linked.
+
+
+
+
## Step 2: Configure App Permissions
Your app needs to have permissions configured in order to use the microphone and camera.
### Android
-These permissions are required to stream audio and video with Fishjam on Android:
+The following Android permissions are required by Fishjam:
- `android.permission.CAMERA`
- `android.permission.RECORD_AUDIO`
- `android.permission.MODIFY_AUDIO_SETTINGS`
+- `android.permission.ACCESS_NETWORK_STATE`
@@ -110,7 +132,8 @@ Add required permissions to the `app.json` file.
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
- "android.permission.MODIFY_AUDIO_SETTINGS"
+ "android.permission.MODIFY_AUDIO_SETTINGS",
+ "android.permission.ACCESS_NETWORK_STATE"
]
}
}
@@ -128,6 +151,7 @@ Add required permissions to the `AndroidManifest.xml` file.
+
...
```
diff --git a/versioned_docs/version-0.25.0/how-to/client/migration-guide.mdx b/versioned_docs/version-0.25.0/how-to/client/migration-guide.mdx
index 270813b..891a6ec 100644
--- a/versioned_docs/version-0.25.0/how-to/client/migration-guide.mdx
+++ b/versioned_docs/version-0.25.0/how-to/client/migration-guide.mdx
@@ -24,7 +24,8 @@ Add the following WebRTC permissions to your Android configuration in `app.json`
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
- "android.permission.MODIFY_AUDIO_SETTINGS"
+ "android.permission.MODIFY_AUDIO_SETTINGS",
+ "android.permission.ACCESS_NETWORK_STATE"
]
}
}
diff --git a/versioned_docs/version-0.25.0/how-to/features/text-chat.mdx b/versioned_docs/version-0.25.0/how-to/features/text-chat.mdx
index 635f114..b979571 100644
--- a/versioned_docs/version-0.25.0/how-to/features/text-chat.mdx
+++ b/versioned_docs/version-0.25.0/how-to/features/text-chat.mdx
@@ -22,7 +22,7 @@ For a deeper understanding of how data channels work, including channel types an
## Step 1 — Set up the chat hook
-Use the [`useDataChannel`](/api/web/functions/useDataChannel) hook to work with data channels. The typical flow is:
+Use the [`useDataChannel`](/api/web/functions/useDataChannel) (web) or [`useDataChannel`](/api/mobile/functions/useDataChannel) (mobile) hook to work with data channels. The typical flow is:
1. Initialize the data channel after connecting to a room
2. Subscribe to incoming messages
@@ -84,9 +84,67 @@ export function useChat() {
```
-
+
-Mobile SDK support for data channels will be available in a future release.
+```tsx
+import {
+ useConnection,
+ useDataChannel,
+} from "@fishjam-cloud/react-native-client";
+import { useCallback, useEffect, useState } from "react";
+
+export function useChat() {
+ const { peerStatus } = useConnection();
+ const {
+ initializeDataChannel,
+ publishData,
+ subscribeData,
+ dataChannelReady,
+ dataChannelLoading,
+ dataChannelError,
+ } = useDataChannel();
+
+ const [messages, setMessages] = useState([]);
+
+ useEffect(() => {
+ if (peerStatus === "connected") {
+ initializeDataChannel();
+ }
+ }, [peerStatus, initializeDataChannel]);
+
+ useEffect(() => {
+ if (dataChannelLoading || !dataChannelReady) return;
+
+ const unsubscribe = subscribeData(
+ (data: Uint8Array) => {
+ const message = new TextDecoder().decode(data);
+ setMessages((prev) => [...prev, message]);
+ },
+ { reliable: true },
+ );
+
+ return unsubscribe;
+ }, [dataChannelReady, dataChannelLoading, subscribeData]);
+
+ const sendMessage = useCallback(
+ (text: string) => {
+ if (!dataChannelReady) return;
+
+ const encoded = new TextEncoder().encode(text);
+ publishData(encoded, { reliable: true });
+ },
+ [publishData, dataChannelReady],
+ );
+
+ return {
+ messages,
+ sendMessage,
+ ready: dataChannelReady,
+ loading: dataChannelLoading,
+ error: dataChannelError,
+ };
+}
+```
@@ -185,9 +243,97 @@ function ChatPanel() {
```
-
+
+
+```tsx
+import React, { useState, useEffect, useCallback } from "react";
+import { View, Text, TextInput, FlatList, Pressable } from "react-native";
+import {
+ useConnection,
+ useDataChannel,
+} from "@fishjam-cloud/react-native-client";
+
+function useChat() {
+ const { peerStatus } = useConnection();
+ const {
+ initializeDataChannel,
+ publishData,
+ subscribeData,
+ dataChannelReady,
+ } = useDataChannel();
+
+ const [messages, setMessages] = useState([]);
+
+ useEffect(() => {
+ if (peerStatus === "connected") {
+ initializeDataChannel();
+ }
+ }, [peerStatus, initializeDataChannel]);
-Mobile SDK support for data channels will be available in a future release.
+ useEffect(() => {
+ if (!dataChannelReady) return;
+
+ const unsubscribe = subscribeData(
+ (data: Uint8Array) => {
+ const message = new TextDecoder().decode(data);
+ setMessages((prev) => [...prev, message]);
+ },
+ { reliable: true },
+ );
+
+ return unsubscribe;
+ }, [subscribeData, dataChannelReady]);
+
+ const sendMessage = useCallback(
+ (text: string) => {
+ if (!dataChannelReady) return;
+
+ const encoded = new TextEncoder().encode(text);
+ publishData(encoded, { reliable: true });
+ },
+ [publishData, dataChannelReady],
+ );
+
+ return { messages, sendMessage, ready: dataChannelReady };
+}
+
+// ---cut---
+
+function ChatPanel() {
+ const { messages, sendMessage, ready } = useChat();
+ const [input, setInput] = useState("");
+
+ const handleSend = () => {
+ if (input.trim()) {
+ sendMessage(input);
+ setInput("");
+ }
+ };
+
+ if (!ready) {
+ return Connecting to chat...;
+ }
+
+ return (
+
+ String(i)}
+ renderItem={({ item }) => {item}}
+ />
+
+
+ Send
+
+
+ );
+}
+```
@@ -209,4 +355,5 @@ This ensures no chat messages are lost or arrive out of order.
- [Data Channels](../../explanation/data-channels) — detailed explanation of channel types and broadcast behavior
- [Connecting to a room](../../how-to/client/connecting) — prerequisite for using data channels
-- [`useDataChannel` API reference](../../api/web/functions/useDataChannel)
+- [`useDataChannel` API reference (Web)](../../api/web/functions/useDataChannel)
+- [`useDataChannel` API reference (Mobile)](../../api/mobile/functions/useDataChannel)
diff --git a/versioned_docs/version-0.25.0/tutorials/react-native-quick-start.mdx b/versioned_docs/version-0.25.0/tutorials/react-native-quick-start.mdx
index 722b430..c3e845b 100644
--- a/versioned_docs/version-0.25.0/tutorials/react-native-quick-start.mdx
+++ b/versioned_docs/version-0.25.0/tutorials/react-native-quick-start.mdx
@@ -53,7 +53,8 @@ Add required permissions to the `app.json` file:
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
- "android.permission.MODIFY_AUDIO_SETTINGS"
+ "android.permission.MODIFY_AUDIO_SETTINGS",
+ "android.permission.ACCESS_NETWORK_STATE"
]
}
}