@streamplace/components 0.7.26 → 0.7.27

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.
@@ -178,6 +178,11 @@ function useWebRTCIngest({ endpoint, }) {
178
178
  const ingestConnectionState = (0, __1.usePlayerStore)((x) => x.ingestConnectionState);
179
179
  const setIngestConnectionState = (0, __1.usePlayerStore)((x) => x.setIngestConnectionState);
180
180
  const storedKey = (0, __1.useStreamKey)();
181
+ (0, react_1.useEffect)(() => {
182
+ if (storedKey?.error) {
183
+ console.error("error creating stream key", storedKey.error);
184
+ }
185
+ }, [storedKey?.error]);
181
186
  const [peerConnection, setPeerConnection] = (0, react_1.useState)(null);
182
187
  const videoTransceiver = (0, react_1.useRef)(null);
183
188
  const audioTransceiver = (0, react_1.useRef)(null);
@@ -211,7 +216,8 @@ function useWebRTCIngest({ endpoint, }) {
211
216
  negotiateConnectionWithClientOffer(peerConnection, endpoint, storedKey.streamKey?.privateKey);
212
217
  });
213
218
  peerConnection.addEventListener("track", (ev) => {
214
- console.log(ev);
219
+ console.log(`got peerconnection track with ${ev.track.kind}`, ev.track.id);
220
+ // console.log(ev);
215
221
  });
216
222
  setPeerConnection(peerConnection);
217
223
  return () => {
@@ -43,11 +43,20 @@ function VideoNative(props) {
43
43
  importPromise = Promise.resolve().then(() => __importStar(require("./video-async.native")));
44
44
  }
45
45
  const [videoNativeModule, setVideoNativeModule] = (0, react_1.useState)(null);
46
+ const [error, setError] = (0, react_1.useState)(null);
46
47
  (0, react_1.useEffect)(() => {
47
- importPromise?.then((module) => {
48
+ importPromise
49
+ ?.then((module) => {
48
50
  setVideoNativeModule(module);
51
+ })
52
+ .catch((err) => {
53
+ setError(err.message);
49
54
  });
50
55
  }, []);
56
+ if (error) {
57
+ console.error(error);
58
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: { flex: 1, justifyContent: "center", alignItems: "center" }, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { children: error }) }));
59
+ }
51
60
  if (!videoNativeModule) {
52
61
  return (0, jsx_runtime_1.jsx)(react_native_1.View, {});
53
62
  }
File without changes
@@ -0,0 +1,24 @@
1
+ // awkward use of require()? you betcha. but import() with Metro causes it to try and
2
+ // resolve the package at compile-time even if not installed, so here we are.
3
+ let rnqc = null;
4
+ let expoCrypto = null;
5
+ try {
6
+ rnqc = require("react-native-quick-crypto");
7
+ }
8
+ catch (err) { }
9
+ try {
10
+ expoCrypto = require("expo-crypto");
11
+ }
12
+ catch (err) { }
13
+ if (!rnqc && !expoCrypto) {
14
+ throw new Error("Livestreaming requires one of react-native-quick-crypto or expo-crypto");
15
+ }
16
+ else if (!rnqc && expoCrypto) {
17
+ // @atproto/crypto dependencies expect crypto.getRandomValues to be a function
18
+ if (typeof globalThis.crypto === "undefined") {
19
+ globalThis.crypto = {};
20
+ }
21
+ if (typeof globalThis.crypto.getRandomValues === "undefined") {
22
+ globalThis.crypto.getRandomValues = expoCrypto.getRandomValues;
23
+ }
24
+ }
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.storage = exports.Dashboard = exports.VideoRetry = exports.zero = exports.ui = exports.PlayerUI = exports.Player = exports.usePlayerContext = exports.withPlayerProvider = exports.PlayerProvider = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  // barrel file :)
6
+ require("./crypto-polyfill");
6
7
  tslib_1.__exportStar(require("./livestream-provider"), exports);
7
8
  tslib_1.__exportStar(require("./livestream-store"), exports);
8
9
  tslib_1.__exportStar(require("./player-store"), exports);
@@ -160,11 +160,9 @@ const reduceChatIncremental = (state, newMessages, blocks, hideUris = []) => {
160
160
  const newAuthors = { ...state.authors };
161
161
  let hasChanges = false;
162
162
  const removedKeys = new Set();
163
- console.log("newMessages", newMessages);
164
163
  for (const msg of newMessages) {
165
164
  if (msg.deleted) {
166
165
  hasChanges = true;
167
- console.log("deleted", msg.uri);
168
166
  removedKeys.add(msg.uri);
169
167
  }
170
168
  }
@@ -81,7 +81,7 @@ const useStreamKey = () => {
81
81
  setStreamKey(JSON.stringify(newKey));
82
82
  setKey(newKey);
83
83
  };
84
- generateKey();
84
+ generateKey().catch((err) => setError(err.message));
85
85
  // eslint-disable-next-line react-hooks/exhaustive-deps
86
86
  }, [key, setStreamKey]);
87
87
  return { streamKey: key, error };
@@ -3,10 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PlayerProvider = void 0;
4
4
  exports.withPlayerProvider = withPlayerProvider;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
- const crypto_1 = require("crypto");
7
6
  const react_1 = require("react");
8
7
  const context_1 = require("./context");
9
8
  const player_store_1 = require("./player-store");
9
+ function randomUUID() {
10
+ let dt = new Date().getTime();
11
+ var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
12
+ var r = (dt + Math.random() * 16) % 16 | 0;
13
+ dt = Math.floor(dt / 16);
14
+ return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
15
+ });
16
+ return uuid;
17
+ }
10
18
  const PlayerProvider = ({ children, initialPlayers = [], defaultId = Math.random().toString(36).slice(8), }) => {
11
19
  const [players, setPlayers] = (0, react_1.useState)(() => {
12
20
  // Initialize with any initial player IDs provided
@@ -21,7 +29,7 @@ const PlayerProvider = ({ children, initialPlayers = [], defaultId = Math.random
21
29
  return initialPlayerStores;
22
30
  });
23
31
  const createPlayer = (0, react_1.useCallback)((id) => {
24
- const playerId = id || (0, crypto_1.randomUUID)();
32
+ const playerId = id || randomUUID();
25
33
  const playerStore = (0, player_store_1.makePlayerStore)(playerId);
26
34
  setPlayers((prev) => ({
27
35
  ...prev,
@@ -12,8 +12,8 @@ const tslib_1 = require("tslib");
12
12
  const jsx_runtime_1 = require("react/jsx-runtime");
13
13
  const react_1 = tslib_1.__importStar(require("react"));
14
14
  const zustand_1 = require("zustand");
15
- const player_store_1 = require("../player-store");
16
15
  const player_state_1 = require("./player-state");
16
+ const player_store_1 = require("./player-store");
17
17
  const SinglePlayerContext = (0, react_1.createContext)(null);
18
18
  /**
19
19
  * Provider component for a single player that creates a scoped context
@@ -111,7 +111,7 @@ function useCreateStreamRecord() {
111
111
  }
112
112
  // Use customUrl if provided, otherwise fall back to the store URL
113
113
  const finalUrl = customUrl || url;
114
- const u = new URL(finalUrl);
114
+ const u = new URL(url);
115
115
  let thumbnail = undefined;
116
116
  if (customThumbnail) {
117
117
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamplace/components",
3
- "version": "0.7.26",
3
+ "version": "0.7.27",
4
4
  "description": "Streamplace React (Native) Components",
5
5
  "main": "dist/index.js",
6
6
  "types": "src/index.tsx",
@@ -53,5 +53,5 @@
53
53
  "start": "tsc --watch --preserveWatchOutput",
54
54
  "prepare": "tsc"
55
55
  },
56
- "gitHead": "4dcda25a5e66a2c1a9f412bee2e09c4dd528a939"
56
+ "gitHead": "c981451ba44cc3e2213e1734c31d35b1383b2132"
57
57
  }
@@ -205,6 +205,11 @@ export function useWebRTCIngest({
205
205
  (x) => x.setIngestConnectionState,
206
206
  );
207
207
  const storedKey = useStreamKey();
208
+ useEffect(() => {
209
+ if (storedKey?.error) {
210
+ console.error("error creating stream key", storedKey.error);
211
+ }
212
+ }, [storedKey?.error]);
208
213
  const [peerConnection, setPeerConnection] =
209
214
  useState<RTCPeerConnection | null>(null);
210
215
 
@@ -249,7 +254,11 @@ export function useWebRTCIngest({
249
254
  });
250
255
 
251
256
  peerConnection.addEventListener("track", (ev) => {
252
- console.log(ev);
257
+ console.log(
258
+ `got peerconnection track with ${ev.track.kind}`,
259
+ ev.track.id,
260
+ );
261
+ // console.log(ev);
253
262
  });
254
263
 
255
264
  setPeerConnection(peerConnection);
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from "react";
2
- import { View } from "react-native";
2
+ import { Text, View } from "react-native";
3
3
  import { VideoNativeProps } from "./props";
4
4
 
5
5
  let importPromise: Promise<typeof import("./video-async.native")> | null = null;
@@ -13,12 +13,27 @@ export default function VideoNative(props: VideoNativeProps) {
13
13
  typeof import("./video-async.native") | null
14
14
  >(null);
15
15
 
16
+ const [error, setError] = useState<string | null>(null);
17
+
16
18
  useEffect(() => {
17
- importPromise?.then((module) => {
18
- setVideoNativeModule(module);
19
- });
19
+ importPromise
20
+ ?.then((module) => {
21
+ setVideoNativeModule(module);
22
+ })
23
+ .catch((err) => {
24
+ setError(err.message);
25
+ });
20
26
  }, []);
21
27
 
28
+ if (error) {
29
+ console.error(error);
30
+ return (
31
+ <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
32
+ <Text>{error}</Text>
33
+ </View>
34
+ );
35
+ }
36
+
22
37
  if (!videoNativeModule) {
23
38
  return <View></View>;
24
39
  }
@@ -0,0 +1,24 @@
1
+ // awkward use of require()? you betcha. but import() with Metro causes it to try and
2
+ // resolve the package at compile-time even if not installed, so here we are.
3
+ let rnqc: any | null = null;
4
+ let expoCrypto: any | null = null;
5
+ try {
6
+ rnqc = require("react-native-quick-crypto");
7
+ } catch (err) {}
8
+ try {
9
+ expoCrypto = require("expo-crypto");
10
+ } catch (err) {}
11
+
12
+ if (!rnqc && !expoCrypto) {
13
+ throw new Error(
14
+ "Livestreaming requires one of react-native-quick-crypto or expo-crypto",
15
+ );
16
+ } else if (!rnqc && expoCrypto) {
17
+ // @atproto/crypto dependencies expect crypto.getRandomValues to be a function
18
+ if (typeof globalThis.crypto === "undefined") {
19
+ globalThis.crypto = {} as any;
20
+ }
21
+ if (typeof globalThis.crypto.getRandomValues === "undefined") {
22
+ globalThis.crypto.getRandomValues = expoCrypto.getRandomValues;
23
+ }
24
+ }
File without changes
package/src/index.tsx CHANGED
@@ -1,4 +1,6 @@
1
1
  // barrel file :)
2
+ import "./crypto-polyfill";
3
+
2
4
  export * from "./livestream-provider";
3
5
  export * from "./livestream-store";
4
6
  export * from "./player-store";
@@ -212,12 +212,9 @@ export const reduceChatIncremental = (
212
212
  let hasChanges = false;
213
213
  const removedKeys = new Set<string>();
214
214
 
215
- console.log("newMessages", newMessages);
216
-
217
215
  for (const msg of newMessages) {
218
216
  if (msg.deleted) {
219
217
  hasChanges = true;
220
- console.log("deleted", msg.uri);
221
218
  removedKeys.add(msg.uri);
222
219
  }
223
220
  }
@@ -90,7 +90,7 @@ export const useStreamKey = (): {
90
90
  setKey(newKey);
91
91
  };
92
92
 
93
- generateKey();
93
+ generateKey().catch((err) => setError(err.message));
94
94
  // eslint-disable-next-line react-hooks/exhaustive-deps
95
95
  }, [key, setStreamKey]);
96
96
 
@@ -1,4 +1,3 @@
1
- import { randomUUID } from "crypto";
2
1
  import React, { useCallback, useMemo, useState } from "react";
3
2
  import { StoreApi } from "zustand";
4
3
  import { PlayerContext } from "./context";
@@ -11,6 +10,19 @@ interface PlayerProviderProps {
11
10
  defaultId?: string;
12
11
  }
13
12
 
13
+ function randomUUID(): string {
14
+ let dt = new Date().getTime();
15
+ var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
16
+ /[xy]/g,
17
+ function (c) {
18
+ var r = (dt + Math.random() * 16) % 16 | 0;
19
+ dt = Math.floor(dt / 16);
20
+ return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
21
+ },
22
+ );
23
+ return uuid;
24
+ }
25
+
14
26
  export const PlayerProvider: React.FC<PlayerProviderProps> = ({
15
27
  children,
16
28
  initialPlayers = [],
@@ -1,7 +1,7 @@
1
1
  import React, { createContext, useContext, useMemo } from "react";
2
2
  import { StoreApi, useStore } from "zustand";
3
- import { usePlayerContext } from "../player-store";
4
3
  import { PlayerProtocol, PlayerState } from "./player-state";
4
+ import { usePlayerContext } from "./player-store";
5
5
 
6
6
  // Context for a single player
7
7
  interface SinglePlayerContextType {
@@ -154,7 +154,7 @@ export function useCreateStreamRecord() {
154
154
 
155
155
  // Use customUrl if provided, otherwise fall back to the store URL
156
156
  const finalUrl = customUrl || url;
157
- const u = new URL(finalUrl);
157
+ const u = new URL(url);
158
158
 
159
159
  let thumbnail: BlobRef | undefined = undefined;
160
160