@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.
- package/dist/components/mobile-player/use-webrtc.js +7 -1
- package/dist/components/mobile-player/video.native.js +10 -1
- package/dist/crypto-polyfill.js +0 -0
- package/dist/crypto-polyfill.native.js +24 -0
- package/dist/index.js +1 -0
- package/dist/livestream-store/chat.js +0 -2
- package/dist/livestream-store/stream-key.js +1 -1
- package/dist/player-store/player-provider.js +10 -2
- package/dist/player-store/single-player-provider.js +1 -1
- package/dist/streamplace-store/stream.js +1 -1
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +2 -2
- package/src/components/mobile-player/use-webrtc.tsx +10 -1
- package/src/components/mobile-player/video.native.tsx +19 -4
- package/src/crypto-polyfill.native.tsx +24 -0
- package/src/crypto-polyfill.tsx +0 -0
- package/src/index.tsx +2 -0
- package/src/livestream-store/chat.tsx +0 -3
- package/src/livestream-store/stream-key.tsx +1 -1
- package/src/player-store/player-provider.tsx +13 -1
- package/src/player-store/single-player-provider.tsx +1 -1
- package/src/streamplace-store/stream.tsx +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -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
|
|
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 ||
|
|
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(
|
|
114
|
+
const u = new URL(url);
|
|
115
115
|
let thumbnail = undefined;
|
|
116
116
|
if (customThumbnail) {
|
|
117
117
|
try {
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamplace/components",
|
|
3
|
-
"version": "0.7.
|
|
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": "
|
|
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(
|
|
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
|
|
18
|
-
|
|
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
|
@@ -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
|
}
|
|
@@ -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(
|
|
157
|
+
const u = new URL(url);
|
|
158
158
|
|
|
159
159
|
let thumbnail: BlobRef | undefined = undefined;
|
|
160
160
|
|