Skip to content

Commit f0abea1

Browse files
Release 0.22.0 (#203)
## Description Describe your changes. ## Motivation and Context Why is this change required? What problem does it solve? If it fixes an open issue, please link to the issue here. ## Documentation impact - [ ] Documentation update required - [ ] Documentation updated [in another PR](_) - [ ] No documentation update required ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
1 parent f48ab50 commit f0abea1

20 files changed

Lines changed: 488 additions & 123 deletions

File tree

examples/selective-subscription/README.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,30 @@ A complete example demonstrating Fishjam's selective subscription flow with both
66

77
1. Install dependencies:
88

9-
```bash
10-
yarn
11-
```
9+
```bash
10+
yarn
11+
```
1212

1313
2. Install frontend dependencies:
1414

15-
```bash
16-
yarn install:frontend
17-
```
15+
```bash
16+
yarn install:frontend
17+
```
1818

1919
3. Copy and configure the environment:
2020

21-
```bash
22-
cp .env.example .env
23-
```
21+
```bash
22+
cp .env.example .env
23+
```
2424

25-
Set the following in `.env`:
25+
Set the following in `.env`:
2626

27-
```
28-
FISHJAM_ID=your_fishjam_id
29-
FISHJAM_TOKEN=your_fishjam_management_token
30-
```
27+
```
28+
FISHJAM_ID=your_fishjam_id
29+
FISHJAM_TOKEN=your_fishjam_management_token
30+
```
3131

32-
fishjam_id and fishjam_management_token can be found at your <https://fishjam.io> dashboard
32+
fishjam_id and fishjam_management_token can be found at your <https://fishjam.io> dashboard
3333

3434
### Start both backend and frontend
3535

@@ -67,29 +67,29 @@ BACKEND API
6767
- Create a new peer in a room configured for manual subscription.
6868
- Example:
6969

70-
```bash
71-
curl http://localhost:3000/peers
72-
```
70+
```bash
71+
curl http://localhost:3000/peers
72+
```
7373

7474
- Response: JSON containing the created peer ID and a peer token.
7575

7676
- POST /subscribe_peer?subId=<SUBSCRIBER_ID>&prodId=<PRODUCER_ID>
7777
- Subscribe the subscriber peer (subId) to all tracks published by the producer peer (prodId).
7878
- Example:
7979

80-
```bash
81-
curl -X POST "http://localhost:3000/subscribe_peer?subId=72457c2f-e4d2-46aa-9ff2-5a400f169df7&prodId=41ed79fb-6ce1-47b0-b5c8-1c33b78d95b4"
82-
```
80+
```bash
81+
curl -X POST "http://localhost:3000/subscribe_peer?subId=72457c2f-e4d2-46aa-9ff2-5a400f169df7&prodId=41ed79fb-6ce1-47b0-b5c8-1c33b78d95b4"
82+
```
8383

8484
- Response: JSON status and any error messages.
8585

8686
- POST /subscribe_tracks?subId=<SUBSCRIBER_ID>&tracks=<TRACK_ID>,<TRACK_ID>...
8787
- Subscribe the subscriber peer (subId) to a comma-separated list of specific tracks.
8888
- Example (subscribe to one track):
8989

90-
```bash
91-
curl -X POST "http://localhost:3000/subscribe_tracks?subId=41ed79fb-6ce1-47b0-b5c8-1c33b78d95b4&tracks=72457c2f-e4d2-46aa-9ff2-5a400f169df7:3c7ccb28-542c-418d-aaa1-e25b4c067824"
92-
```
90+
```bash
91+
curl -X POST "http://localhost:3000/subscribe_tracks?subId=41ed79fb-6ce1-47b0-b5c8-1c33b78d95b4&tracks=72457c2f-e4d2-46aa-9ff2-5a400f169df7:3c7ccb28-542c-418d-aaa1-e25b4c067824"
92+
```
9393

9494
- Response: JSON status and any error messages.
9595

examples/selective-subscription/frontend/src/App.tsx

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,49 +21,54 @@ function App() {
2121
const [peers, setPeers] = useState<Peer[]>([]);
2222

2323
const addNotification = (type: string, data: any) => {
24-
setNotifications(prev => [{
25-
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
26-
type, timestamp: new Date(), data
27-
}, ...prev.slice(0, 49)]);
24+
setNotifications((prev) => [
25+
{
26+
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
27+
type,
28+
timestamp: new Date(),
29+
data,
30+
},
31+
...prev.slice(0, 49),
32+
]);
2833
};
2934

3035
const handlePeerCreated = (peer: Peer) => {
31-
setPeers(prev => [...prev, peer]);
36+
setPeers((prev) => [...prev, peer]);
3237
addNotification('peerCreated', { peerId: peer.id });
3338
};
3439

35-
return (
36-
<div style={{ fontFamily: 'Arial, sans-serif' }}>
40+
return (
41+
<div style={{ fontFamily: 'Arial, sans-serif' }}>
3742
<header style={{ backgroundColor: '#343a40', color: 'white', padding: '20px 0', marginBottom: '30px' }}>
3843
<div style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px' }}>
39-
<h1>🐟 Fishjam Selective Subscription Dashboard</h1>
40-
<p>Create peers and test selective subscription features</p>
41-
<p>
42-
As a Fishjam client you can use:{' '}
43-
<a
44-
href="https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client"
45-
target="_blank"
46-
rel="noopener noreferrer"
47-
style={{ color: '#ffd700', textDecoration: 'underline' }}
48-
>
49-
minimal-react client app
50-
</a>
51-
</p>
44+
<h1>🐟 Fishjam Selective Subscription Dashboard</h1>
45+
<p>Create peers and test selective subscription features</p>
46+
<p>
47+
As a Fishjam client you can use:{' '}
48+
<a
49+
href="https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client"
50+
target="_blank"
51+
rel="noopener noreferrer"
52+
style={{ color: '#ffd700', textDecoration: 'underline' }}
53+
>
54+
minimal-react client app
55+
</a>
56+
</p>
5257
</div>
5358
</header>
54-
59+
5560
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
5661
<div>
57-
<CreatePeerSection peers={peers} onPeerCreated={handlePeerCreated} />
58-
<SubscribeToPeerSection peers={peers} onNotification={addNotification} />
59-
<SubscribeToTracksSection peers={peers} onNotification={addNotification} />
62+
<CreatePeerSection peers={peers} onPeerCreated={handlePeerCreated} />
63+
<SubscribeToPeerSection peers={peers} onNotification={addNotification} />
64+
<SubscribeToTracksSection peers={peers} onNotification={addNotification} />
6065
</div>
6166
<div>
62-
<NotificationsSection localNotifications={notifications} />
67+
<NotificationsSection localNotifications={notifications} />
6368
</div>
6469
</div>
65-
</div>
66-
);
70+
</div>
71+
);
6772
}
6873

6974
export default App;

examples/selective-subscription/frontend/src/components/CreatePeerSection.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,16 @@ export const CreatePeerSection: React.FC<CreatePeerSectionProps> = ({ peers, onP
3131
<button onClick={createPeer} disabled={isCreating}>
3232
{isCreating ? 'Creating...' : 'Create New Peer'}
3333
</button>
34-
34+
3535
<div style={{ marginTop: '20px' }}>
3636
<h4>Created Peers ({peers.length})</h4>
3737
{peers.map((peer) => (
38-
<div key={peer.id} style={{ margin: '10px 0', padding: '10px', backgroundColor: '#f9f9f9', borderRadius: '4px' }}>
38+
<div
39+
key={peer.id}
40+
style={{ margin: '10px 0', padding: '10px', backgroundColor: '#f9f9f9', borderRadius: '4px' }}
41+
>
3942
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '8px' }}>
40-
<strong>ID:</strong>
43+
<strong>ID:</strong>
4144
<code style={{ flex: 1 }}>{peer.id}</code>
4245
<button onClick={() => navigator.clipboard.writeText(peer.id)}>Copy</button>
4346
</div>
@@ -51,4 +54,4 @@ export const CreatePeerSection: React.FC<CreatePeerSectionProps> = ({ peers, onP
5154
</div>
5255
</div>
5356
);
54-
};
57+
};

examples/selective-subscription/frontend/src/components/NotificationsSection.tsx

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({ loca
2222
try {
2323
const notification = JSON.parse(event.data);
2424
if (notification.type !== 'heartbeat') {
25-
setServerNotifications(prev => [{
26-
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
27-
type: notification.type,
28-
timestamp: new Date(notification.timestamp),
29-
data: notification.data
30-
}, ...prev.slice(0, 19)]);
25+
setServerNotifications((prev) => [
26+
{
27+
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
28+
type: notification.type,
29+
timestamp: new Date(notification.timestamp),
30+
data: notification.data,
31+
},
32+
...prev.slice(0, 19),
33+
]);
3134
}
3235
} catch {}
3336
};
@@ -41,9 +44,14 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({ loca
4144

4245
const getIcon = (type: string) => {
4346
const icons: Record<string, string> = {
44-
peerCreated: '✅', peerConnected: '✅', peerSubscribed: '🔗',
45-
tracksSubscribed: '🔗', peerDisconnected: '❌', trackAdded: '🎥',
46-
trackRemoved: '🗑️', subscriptionError: '⚠️'
47+
peerCreated: '✅',
48+
peerConnected: '✅',
49+
peerSubscribed: '🔗',
50+
tracksSubscribed: '🔗',
51+
peerDisconnected: '❌',
52+
trackAdded: '🎥',
53+
trackRemoved: '🗑️',
54+
subscriptionError: '⚠️',
4755
};
4856
return icons[type] || '📢';
4957
};
@@ -59,13 +67,24 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({ loca
5967
<p>No notifications yet</p>
6068
) : (
6169
allNotifications.map((notification) => (
62-
<div key={notification.id} style={{ margin: '10px 0', padding: '15px', backgroundColor: '#f9f9f9', borderRadius: '4px' }}>
70+
<div
71+
key={notification.id}
72+
style={{ margin: '10px 0', padding: '15px', backgroundColor: '#f9f9f9', borderRadius: '4px' }}
73+
>
6374
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '10px', fontWeight: 'bold' }}>
6475
<span style={{ marginRight: '8px' }}>{getIcon(notification.type)}</span>
6576
<span style={{ flex: 1 }}>{notification.type}</span>
6677
<span style={{ fontSize: '12px' }}>{notification.timestamp.toLocaleTimeString()}</span>
6778
</div>
68-
<pre style={{ fontSize: '12px', margin: 0, backgroundColor: '#f0f0f0', padding: '10px', borderRadius: '4px' }}>
79+
<pre
80+
style={{
81+
fontSize: '12px',
82+
margin: 0,
83+
backgroundColor: '#f0f0f0',
84+
padding: '10px',
85+
borderRadius: '4px',
86+
}}
87+
>
6988
{JSON.stringify(notification.data, null, 2)}
7089
</pre>
7190
</div>
@@ -74,4 +93,4 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({ loca
7493
</div>
7594
</div>
7695
);
77-
};
96+
};

examples/selective-subscription/frontend/src/components/SubscribeToPeerSection.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,36 @@ export const SubscribeToPeerSection: React.FC<SubscribeToPeerSectionProps> = ({
3131
return (
3232
<div style={{ marginBottom: '30px', padding: '20px', border: '1px solid #ddd', borderRadius: '8px' }}>
3333
<h3>Subscribe to All Peer Tracks</h3>
34-
34+
3535
<div style={{ marginBottom: '15px' }}>
3636
<label>Subscriber Peer:</label>
3737
<select value={subscriberId} onChange={(e) => setSubscriberId(e.target.value)}>
3838
<option value="">Select subscriber...</option>
39-
{peers.map(peer => (
40-
<option key={peer.id} value={peer.id}>{peer.id}</option>
39+
{peers.map((peer) => (
40+
<option key={peer.id} value={peer.id}>
41+
{peer.id}
42+
</option>
4143
))}
4244
</select>
4345
</div>
44-
46+
4547
<div style={{ marginBottom: '15px' }}>
4648
<label>Producer Peer:</label>
4749
<select value={producerId} onChange={(e) => setProducerId(e.target.value)}>
4850
<option value="">Select producer...</option>
49-
{peers.filter(peer => peer.id !== subscriberId).map(peer => (
50-
<option key={peer.id} value={peer.id}>{peer.id}</option>
51-
))}
51+
{peers
52+
.filter((peer) => peer.id !== subscriberId)
53+
.map((peer) => (
54+
<option key={peer.id} value={peer.id}>
55+
{peer.id}
56+
</option>
57+
))}
5258
</select>
5359
</div>
54-
60+
5561
<button onClick={subscribeToPeer} disabled={isSubscribing || !subscriberId || !producerId}>
5662
{isSubscribing ? 'Subscribing...' : 'Subscribe to All Tracks'}
5763
</button>
5864
</div>
5965
);
60-
};
66+
};

examples/selective-subscription/frontend/src/components/SubscribeToTracksSection.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ export const SubscribeToTracksSection: React.FC<SubscribeToTracksSectionProps> =
2121
if (!subscriberId || !tracks.trim()) return;
2222
setIsSubscribing(true);
2323
try {
24-
const trackIds = tracks.split(',').map(t => t.trim()).filter(t => t);
24+
const trackIds = tracks
25+
.split(',')
26+
.map((t) => t.trim())
27+
.filter((t) => t);
2528
await axios.post(`${API_BASE_URL}/subscribe_tracks?subId=${subscriberId}&tracks=${trackIds.join(',')}`);
2629
onNotification('tracksSubscribed', { subscriberId, tracks: trackIds });
2730
} finally {
@@ -32,17 +35,19 @@ export const SubscribeToTracksSection: React.FC<SubscribeToTracksSectionProps> =
3235
return (
3336
<div style={{ marginBottom: '30px', padding: '20px', border: '1px solid #ddd', borderRadius: '8px' }}>
3437
<h3>Subscribe to Specific Tracks</h3>
35-
38+
3639
<div style={{ marginBottom: '15px' }}>
3740
<label>Subscriber Peer:</label>
3841
<select value={subscriberId} onChange={(e) => setSubscriberId(e.target.value)}>
3942
<option value="">Select subscriber...</option>
40-
{peers.map(peer => (
41-
<option key={peer.id} value={peer.id}>{peer.id}</option>
43+
{peers.map((peer) => (
44+
<option key={peer.id} value={peer.id}>
45+
{peer.id}
46+
</option>
4247
))}
4348
</select>
4449
</div>
45-
50+
4651
<div style={{ marginBottom: '15px' }}>
4752
<label>Track IDs (comma-separated):</label>
4853
<input
@@ -52,10 +57,10 @@ export const SubscribeToTracksSection: React.FC<SubscribeToTracksSectionProps> =
5257
onChange={(e) => setTracks(e.target.value)}
5358
/>
5459
</div>
55-
60+
5661
<button onClick={subscribeToTracks} disabled={isSubscribing || !subscriberId || !tracks.trim()}>
5762
{isSubscribing ? 'Subscribing...' : 'Subscribe to Tracks'}
5863
</button>
5964
</div>
6065
);
61-
};
66+
};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const API_BASE_URL = 'http://localhost:3000';
1+
export const API_BASE_URL = 'http://localhost:3000';
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { StrictMode } from 'react'
2-
import { createRoot } from 'react-dom/client'
3-
import App from './App.tsx'
1+
import { StrictMode } from 'react';
2+
import { createRoot } from 'react-dom/client';
3+
import App from './App.tsx';
44

55
createRoot(document.getElementById('root')!).render(
66
<StrictMode>
77
<App />
8-
</StrictMode>,
9-
)
8+
</StrictMode>
9+
);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { defineConfig } from 'vite'
2-
import react from '@vitejs/plugin-react'
1+
import { defineConfig } from 'vite';
2+
import react from '@vitejs/plugin-react';
33

44
// https://vite.dev/config/
55
export default defineConfig({
66
plugins: [react()],
7-
})
7+
});

0 commit comments

Comments
 (0)