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
71 changes: 71 additions & 0 deletions .github/workflows/mobile_eas_build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Mobile EAS Build
on:
pull_request:
types: [labeled]

permissions:
contents: read
pull-requests: write

jobs:
build:
if: ${{ github.event.label.name == 'eas build' }}
runs-on: macOS-latest
steps:
- name: 🏗 Setup repo
uses: actions/checkout@v4
with:
submodules: recursive

- name: 🏗 Setup Node
uses: actions/setup-node@v4
with:
node-version: 22.x
cache: npm

- name: 🏗 Setup EAS
uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}

- name: Use corepack
run: corepack enable

- name: 📦 Install dependencies
run: yarn && yarn build

- name: 🚀 Build app
run: eas build --non-interactive --platform=all --profile production
working-directory: examples/mobile-client/fishjam-chat

- name: 🛫 Submit iOS app to TestFlight
run: eas submit --non-interactive --platform=ios --latest
working-directory: examples/mobile-client/fishjam-chat

- name: ⛓️‍💥 Get iOS archive url and version
id: ios_build
run: eas build:list --json --non-interactive | jq -r '[.[] | select(.platform=="IOS")][0] | "version=\(.appVersion) (\(.appBuildVersion))"' >> $GITHUB_OUTPUT
working-directory: examples/mobile-client/fishjam-chat

- name: ⛓️‍💥 Get Android archive url and version
id: android_build
run: eas build:list --json --non-interactive | jq -r '[.[] | select(.platform=="ANDROID")][0] | "url=\(.artifacts.applicationArchiveUrl)\nversion=\(.appVersion) (\(.appBuildVersion))"' >> $GITHUB_OUTPUT
working-directory: examples/mobile-client/fishjam-chat

- name: 📱 Get App Store Connect app ID
id: asc_app
run: echo "id=$(jq -r '.submit.production.ios.ascAppId' eas.json)" >> $GITHUB_OUTPUT
working-directory: examples/mobile-client/fishjam-chat

- name: 💬 Add comment with build links
uses: actions/github-script@v7
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '**Download links**\nAndroid - ${{ steps.android_build.outputs.version }}: ${{ steps.android_build.outputs.url }}\niOS - ${{ steps.ios_build.outputs.version }}: https://testflight.apple.com/v1/app/${{ steps.asc_app.outputs.id }}'
})
3 changes: 3 additions & 0 deletions examples/mobile-client/fishjam-chat/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
EXPO_PUBLIC_FISHJAM_ID=
EXPO_PUBLIC_VIDEOROOM_STAGING_SANDBOX_URL=
EXPO_PUBLIC_SANDBOX_API_URL=
18 changes: 18 additions & 0 deletions examples/mobile-client/fishjam-chat/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
extends: ['expo'],
ignorePatterns: [
'dist/*',
'node_modules/*',
'coverage/*',
'build/*',
'ios/*',
'android/*',
'.eslintrc.js',
'prettier.config.js',
'global.d.ts',
],
rules: {
'import/no-unresolved': 'off',
},
};
41 changes: 41 additions & 0 deletions examples/mobile-client/fishjam-chat/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# dependencies
node_modules/

# Expo
.expo/
dist/
web-build/
expo-env.d.ts

# Native
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Metro
.metro-health-check*

# debug
npm-debug.*
yarn-debug.*
yarn-error.*

# macOS
.DS_Store
*.pem

# local env files
.env*.local

# typescript
*.tsbuildinfo

app-example

# generated native folders
/ios
/android
84 changes: 84 additions & 0 deletions examples/mobile-client/fishjam-chat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# React Native Fishjam example

## Prerequisites

Copy `.env.example` to `.env` in the `examples/mobile-client/fishjam-chat` directory and fill in the required value:

- `EXPO_PUBLIC_FISHJAM_ID` - Fishjam ID for connecting to fishjam platform
- `EXPO_PUBLIC_SANDBOX_API_URL` - Sandbox API URL used by `useSandbox` to create rooms and fetch peer, viewer, and streamer tokens

You can find these values in the Fishjam dashboard:

- `Fishjam ID` is available at [fishjam.io/app](https://fishjam.io/app).
- `Sandbox API url` is available at [fishjam.io/app/sandbox](https://fishjam.io/app/sandbox).

There also exists this additional environment variable, which is used for internal testing purposes:

- `EXPO_PUBLIC_VIDEOROOM_STAGING_SANDBOX_URL` - Sandbox URL for VideoRoom staging environment

## Example Overview

The app has 2 tabs showing different ways to connect to Fishjam video calls:

**VideoRoom** - Connect to VideoRoom (Fishjam's demo service, something like Google Meet) by entering a room name and username. The app automatically creates the room and generates tokens for you.

**Livestream** - Join existing livestreams or create your own livestream.

## Project setup

1. Clone the repository:

```
git clone https://github.com/fishjam-cloud/web-client-sdk.git
cd web-client-sdk
```

2. Install dependencies and build project:

```sh
yarn
yarn build
```

> [!IMPORTANT]
> Before prebuilding, replace all occurrences of `io.fishjam.example.fishjamchat` in `app.json` with your own bundle identifier:
>
> - **iOS bundle identifier** — `expo.ios.bundleIdentifier`
> - **Android package name** — `expo.android.package`
>
> For example, if your bundle ID is `com.yourcompany.yourapp`:
>
> - iOS & Android: `com.yourcompany.yourapp`
> - ScreenBroadcastExtension: `com.yourcompany.yourapp.ScreenBroadcastExtension`
> - App group: `group.com.yourcompany.yourapp`

3. Prebuild native files in example directory:

```sh
cd examples/mobile-client/fishjam-chat
npx expo prebuild --clean
```

> [!NOTE]
> Be sure to run `npx expo prebuild` and not `yarn prebuild` as there's an issue with path generation for the `ios/.xcode.env.local` file

4. Build app:

```
yarn ios
yarn android
```

## Development

1. Whenever you make changes in the `packages` directory, make sure to build the app in the root directory (not in `examples/mobile-client/fishjam-chat`). This ensures that all related workspaces are also built:

```sh
yarn build
```

2. Linter (run in the root directory):

```sh
yarn lint
```
102 changes: 102 additions & 0 deletions examples/mobile-client/fishjam-chat/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"expo": {
"name": "fishjam-chat",
"slug": "fishjam-chat",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "fishjamchat",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
"ios": {
"supportsTablet": true,
"bundleIdentifier": "io.fishjam.example.fishjamchat",
"infoPlist": {
"NSCameraUsageDescription": "Allow $(PRODUCT_NAME) to access your camera.",
"NSMicrophoneUsageDescription": "Allow $(PRODUCT_NAME) to access your microphone.",
"ITSAppUsesNonExemptEncryption": false
}
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"monochromeImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false,
"permissions": [
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
"android.permission.MODIFY_AUDIO_SETTINGS",
"android.permission.ACCESS_NETWORK_STATE",
"android.permission.ACCESS_WIFI_STATE",
"android.permission.FOREGROUND_SERVICE",
"android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION",
"android.permission.FOREGROUND_SERVICE_CAMERA",
"android.permission.FOREGROUND_SERVICE_MICROPHONE",
"android.permission.POST_NOTIFICATIONS"
],
"package": "io.fishjam.example.fishjamchat"
},
"web": {
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"@fishjam-cloud/react-native-client",
{
"android": {
"supportsPictureInPicture": true,
"enableForegroundService": true,
"enableScreensharing": true
},
"ios": {
"enableScreensharing": true,
"enableVoIPBackgroundMode": true,
"supportsPictureInPicture": true
}
}
],
[
"expo-splash-screen",
{
"image": "./assets/images/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff",
"dark": {
"backgroundColor": "#000000"
}
}
]
],
"experiments": {
"typedRoutes": true
},
"extra": {
"eas": {
"projectId": "3cb3251a-603a-4c13-ab69-6fac3249072d",
"build": {
"experimental": {
"ios": {
"appExtensions": [
{
"targetName": "ScreenBroadcastExtension",
"bundleIdentifier": "io.fishjam.example.fishjamchat.ScreenBroadcastExtension",
"entitlements": {
"com.apple.security.application-groups": [
"group.io.fishjam.example.fishjamchat"
]
}
}
]
}
}
}
}
},
"owner": "fishjam-cloud"
}
}
34 changes: 34 additions & 0 deletions examples/mobile-client/fishjam-chat/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Ionicons } from '@expo/vector-icons';
import { Tabs } from 'expo-router';

import { BrandColors } from '../../utils/Colors';

export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: BrandColors.darkBlue100,
tabBarInactiveTintColor: '#8E8E93',
headerShown: false,
}}>
<Tabs.Screen
name="room"
options={{
title: 'Room',
tabBarIcon: ({ color, size }) => (
<Ionicons name="videocam" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="livestream"
options={{
title: 'Livestream',
tabBarIcon: ({ color, size }) => (
<Ionicons name="radio" size={size} color={color} />
),
}}
/>
</Tabs>
);
}
Loading
Loading