kasunk99-livestream-core 0.2.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,8 +16,16 @@ export type UseHostSocketOptions = {
16
16
  /** App-level user ID forwarded to the server on join-room (optional). */
17
17
  hostUserId?: string;
18
18
  };
19
+ export type HostChatMessage = {
20
+ id: string;
21
+ displayName: string;
22
+ text: string;
23
+ timestamp: number;
24
+ };
19
25
  export type UseHostSocketReturn = HostState & {
26
+ chatMessages: HostChatMessage[];
20
27
  setDisplayName: (name: string) => void;
28
+ sendChatMessage: (text: string) => void;
21
29
  startPreview: () => Promise<void>;
22
30
  stopPreview: () => void;
23
31
  startLive: () => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"useHostSocket.d.ts","sourceRoot":"","sources":["../../src/hooks/useHostSocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAoB3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG;IAC5C,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC,CAAC;AAMF,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CAmlBrF"}
1
+ {"version":3,"file":"useHostSocket.d.ts","sourceRoot":"","sources":["../../src/hooks/useHostSocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAoB3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG;IAC5C,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC,CAAC;AAMF,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CA4nBrF"}
@@ -36,6 +36,7 @@ export function useHostSocket(options = {}) {
36
36
  // Subscribe to module-level state so all hook instances stay in sync
37
37
  // and the state survives remount (tab navigation).
38
38
  const [state, setLocalState] = useState(getHostState);
39
+ const [chatMessages, setChatMessages] = useState([]);
39
40
  useEffect(() => {
40
41
  // If the store has a streamURL but our local copy doesn't (fresh mount),
41
42
  // restore it from the active stream so the preview shows immediately.
@@ -107,6 +108,7 @@ export function useHostSocket(options = {}) {
107
108
  }
108
109
  catch { /* ignore */ }
109
110
  resetHostState();
111
+ setChatMessages([]);
110
112
  // Step 3 — stop tracks deferred: give the executor a moment to finish pc.close().
111
113
  // Screen stream: use release() not t.stop(). release() calls TrackPrivate.dispose()
112
114
  // → ScreenCaptureController.dispose() → MediaProjectionService.abort() +
@@ -181,6 +183,36 @@ export function useHostSocket(options = {}) {
181
183
  socket.off('ice-servers', onIceServers);
182
184
  };
183
185
  }, [fullCleanup]);
186
+ // ── Chat subscription ──────────────────────────────────────────────────────
187
+ // Registered on a separate effect keyed to live state so it is guaranteed to
188
+ // be active only while the host is in the room (socket.join runs as part of
189
+ // startLive). Registering it in the socket setup effect is too early — the host
190
+ // has not joined the room yet, and reconnects after navigate-away clear the
191
+ // room membership, so we need to re-register on every live transition.
192
+ useEffect(() => {
193
+ if (!state.live) {
194
+ setChatMessages([]);
195
+ return;
196
+ }
197
+ const socket = hostSession.socket;
198
+ if (!socket)
199
+ return;
200
+ const onChatMessage = (msg) => {
201
+ if (!msg || typeof msg !== 'object')
202
+ return;
203
+ const m = msg;
204
+ const text = typeof m.text === 'string' ? m.text.trim() : '';
205
+ if (!text)
206
+ return;
207
+ const displayName = typeof m.displayName === 'string' ? m.displayName : 'User';
208
+ const timestamp = typeof m.timestamp === 'number' ? m.timestamp : Date.now();
209
+ const id = `${String(m.peerId ?? 'p')}-${timestamp}-${text.slice(0, 6)}`;
210
+ setChatMessages((prev) => [...prev.slice(-99), { id, displayName, text, timestamp }]);
211
+ };
212
+ socket.on('chat-message', onChatMessage);
213
+ return () => { socket.off('chat-message', onChatMessage); };
214
+ // eslint-disable-next-line react-hooks/exhaustive-deps
215
+ }, [state.live]);
184
216
  // ── Permissions ────────────────────────────────────────────────────────────
185
217
  const requestCameraMicPermissions = useCallback(async () => {
186
218
  if (Platform.OS !== 'android')
@@ -545,9 +577,17 @@ export function useHostSocket(options = {}) {
545
577
  const setDisplayName = useCallback((name) => {
546
578
  patchHostState({ displayName: name });
547
579
  }, []);
580
+ const sendChatMessage = useCallback((text) => {
581
+ const trimmed = text.trim();
582
+ if (!trimmed || !hostSession.socket?.connected)
583
+ return;
584
+ hostSession.socket.emit('chat-message', { text: trimmed });
585
+ }, []);
548
586
  return {
549
587
  ...state,
588
+ chatMessages,
550
589
  setDisplayName,
590
+ sendChatMessage,
551
591
  startPreview,
552
592
  stopPreview,
553
593
  startLive,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kasunk99-livestream-core",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "description": "Reusable livestream viewer/host module for React Native (Expo) — mediasoup + Socket.IO",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",