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"