diff --git a/.spelling b/.spelling
index 4b0611b..71e8dcb 100644
--- a/.spelling
+++ b/.spelling
@@ -20,3 +20,9 @@ js-server-sdk
Docusaurus
pre-configured
TabItem
+AndroidManifest.xml
+iOS
+Xcode
+UI
+dev
+Podfile
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index a185dfa..4b19196 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -37,6 +37,9 @@ const config: Config = {
path: "guide",
routeBasePath: "guide",
editUrl: "https://github.com/fishjam-cloud/documentation/",
+ remarkPlugins: [
+ [require("@docusaurus/remark-plugin-npm2yarn"), { sync: true }],
+ ],
},
blog: {
showReadingTime: true,
@@ -56,26 +59,7 @@ const config: Config = {
],
],
- plugins: [
- // [
- // "@docusaurus/plugin-content-docs",
- // {
- // id: "react",
- // path: "react-docs",
- // routeBasePath: "react",
- // sidebarPath: "./sidebars/react.ts",
- // },
- // ],
- // [
- // "@docusaurus/plugin-content-docs",
- // {
- // id: "react-native",
- // path: "react-native-docs",
- // routeBasePath: "react-native",
- // sidebarPath: "./sidebars/react-native.ts",
- // },
- // ],
- ],
+ plugins: [],
themeConfig: {
image: "img/social-card.png",
@@ -96,18 +80,7 @@ const config: Config = {
position: "left",
sidebarId: "guideSidebar",
},
- // {
- // to: "/react-native",
- // label: "React Native",
- // position: "left",
- // sidebarId: "reactNativeSidebar",
- // },
- // {
- // to: "/react",
- // label: "React",
- // position: "left",
- // sidebarId: "reactSidebar",
- // },
+
{
href: "https://fishjam.io/app/",
label: "Fishjam Dashboard",
@@ -163,6 +136,7 @@ const config: Config = {
prism: {
theme: prismThemes.gruvboxMaterialLight,
darkTheme: prismThemes.gruvboxMaterialDark,
+ additionalLanguages: ["bash"],
},
} satisfies Preset.ThemeConfig,
};
diff --git a/guide/react-native/assets/ios-new-folder.png b/guide/react-native/assets/ios-new-folder.png
new file mode 100644
index 0000000..59299cf
Binary files /dev/null and b/guide/react-native/assets/ios-new-folder.png differ
diff --git a/guide/react-native/assets/ios-new-group.png b/guide/react-native/assets/ios-new-group.png
new file mode 100644
index 0000000..8ec7c41
Binary files /dev/null and b/guide/react-native/assets/ios-new-group.png differ
diff --git a/guide/react-native/assets/ios-new-target.png b/guide/react-native/assets/ios-new-target.png
new file mode 100644
index 0000000..4ecff35
Binary files /dev/null and b/guide/react-native/assets/ios-new-target.png differ
diff --git a/guide/react-native/background.mdx b/guide/react-native/background.mdx
new file mode 100644
index 0000000..cd0272c
--- /dev/null
+++ b/guide/react-native/background.mdx
@@ -0,0 +1,56 @@
+---
+sidebar_position: 6
+---
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+# Streaming from background
+
+On Android, it is possible to continue streaming when app is in background. Unfortunately this functionality is not available on iOS (due to Apple limitations)
+
+Below is configuration required to make it work:
+
+
+
+
+
+You need to modify `app.json` file and add our plugin:
+
+```json
+{
+ "expo": {
+ ...
+ "plugins": {
+ ...
+ [
+ "@fishjam-cloud/react-native-client",
+ {
+ "android": {
+ "enableForegroundService": true
+ }
+ }
+ ],
+ ...
+ }
+ }
+}
+```
+
+
+
+
+You need to modify `AndroidManifest.xml` file and add below service:
+
+```xml
+
+ ...
+
+ ...
+
+
+
+```
+
+
+
diff --git a/guide/react-native/connecting.mdx b/guide/react-native/connecting.mdx
index e8d0df5..c0a3d24 100644
--- a/guide/react-native/connecting.mdx
+++ b/guide/react-native/connecting.mdx
@@ -2,6 +2,9 @@
sidebar_position: 2
---
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
# Connecting
How to connect to Fishjam Cloud
@@ -10,7 +13,9 @@ How to connect to Fishjam Cloud
In order to connect, you need to retrieve URL (multimedia server address) and token (token that will authenticate you in your Room)
-### Using sandbox app
+
+
+
Once you get your account on [Fishjam Cloud](https://fishjam.io), you will have access to Sandbox App.
This app comes with pre-configured test service called Room Manager. This is basically service that will
@@ -20,12 +25,21 @@ To use that simply call `fetch`:
```ts
const response = await fetch(
- `https://fishjam.io/api/v1/connect/*YOUR_ID*/room-manager/*ROOM_NAME*/users/*USER_NAME*`,
+ `https://fishjam.io/api/v1/connect/*YOUR_ID*/room-manager?room=*ROOM_NAME&user=*USER_NAME*`,
);
-const { url, token } = await response.json();
+const { fishjamUrl, participantToken } = await response.json();
```
+
+
+
+For production app, you need to implement your own backend service that will provide user with `participantToken`.
+To do that, follow our [server setup instructions](/guide/server).
+
+
+
+
## Connecting
In order to connect, you just need to call `joinRoom` method with data from previous step:
diff --git a/guide/react-native/installation.mdx b/guide/react-native/installation.mdx
index 6e6c3b1..4e48386 100644
--- a/guide/react-native/installation.mdx
+++ b/guide/react-native/installation.mdx
@@ -7,55 +7,125 @@ import TabItem from "@theme/TabItem";
# Installation
-If you don't have an existing project, you can create a new Expo app using a template:
+How to install package in your mobile app
-
-
-
- ```
- npx create-expo-app@latest my-video-app
- ```
+## Optional: Create new App
-
-
+
+ Follow these steps to create a new mobile app
- ```
- yarn create expo-app my-video-app
- ```
+If you don't have an existing project, you can create a new Expo app using a template
-
-
+```bash
+npx create-expo-app@latest my-video-app
+```
+
+As the next step, you have to generate native files with `expo prepare` command:
+
+```bash
+npx expo prebuild
+```
+
+You can also follow more detailed [expo instructions](https://docs.expo.dev/get-started/introduction/).
-## Installation
+
-### Step 1: Install the package
+## Step 1: Install the package
Install `@fishjam-cloud/react-native-client` package:
-
+```bash npm2yarn
+npm install @fishjam-cloud/react-native-client
+```
+
+## Step 2: Configure App permissions
+
+Your app must have permissions configured to use the microphone and camera.
+
+### Android
+
+For android you need to ask for certain permissions:
+
+- `android.permission.CAMERA`
+- `android.permission.RECORD_AUDIO`
+- `android.permission.MODIFY_AUDIO_SETTINGS`
-
+
- ```
- npm install @fishjam-cloud/react-native-client
- ```
+
+
+You need to modify `app.json` file and add all permissions:
+
+```json
+{
+ "expo": {
+ ...
+ "android": {
+ ...
+ "permissions": {
+ "android.permission.CAMERA",
+ "android.permission.RECORD_AUDIO",
+ "android.permission.MODIFY_AUDIO_SETTINGS"
+ }
+ }
+ }
+}
+```
-
+
+
+You need to modify `AndroidManifest.xml` file, and these lines:
- ```
- yarn add @fishjam-cloud/react-native-client
- ```
+```xml
+
+ ...
+
+
+
+ ...
+
+```
-### Step 2: Configure screen sharing
+### iOS
-If you plan to use Screen Sharing feature, there are few extra steps required to configure it.
+
-:::warning missing docs
+
-This part of docs will be updated
+You don't have to make any changes to run app on iOS.
+To update default content of permission alert, you can add these settings to `app.json`:
+
+```json
+{
+ "expo": {
+ ...
+ "ios": {
+ ...
+ "infoPlist": {
+ "NSCameraUsageDescription": "Your message.",
+ "NSMicrophoneUsageDescription": "Your message"
+ }
+ },
+ }
+}
+```
+
+
+
-:::
+You need to make sure that `info.plist` contain these entries:
+
+```xml
+ NSCameraUsageDescription
+ Allow $(PRODUCT_NAME) to access your camera.
+ NSMicrophoneUsageDescription
+ Allow $(PRODUCT_NAME) to access your microphone
+
+```
+
+
+
diff --git a/guide/react-native/screensharing.mdx b/guide/react-native/screensharing.mdx
new file mode 100644
index 0000000..ba0cfca
--- /dev/null
+++ b/guide/react-native/screensharing.mdx
@@ -0,0 +1,192 @@
+---
+sidebar_position: 5
+---
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+# Screen sharing
+
+Our SDK also allow to stream content of mobile device screen.
+
+## Installation
+
+### Android
+
+To enable screen sharing on android, you need enable foreground services. Here is [instruction on how to enable it](./background).
+
+### iOS
+
+To enable screen share feature on iOS, you need to follow below steps
+
+
+
+
+
+You need to modify `app.json` file and add our plugin:
+
+```json
+{
+ "expo": {
+ ...
+ "plugins": {
+ ...
+ [
+ "@fishjam-cloud/react-native-client",
+ {
+ "ios": {
+ "enableScreensharing": true
+ }
+ }
+ ],
+ ...
+ }
+ }
+}
+```
+
+
+
+
+Configuring screen sharing on iOS is a little complicated.
+
+1. Add camera and microphone permissions to your main `Info.plist`.
+
+ ```xml
+ NSCameraUsageDescription
+ Allow $(PRODUCT_NAME) to use the camera
+ NSMicrophoneUsageDescription
+ Allow $(PRODUCT_NAME) to use the microphone
+ ```
+
+1. Open your `.xcworkspace` in Xcode
+
+1. Create new Broadcast Upload Extension. Select `File → New → Target... → Broadcast Upload Extension → Next`. Choose the name for the new target, select Swift language and deselect "Include UI Extension".
+ ![New Target](./assets/ios-new-target.png)
+
+1. Configure app group. Go to "Signing & Capabilities" tab, click "+ Capability" button in upper left corner and select "App Groups".
+
+ ![New Group](./assets/ios-new-group.png)
+ Then in the "App Groups" add a new group or select existing. Usually group name has format `group.`. Verify that both app and extension targets have app group and dev team set correctly.
+
+1. A new folder with app extension should appear on the left with contents like this:
+ ![New Folder](./assets/ios-new-folder.png)
+
+ Replace `SampleHandler.swift` with `FishjamBroadcastHandler.swift` and this code:
+
+ ```swift
+ import FishjamCloudClient
+ import Foundation
+ import ReplayKit
+ import WebRTC
+ import os.log
+
+ let appGroup = "group.{{BUNDLE_IDENTIFIER}}"
+
+ let logger = OSLog(subsystem: "{{BUNDLE_IDENTIFIER}}.FishjamBroadcastHandler", category: "Broadcaster")
+
+ class FishjamBroadcastSampleHandler: RPBroadcastSampleHandler {
+ let broadcastSource = BroadcastSampleSource(appGroup: appGroup)
+ var started: Bool = false
+
+ override func broadcastStarted(withSetupInfo _: [String: NSObject]?) {
+ started = broadcastSource.connect()
+
+ guard started else {
+ os_log("failed to connect with ipc server", log: logger, type: .debug)
+
+ super.finishBroadcastWithError(NSError(domain: "", code: 0, userInfo: nil))
+
+ return
+ }
+
+ broadcastSource.started()
+ }
+
+ override func broadcastPaused() {
+ broadcastSource.paused()
+ }
+
+ override func broadcastResumed() {
+ broadcastSource.resumed()
+ }
+
+ override func broadcastFinished() {
+ broadcastSource.finished()
+ }
+
+ override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
+ guard started else {
+ return
+ }
+
+ broadcastSource.processFrame(sampleBuffer: sampleBuffer, ofType: sampleBufferType)
+ }
+ }
+ ```
+
+ Replace `{{BUNDLE_IDENTIFIER}}` with your bundle identifier.
+
+1. In project's Podfile add the following code:
+
+ ```rb
+ target 'FishjamScreenBroadcastExtension' do
+ pod 'FishjamCloudClient/Broadcast'
+ end
+ ```
+
+1. Add the following constants in your `Info.plist`:
+
+ ```xml
+ AppGroupName
+ group.{{BUNDLE_IDENTIFIER}}
+ ScreencastExtensionBundleId
+ {{BUNDLE_IDENTIFIER}}.FishjamScreenBroadcastExtension
+ ```
+
+1. Run `pod install`, rebuild your app and enjoy!
+
+
+
+
+## Usage
+
+You can use `useScreenShare` hook to enable screen sharing.
+
+First, you have to make sure that permissions are granted. To do that, you can call `handleScreenSharePermission` method:
+
+```tsx
+import { useScreenShare } from "@fishjam-cloud/react-native-client";
+
+function Component() {
+ const { handleScreenSharePermission } = useScreenShare();
+
+ useEffect(() => {
+ function checkPermissions() {
+ const result = await handleScreenSharePermission();
+ if (result === "granted") {
+ // permissions are granted
+ }
+ }
+ checkPermissions();
+ }, []);
+
+ return ;
+}
+```
+
+Then, you can enable/disable screen sharing with `toggleScreenShare` method. And check current state with `isScreenShareOn` property.
+
+```tsx
+import { useScreenShare } from "@fishjam-cloud/react-native-client";
+
+function ScreenShareButton() {
+ const { toggleScreenShare, isScreenShareOn } = useScreenShare();
+
+ return (
+
+ );
+}
+```
diff --git a/guide/react/installation.mdx b/guide/react/installation.mdx
index 257007a..31c5a32 100644
--- a/guide/react/installation.mdx
+++ b/guide/react/installation.mdx
@@ -11,24 +11,9 @@ import TabItem from "@theme/TabItem";
Install `@fishjam-cloud/react-client` package:
-
-
-
-
- ```
- npm install @fishjam-cloud/react-client
- ```
-
-
-
-
-
- ```
- yarn add @fishjam-cloud/react-client
- ```
-
-
-
+```bash npm2yarn
+npm install @fishjam-cloud/react-client
+```
### 2. Setup Fishjam context
diff --git a/guide/server.mdx b/guide/server.mdx
index c53f294..f565bf4 100644
--- a/guide/server.mdx
+++ b/guide/server.mdx
@@ -15,7 +15,7 @@ It's also possible to use the bare REST API, in this case you can skip this step
- ```
+ ```bash
npm install @fishjam-cloud/js-server-sdk
```
@@ -23,7 +23,7 @@ It's also possible to use the bare REST API, in this case you can skip this step
- ```
+ ```bash
yarn add @fishjam-cloud/js-server-sdk
```
@@ -31,7 +31,7 @@ It's also possible to use the bare REST API, in this case you can skip this step
- ```
+ ```bash
pip install fishjam-server-sdk
```
@@ -39,7 +39,7 @@ It's also possible to use the bare REST API, in this case you can skip this step
- ```
+ ```bash
poetry add fishjam-server-sdk
```
diff --git a/package.json b/package.json
index b989a8b..2262885 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"dependencies": {
"@docusaurus/core": "3.5.2",
"@docusaurus/preset-classic": "3.5.2",
+ "@docusaurus/remark-plugin-npm2yarn": "^3.5.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
diff --git a/static/img/social-card.png b/static/img/social-card.png
index b4e415f..716fbba 100644
Binary files a/static/img/social-card.png and b/static/img/social-card.png differ
diff --git a/yarn.lock b/yarn.lock
index eeb53d0..84ed7b0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1498,6 +1498,17 @@
"@docusaurus/theme-search-algolia" "3.5.2"
"@docusaurus/types" "3.5.2"
+"@docusaurus/remark-plugin-npm2yarn@^3.5.2":
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/@docusaurus/remark-plugin-npm2yarn/-/remark-plugin-npm2yarn-3.5.2.tgz#892a63a9b53475d7c59957bd67277656dcd91079"
+ integrity sha512-EAD7R/skPuhW3lWZyDhRuFs3m2EGaR008tuoe6SrFre7PifoxmSCwXk8Nb4VtVRKnnbn4IgHyqq+ma47gGmKwg==
+ dependencies:
+ mdast-util-mdx "^3.0.0"
+ npm-to-yarn "^2.2.1"
+ tslib "^2.6.0"
+ unified "^11.0.3"
+ unist-util-visit "^5.0.0"
+
"@docusaurus/theme-classic@3.5.2":
version "3.5.2"
resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.5.2.tgz#602ddb63d987ab1f939e3760c67bc1880f01c000"
@@ -6248,6 +6259,11 @@ npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
+npm-to-yarn@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/npm-to-yarn/-/npm-to-yarn-2.2.1.tgz#048843a6630621daffc6a239dfc89698b8abf7e8"
+ integrity sha512-O/j/ROyX0KGLG7O6Ieut/seQ0oiTpHF2tXAcFbpdTLQFiaNtkyTXXocM1fwpaa60dg1qpWj0nHlbNhx6qwuENQ==
+
nprogress@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1"