@streamplace/components 0.7.18 → 0.7.21

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.
Files changed (122) hide show
  1. package/dist/assets/emoji-data.json +19371 -0
  2. package/dist/components/chat/chat-box.js +319 -0
  3. package/dist/components/chat/chat-message.js +87 -0
  4. package/dist/components/chat/chat.js +150 -0
  5. package/dist/components/chat/emoji-suggestions.js +35 -0
  6. package/dist/components/chat/mention-suggestions.js +42 -0
  7. package/dist/components/chat/mod-view.js +112 -0
  8. package/dist/components/chat/system-message.js +19 -0
  9. package/dist/components/dashboard/chat-panel.js +38 -0
  10. package/dist/components/dashboard/header.js +80 -0
  11. package/dist/components/dashboard/index.js +14 -0
  12. package/dist/components/dashboard/information-widget.js +234 -0
  13. package/dist/components/dashboard/mod-actions.js +71 -0
  14. package/dist/components/dashboard/problems.js +74 -0
  15. package/dist/components/icons/bluesky-icon.js +9 -0
  16. package/dist/components/keep-awake.js +7 -0
  17. package/dist/components/keep-awake.native.js +16 -0
  18. package/dist/components/mobile-player/fullscreen.js +76 -0
  19. package/dist/components/mobile-player/fullscreen.native.js +141 -0
  20. package/dist/components/mobile-player/player.js +94 -0
  21. package/dist/components/mobile-player/props.js +2 -0
  22. package/dist/components/mobile-player/shared.js +54 -0
  23. package/dist/components/mobile-player/ui/autoplay-button.js +68 -0
  24. package/dist/components/mobile-player/ui/countdown.js +83 -0
  25. package/dist/components/mobile-player/ui/index.js +12 -0
  26. package/dist/components/mobile-player/ui/input.js +42 -0
  27. package/dist/components/mobile-player/ui/metrics.js +44 -0
  28. package/dist/components/mobile-player/ui/report-modal.js +90 -0
  29. package/dist/components/mobile-player/ui/streamer-context-menu.js +7 -0
  30. package/dist/components/mobile-player/ui/streamer-loading-overlay.js +104 -0
  31. package/dist/components/mobile-player/ui/viewer-context-menu.js +51 -0
  32. package/dist/components/mobile-player/ui/viewer-loading-overlay.js +49 -0
  33. package/dist/components/mobile-player/ui/viewers.js +23 -0
  34. package/dist/components/mobile-player/use-webrtc.js +243 -0
  35. package/dist/components/mobile-player/video-async.native.js +276 -0
  36. package/dist/components/mobile-player/video-retry.js +29 -0
  37. package/dist/components/mobile-player/video.js +475 -0
  38. package/dist/components/mobile-player/video.native.js +56 -0
  39. package/dist/components/mobile-player/webrtc-diagnostics.js +110 -0
  40. package/dist/components/mobile-player/webrtc-primitives.js +27 -0
  41. package/dist/components/mobile-player/webrtc-primitives.native.js +8 -0
  42. package/dist/components/share/sharesheet.js +91 -0
  43. package/dist/components/ui/button.js +223 -0
  44. package/dist/components/ui/dialog.js +206 -0
  45. package/dist/components/ui/dropdown.js +172 -0
  46. package/dist/components/ui/icons.js +25 -0
  47. package/dist/components/ui/index.js +34 -0
  48. package/dist/components/ui/info-box.js +31 -0
  49. package/dist/components/ui/info-row.js +23 -0
  50. package/dist/components/ui/input.js +205 -0
  51. package/dist/components/ui/loader.js +10 -0
  52. package/dist/components/ui/primitives/button.js +125 -0
  53. package/dist/components/ui/primitives/input.js +206 -0
  54. package/dist/components/ui/primitives/modal.js +206 -0
  55. package/dist/components/ui/primitives/text.js +292 -0
  56. package/dist/components/ui/resizeable.js +121 -0
  57. package/dist/components/ui/slider.js +5 -0
  58. package/dist/components/ui/text.js +177 -0
  59. package/dist/components/ui/textarea.js +19 -0
  60. package/dist/components/ui/toast.js +175 -0
  61. package/dist/components/ui/view.js +252 -0
  62. package/dist/hooks/index.js +14 -0
  63. package/dist/hooks/useAvatars.js +35 -0
  64. package/dist/hooks/useCameraToggle.js +12 -0
  65. package/dist/hooks/useKeyboard.js +36 -0
  66. package/dist/hooks/useKeyboardSlide.js +14 -0
  67. package/dist/hooks/useLivestreamInfo.js +69 -0
  68. package/dist/hooks/useOuterAndInnerDimensions.js +30 -0
  69. package/dist/hooks/usePlayerDimensions.js +22 -0
  70. package/dist/hooks/usePointerDevice.js +71 -0
  71. package/dist/hooks/useSegmentDimensions.js +17 -0
  72. package/dist/hooks/useSegmentTiming.js +65 -0
  73. package/dist/index.js +34 -0
  74. package/dist/lib/browser.js +35 -0
  75. package/dist/lib/facet.js +92 -0
  76. package/dist/lib/system-messages.js +101 -0
  77. package/dist/lib/theme/atoms.js +646 -0
  78. package/dist/lib/theme/atoms.types.js +6 -0
  79. package/dist/lib/theme/index.js +35 -0
  80. package/dist/lib/theme/theme.js +256 -0
  81. package/dist/lib/theme/tokens.js +659 -0
  82. package/dist/lib/utils.js +105 -0
  83. package/dist/livestream-provider/index.js +30 -0
  84. package/dist/livestream-provider/websocket.js +45 -0
  85. package/dist/livestream-store/chat.js +308 -0
  86. package/dist/livestream-store/context.js +5 -0
  87. package/dist/livestream-store/index.js +7 -0
  88. package/dist/livestream-store/livestream-state.js +2 -0
  89. package/dist/livestream-store/livestream-store.js +58 -0
  90. package/dist/livestream-store/problems.js +76 -0
  91. package/dist/livestream-store/stream-key.js +88 -0
  92. package/dist/livestream-store/websocket-consumer.js +94 -0
  93. package/dist/player-store/context.js +5 -0
  94. package/dist/player-store/index.js +9 -0
  95. package/dist/player-store/player-provider.js +58 -0
  96. package/dist/player-store/player-state.js +25 -0
  97. package/dist/player-store/player-store.js +201 -0
  98. package/dist/player-store/single-player-provider.js +121 -0
  99. package/dist/streamplace-provider/context.js +5 -0
  100. package/dist/streamplace-provider/index.js +20 -0
  101. package/dist/streamplace-provider/poller.js +49 -0
  102. package/dist/streamplace-provider/xrpc.js +0 -0
  103. package/dist/streamplace-store/block.js +65 -0
  104. package/dist/streamplace-store/index.js +6 -0
  105. package/dist/streamplace-store/stream.js +247 -0
  106. package/dist/streamplace-store/streamplace-store.js +47 -0
  107. package/dist/streamplace-store/user.js +52 -0
  108. package/dist/streamplace-store/xrpc.js +15 -0
  109. package/dist/ui/index.js +79 -0
  110. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  111. package/package.json +5 -4
  112. package/src/components/chat/chat-box.tsx +3 -0
  113. package/src/components/chat/mod-view.tsx +39 -5
  114. package/src/components/mobile-player/fullscreen.tsx +2 -0
  115. package/src/components/mobile-player/ui/autoplay-button.tsx +86 -0
  116. package/src/components/mobile-player/ui/index.ts +1 -0
  117. package/src/components/mobile-player/video.tsx +11 -1
  118. package/src/livestream-store/chat.tsx +22 -0
  119. package/src/player-store/player-provider.tsx +2 -1
  120. package/src/player-store/player-state.tsx +6 -0
  121. package/src/player-store/player-store.tsx +4 -0
  122. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,475 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = WebVideo;
4
+ exports.ProgressiveMP4Player = ProgressiveMP4Player;
5
+ exports.ProgressiveWebMPlayer = ProgressiveWebMPlayer;
6
+ exports.HLSPlayer = HLSPlayer;
7
+ exports.WebRTCPlayer = WebRTCPlayer;
8
+ exports.WebRTCPlayerInner = WebRTCPlayerInner;
9
+ exports.WebcamIngestPlayer = WebcamIngestPlayer;
10
+ const tslib_1 = require("tslib");
11
+ const jsx_runtime_1 = require("react/jsx-runtime");
12
+ const hls_js_1 = tslib_1.__importDefault(require("hls.js"));
13
+ const react_1 = require("react");
14
+ const __1 = require("../..");
15
+ const atoms_1 = require("../../lib/theme/atoms");
16
+ const index_1 = require("../ui/index");
17
+ const loader_1 = require("../ui/loader");
18
+ const shared_1 = require("./shared");
19
+ const use_webrtc_1 = tslib_1.__importStar(require("./use-webrtc"));
20
+ const webrtc_diagnostics_1 = require("./webrtc-diagnostics");
21
+ const webrtc_primitives_1 = require("./webrtc-primitives");
22
+ function assignVideoRef(ref, instance) {
23
+ if (!ref)
24
+ return;
25
+ if (typeof ref === "function")
26
+ ref(instance);
27
+ else
28
+ ref.current = instance;
29
+ }
30
+ function useVideoDimensions(videoRef) {
31
+ const [dimensions, setDimensions] = (0, react_1.useState)({ width: 0, height: 0 });
32
+ (0, react_1.useEffect)(() => {
33
+ if (!videoRef.current)
34
+ return;
35
+ function updateSize() {
36
+ setDimensions({
37
+ width: videoRef.current?.videoWidth || 0,
38
+ height: videoRef.current?.videoHeight || 0,
39
+ });
40
+ }
41
+ updateSize();
42
+ const observer = new window.ResizeObserver(updateSize);
43
+ observer.observe(videoRef.current);
44
+ videoRef.current.addEventListener("loadedmetadata", updateSize);
45
+ videoRef.current.addEventListener("resize", updateSize);
46
+ return () => {
47
+ observer.disconnect();
48
+ videoRef.current?.removeEventListener("loadedmetadata", updateSize);
49
+ videoRef.current?.removeEventListener("resize", updateSize);
50
+ };
51
+ }, [videoRef, videoRef.current]);
52
+ return dimensions;
53
+ }
54
+ function WebVideo(props) {
55
+ const inProto = (0, __1.usePlayerStore)((x) => x.protocol);
56
+ const isIngesting = (0, __1.usePlayerStore)((x) => x.ingestConnectionState !== null);
57
+ const selectedRendition = (0, __1.usePlayerStore)((x) => x.selectedRendition);
58
+ const src = (0, __1.usePlayerStore)((x) => x.src);
59
+ const setPlayerWidth = (0, __1.usePlayerStore)((x) => x.setPlayerWidth);
60
+ const setPlayerHeight = (0, __1.usePlayerStore)((x) => x.setPlayerHeight);
61
+ const { url, protocol } = (0, shared_1.srcToUrl)({ src: src, selectedRendition }, inProto);
62
+ const videoRef = (0, react_1.useRef)(null);
63
+ const dimensions = useVideoDimensions(videoRef);
64
+ (0, react_1.useEffect)(() => {
65
+ if (videoRef.current) {
66
+ setPlayerWidth(dimensions.width);
67
+ setPlayerHeight(dimensions.height);
68
+ }
69
+ }, [dimensions, setPlayerWidth, setPlayerHeight]);
70
+ const playerProps = {
71
+ url,
72
+ videoRef,
73
+ objectFit: props?.objectFit,
74
+ pictureInPictureEnabled: props?.pictureInPictureEnabled,
75
+ };
76
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: isIngesting ? ((0, jsx_runtime_1.jsx)(WebcamIngestPlayer, { ...playerProps })) : protocol === __1.PlayerProtocol.PROGRESSIVE_MP4 ? ((0, jsx_runtime_1.jsx)(ProgressiveMP4Player, { ...playerProps })) : protocol === __1.PlayerProtocol.PROGRESSIVE_WEBM ? ((0, jsx_runtime_1.jsx)(ProgressiveWebMPlayer, { ...playerProps })) : protocol === __1.PlayerProtocol.HLS ? ((0, jsx_runtime_1.jsx)(HLSPlayer, { ...playerProps })) : protocol === __1.PlayerProtocol.WEBRTC ? ((0, jsx_runtime_1.jsx)(WebRTCPlayer, { ...playerProps })) : ((() => {
77
+ throw new Error(`unknown playback protocol ${inProto}`);
78
+ })()) }));
79
+ }
80
+ const updateEvents = {
81
+ playing: true,
82
+ waiting: true,
83
+ stalled: true,
84
+ pause: true,
85
+ suspend: true,
86
+ mute: true,
87
+ };
88
+ const VideoElement = (0, react_1.forwardRef)((props, ref) => {
89
+ const x = (0, __1.usePlayerStore)((x) => x);
90
+ const url = (0, __1.useStreamplaceStore)((x) => x.url);
91
+ const playerEvent = (0, __1.usePlayerStore)((x) => x.playerEvent);
92
+ const setMuted = (0, __1.usePlayerStore)((x) => x.setMuted);
93
+ const setMuteWasForced = (0, __1.usePlayerStore)((x) => x.setMuteWasForced);
94
+ const muted = (0, __1.usePlayerStore)((x) => x.muted);
95
+ const ingest = (0, __1.usePlayerStore)((x) => x.ingestConnectionState !== null);
96
+ const volume = (0, __1.usePlayerStore)((x) => x.volume);
97
+ const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
98
+ const setUserInteraction = (0, __1.usePlayerStore)((x) => x.setUserInteraction);
99
+ const setVideoRef = (0, __1.usePlayerStore)((x) => x.setVideoRef);
100
+ const event = (evType) => (e) => {
101
+ console.log(evType);
102
+ const now = new Date();
103
+ if (updateEvents[evType]) {
104
+ x.setStatus(evType);
105
+ }
106
+ console.log("Sending", evType, "status to", url);
107
+ playerEvent(url, now.toISOString(), evType, {});
108
+ };
109
+ const [firstAttempt, setFirstAttempt] = (0, react_1.useState)(true);
110
+ const setAutoplayFailed = (0, __1.usePlayerStore)((x) => x.setAutoplayFailed);
111
+ const localVideoRef = props.videoRef ?? (0, react_1.useRef)(null);
112
+ // setPipAction comes from Zustand store
113
+ (0, react_1.useEffect)(() => {
114
+ if (typeof x.setPipAction === "function") {
115
+ const fn = () => {
116
+ if (localVideoRef.current) {
117
+ try {
118
+ localVideoRef.current.requestPictureInPicture?.();
119
+ }
120
+ catch (err) {
121
+ console.error("Error requesting Picture-in-Picture:", err);
122
+ }
123
+ }
124
+ else {
125
+ console.log("No video ref available for PiP");
126
+ }
127
+ };
128
+ x.setPipAction(fn);
129
+ }
130
+ // Cleanup on unmount
131
+ return () => {
132
+ if (typeof x.setPipAction === "function") {
133
+ x.setPipAction(undefined);
134
+ }
135
+ };
136
+ }, []);
137
+ const canPlayThrough = (e) => {
138
+ console.log("canPlayThrough called", {
139
+ firstAttempt,
140
+ videoRef: !!localVideoRef.current,
141
+ });
142
+ setStatus(__1.PlayerStatus.PLAYING);
143
+ event("canplaythrough")(e);
144
+ if (firstAttempt && localVideoRef.current) {
145
+ setFirstAttempt(false);
146
+ console.log("Attempting to play video");
147
+ localVideoRef.current.play().catch((err) => {
148
+ console.log("error playing video", err.name);
149
+ if (err.name === "NotAllowedError") {
150
+ if (localVideoRef.current) {
151
+ console.log("Setting muted and retrying");
152
+ setMuted(true);
153
+ localVideoRef.current.muted = true;
154
+ localVideoRef.current
155
+ .play()
156
+ .then(() => {
157
+ console.log("Muted play succeeded");
158
+ setMuteWasForced(true);
159
+ })
160
+ .catch((err) => {
161
+ console.error("Muted play also failed", err);
162
+ setAutoplayFailed(true);
163
+ });
164
+ }
165
+ }
166
+ else {
167
+ // For other errors (not NotAllowedError), also show play button
168
+ setAutoplayFailed(true);
169
+ }
170
+ });
171
+ }
172
+ };
173
+ const handlePlaying = (e) => {
174
+ setAutoplayFailed(false);
175
+ event("playing")(e);
176
+ };
177
+ (0, react_1.useEffect)(() => {
178
+ return () => {
179
+ setStatus(__1.PlayerStatus.START);
180
+ };
181
+ }, []);
182
+ (0, react_1.useEffect)(() => {
183
+ if (localVideoRef.current) {
184
+ localVideoRef.current.volume = volume;
185
+ console.log("Setting volume to", volume);
186
+ }
187
+ }, [volume]);
188
+ (0, react_1.useEffect)(() => {
189
+ console.log(localVideoRef.current?.width, localVideoRef.current?.height);
190
+ setVideoRef(localVideoRef);
191
+ }, [setVideoRef, localVideoRef]);
192
+ const handleVideoRef = (videoElement) => {
193
+ if (typeof ref === "function") {
194
+ ref(videoElement);
195
+ }
196
+ else if (ref) {
197
+ ref.current =
198
+ videoElement;
199
+ }
200
+ localVideoRef.current = videoElement;
201
+ };
202
+ const eventLogger = (evType) => (e) => {
203
+ console.log("📺 Video event:", evType);
204
+ const now = new Date();
205
+ if (updateEvents[evType]) {
206
+ x.setStatus(evType);
207
+ }
208
+ console.log("Sending", evType, "status to", url);
209
+ playerEvent(url, now.toISOString(), evType, {});
210
+ };
211
+ return ((0, jsx_runtime_1.jsx)("video", { autoPlay: true, playsInline: true, ref: handleVideoRef, controls: false, src: ingest ? undefined : props.url, muted: muted, crossOrigin: "anonymous", onMouseMove: setUserInteraction, onClick: setUserInteraction, onAbort: event("abort"), onCanPlay: eventLogger, onCanPlayThroughCapture: eventLogger, onCanPlayThrough: canPlayThrough, onEmptied: event("emptied"), onEncrypted: event("encrypted"), onEnded: event("ended"), onError: event("error"), onLoadedData: event("loadeddata"), onLoadedMetadata: event("loadedmetadata"), onLoadStart: event("loadstart"), onPause: event("pause"), onPlay: event("play"), onPlaying: handlePlaying, onRateChange: event("ratechange"), onSeeked: event("seeked"), onSeeking: event("seeking"), onStalled: event("stalled"), onSuspend: event("suspend"), onVolumeChange: event("volumechange"), onWaiting: event("waiting"), style: {
212
+ objectFit: props.objectFit || "contain",
213
+ backgroundColor: "transparent",
214
+ width: "100%",
215
+ height: "100%",
216
+ maxWidth: "100%",
217
+ maxHeight: "100%",
218
+ transform: ingest ? "scaleX(-1)" : undefined,
219
+ }, disablePictureInPicture: props.pictureInPictureEnabled === false }));
220
+ });
221
+ function ProgressiveMP4Player(props) {
222
+ return (0, jsx_runtime_1.jsx)(VideoElement, { ...props });
223
+ }
224
+ function ProgressiveWebMPlayer(props) {
225
+ return (0, jsx_runtime_1.jsx)(VideoElement, { ...props });
226
+ }
227
+ function HLSPlayer(props) {
228
+ const localRef = (0, react_1.useRef)(null);
229
+ (0, react_1.useEffect)(() => {
230
+ if (!localRef.current) {
231
+ return;
232
+ }
233
+ if (hls_js_1.default.isSupported()) {
234
+ var hls = new hls_js_1.default({ maxAudioFramesDrift: 20 });
235
+ hls.loadSource(props.url);
236
+ try {
237
+ hls.attachMedia(localRef.current);
238
+ }
239
+ catch (e) {
240
+ console.error("error on attachMedia");
241
+ hls.stopLoad();
242
+ return;
243
+ }
244
+ hls.on(hls_js_1.default.Events.MANIFEST_PARSED, () => {
245
+ if (!localRef.current) {
246
+ return;
247
+ }
248
+ localRef.current.play();
249
+ });
250
+ return () => {
251
+ hls.stopLoad();
252
+ };
253
+ }
254
+ else if (localRef.current.canPlayType("application/vnd.apple.mpegurl")) {
255
+ localRef.current.src = props.url;
256
+ localRef.current.addEventListener("canplay", () => {
257
+ if (!localRef.current) {
258
+ return;
259
+ }
260
+ localRef.current.play();
261
+ });
262
+ }
263
+ }, [props.url]);
264
+ return (0, jsx_runtime_1.jsx)(VideoElement, { ...props, ref: localRef });
265
+ }
266
+ function WebRTCPlayer(props) {
267
+ const [webrtcError, setWebrtcError] = (0, react_1.useState)(null);
268
+ const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
269
+ const setProtocol = (0, __1.usePlayerStore)((x) => x.setProtocol);
270
+ const diagnostics = (0, webrtc_diagnostics_1.useWebRTCDiagnostics)();
271
+ // Check WebRTC compatibility on component mount
272
+ (0, react_1.useEffect)(() => {
273
+ try {
274
+ (0, webrtc_primitives_1.checkWebRTCSupport)();
275
+ console.log("WebRTC Player - Browser compatibility check passed");
276
+ (0, webrtc_diagnostics_1.logWebRTCDiagnostics)();
277
+ }
278
+ catch (error) {
279
+ console.error("WebRTC Player - Compatibility error:", error.message);
280
+ setWebrtcError(error.message);
281
+ setStatus(__1.PlayerStatus.START);
282
+ return;
283
+ }
284
+ }, []);
285
+ // Monitor diagnostics for errors
286
+ (0, react_1.useEffect)(() => {
287
+ if (!diagnostics.browserSupport && diagnostics.errors.length > 0) {
288
+ setWebrtcError(diagnostics.errors.join(", "));
289
+ }
290
+ }, [diagnostics]);
291
+ if (!diagnostics.done)
292
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
293
+ if (webrtcError) {
294
+ setProtocol(__1.PlayerProtocol.HLS);
295
+ return ((0, jsx_runtime_1.jsx)(index_1.View, { backgroundColor: "#111", children: (0, jsx_runtime_1.jsxs)(index_1.View, { children: [(0, jsx_runtime_1.jsx)(index_1.View, { children: (0, jsx_runtime_1.jsx)(index_1.Text, { children: "WebRTC Not Supported" }) }), (0, jsx_runtime_1.jsx)(index_1.Text, { children: webrtcError }), diagnostics.errors.length > 0 && ((0, jsx_runtime_1.jsxs)(index_1.View, { children: [(0, jsx_runtime_1.jsx)(index_1.Text, { children: "Technical Details:" }), diagnostics.errors.map((error, index) => ((0, jsx_runtime_1.jsxs)(index_1.Text, { children: ["\u2022 ", error] }, index)))] })), (0, jsx_runtime_1.jsx)(index_1.Text, { children: "\u2022 To use WebRTC, you may need to disable any blocking extensions or update your browser." }), (0, jsx_runtime_1.jsx)(index_1.Text, { style: [atoms_1.mt[2]], children: "Switching to HLS..." })] }) }));
296
+ }
297
+ return (0, jsx_runtime_1.jsx)(WebRTCPlayerInner, { url: props.url, videoRef: props.videoRef });
298
+ }
299
+ const connectionStatusMessages = {
300
+ initializing: "Starting up...",
301
+ connecting: "Connecting...",
302
+ "connection-failed": "Connecting...",
303
+ connected: "Connected",
304
+ reconnecting: "Reconnecting...",
305
+ checking: "Checking connection...",
306
+ };
307
+ function WebRTCPlayerInner({ videoRef, url, width, height, }) {
308
+ const [connectionStatus, setConnectionStatus] = (0, react_1.useState)("initializing");
309
+ const status = (0, __1.usePlayerStore)((x) => x.status);
310
+ const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
311
+ const playerEvent = (0, __1.usePlayerStore)((x) => x.playerEvent);
312
+ const spurl = (0, __1.useStreamplaceStore)((x) => x.url);
313
+ const [mediaStream, stuck] = (0, use_webrtc_1.default)(url);
314
+ (0, react_1.useEffect)(() => {
315
+ if (stuck) {
316
+ setConnectionStatus("connection-failed");
317
+ }
318
+ else if (mediaStream) {
319
+ setConnectionStatus("connected");
320
+ }
321
+ else {
322
+ setConnectionStatus("connecting");
323
+ }
324
+ }, [url, mediaStream, stuck, status]);
325
+ (0, react_1.useEffect)(() => {
326
+ if (stuck && status === __1.PlayerStatus.PLAYING) {
327
+ setStatus(__1.PlayerStatus.STALLED);
328
+ }
329
+ if (!stuck && status === __1.PlayerStatus.STALLED) {
330
+ setStatus(__1.PlayerStatus.PLAYING);
331
+ }
332
+ }, [stuck, status, mediaStream]);
333
+ (0, react_1.useEffect)(() => {
334
+ if (!mediaStream) {
335
+ return;
336
+ }
337
+ const evt = (evType) => (e) => {
338
+ console.log("webrtc event", evType);
339
+ playerEvent(spurl, new Date().toISOString(), evType, {});
340
+ };
341
+ const active = evt("active");
342
+ const inactive = evt("inactive");
343
+ const ended = evt("ended");
344
+ const mute = evt("mute");
345
+ const unmute = evt("playing");
346
+ mediaStream.addEventListener("active", active);
347
+ mediaStream.addEventListener("inactive", inactive);
348
+ mediaStream.addEventListener("ended", ended);
349
+ for (const track of mediaStream.getTracks()) {
350
+ track.addEventListener("ended", ended);
351
+ track.addEventListener("mute", mute);
352
+ track.addEventListener("unmute", unmute);
353
+ }
354
+ return () => {
355
+ for (const track of mediaStream.getTracks()) {
356
+ track.removeEventListener("ended", ended);
357
+ track.removeEventListener("mute", mute);
358
+ track.removeEventListener("unmute", unmute);
359
+ }
360
+ mediaStream.removeEventListener("active", active);
361
+ mediaStream.removeEventListener("inactive", inactive);
362
+ mediaStream.removeEventListener("ended", ended);
363
+ };
364
+ }, [mediaStream]);
365
+ (0, react_1.useEffect)(() => {
366
+ if (!videoRef || !videoRef.current) {
367
+ return;
368
+ }
369
+ videoRef.current.srcObject = mediaStream;
370
+ }, [mediaStream]);
371
+ if (!mediaStream) {
372
+ const isError = connectionStatus === "connection-failed";
373
+ return ((0, jsx_runtime_1.jsx)(index_1.View, { backgroundColor: "#111", style: {
374
+ minWidth: "100%",
375
+ minHeight: "100%",
376
+ display: "flex",
377
+ alignItems: "center",
378
+ justifyContent: "center",
379
+ }, children: (0, jsx_runtime_1.jsxs)(index_1.View, { style: {
380
+ borderRadius: atoms_1.borderRadius.md,
381
+ padding: 24,
382
+ alignItems: "center",
383
+ gap: 16,
384
+ }, children: [!isError && (0, jsx_runtime_1.jsx)(loader_1.Loader, { size: "large" }), (0, jsx_runtime_1.jsx)(index_1.Text, { size: "lg", weight: "semibold", children: connectionStatusMessages[connectionStatus] || "Connecting..." })] }) }));
385
+ }
386
+ return (0, jsx_runtime_1.jsx)(VideoElement, { url: url, ref: videoRef });
387
+ }
388
+ function WebcamIngestPlayer(props) {
389
+ const ingestStarting = (0, __1.usePlayerStore)((x) => x.ingestStarting);
390
+ const ingestMediaSource = (0, __1.usePlayerStore)((x) => x.ingestMediaSource);
391
+ const ingestAutoStart = (0, __1.usePlayerStore)((x) => x.ingestAutoStart);
392
+ const [error, setError] = (0, react_1.useState)(null);
393
+ let streamKey = null;
394
+ const [videoElement, setVideoElement] = (0, react_1.useState)(null);
395
+ const handleRef = (0, react_1.useCallback)((node) => {
396
+ if (node) {
397
+ setVideoElement(node);
398
+ }
399
+ }, []);
400
+ const url = (0, __1.useStreamplaceStore)((x) => x.url);
401
+ const [localMediaStream, setLocalMediaStream] = (0, react_1.useState)(null);
402
+ // we assign a stream key in the webrtcingest hook
403
+ const [remoteMediaStream, setRemoteMediaStream] = (0, use_webrtc_1.useWebRTCIngest)({
404
+ endpoint: `${url}/api/ingest/webrtc`,
405
+ });
406
+ (0, react_1.useEffect)(() => {
407
+ if (ingestMediaSource === __1.IngestMediaSource.DISPLAY) {
408
+ navigator.mediaDevices
409
+ .getDisplayMedia({
410
+ audio: true,
411
+ video: true,
412
+ })
413
+ .then((stream) => {
414
+ setLocalMediaStream(stream);
415
+ })
416
+ .catch((e) => {
417
+ console.error("error getting display media", e);
418
+ });
419
+ }
420
+ else {
421
+ navigator.mediaDevices
422
+ .getUserMedia({
423
+ audio: true,
424
+ video: {
425
+ width: { min: 200, ideal: 1080, max: 2160 },
426
+ height: { min: 200, ideal: 1920, max: 3840 },
427
+ },
428
+ })
429
+ .then((stream) => {
430
+ setLocalMediaStream(stream);
431
+ })
432
+ .catch((e) => {
433
+ console.error("error getting user media", e.name);
434
+ if (e.name == "NotAllowedError") {
435
+ setError(new Error("Unable to access video! Please allow it in your browser settings."));
436
+ }
437
+ });
438
+ }
439
+ }, [ingestMediaSource]);
440
+ (0, react_1.useEffect)(() => {
441
+ if (!ingestStarting && !ingestAutoStart) {
442
+ setRemoteMediaStream(null);
443
+ return;
444
+ }
445
+ if (!localMediaStream) {
446
+ return;
447
+ }
448
+ setRemoteMediaStream(localMediaStream);
449
+ }, [localMediaStream, ingestStarting, ingestAutoStart]);
450
+ (0, react_1.useEffect)(() => {
451
+ if (!videoElement) {
452
+ return;
453
+ }
454
+ if (!localMediaStream) {
455
+ return;
456
+ }
457
+ videoElement.srcObject = localMediaStream;
458
+ }, [videoElement, localMediaStream]);
459
+ if (error) {
460
+ return ((0, jsx_runtime_1.jsx)(index_1.View, { backgroundColor: "#111", style: {
461
+ minWidth: "100%",
462
+ minHeight: "100%",
463
+ display: "flex",
464
+ alignItems: "center",
465
+ justifyContent: "center",
466
+ }, children: (0, jsx_runtime_1.jsx)(index_1.View, { backgroundColor: atoms_1.colors.destructive[900], style: {
467
+ borderRadius: atoms_1.borderRadius.md,
468
+ padding: 24,
469
+ alignItems: "center",
470
+ gap: 16,
471
+ maxWidth: 400,
472
+ }, children: (0, jsx_runtime_1.jsx)(index_1.Text, { size: "xl", weight: "extrabold", color: "default", children: error.message }) }) }));
473
+ }
474
+ return (0, jsx_runtime_1.jsx)(VideoElement, { ...props, ref: handleRef });
475
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.default = VideoNative;
37
+ const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const react_1 = require("react");
39
+ const react_native_1 = require("react-native");
40
+ let importPromise = null;
41
+ function VideoNative(props) {
42
+ if (!importPromise) {
43
+ importPromise = Promise.resolve().then(() => __importStar(require("./video-async.native")));
44
+ }
45
+ const [videoNativeModule, setVideoNativeModule] = (0, react_1.useState)(null);
46
+ (0, react_1.useEffect)(() => {
47
+ importPromise?.then((module) => {
48
+ setVideoNativeModule(module);
49
+ });
50
+ }, []);
51
+ if (!videoNativeModule) {
52
+ return (0, jsx_runtime_1.jsx)(react_native_1.View, {});
53
+ }
54
+ const VideoNative = videoNativeModule.default;
55
+ return (0, jsx_runtime_1.jsx)(VideoNative, { ...props });
56
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useWebRTCDiagnostics = useWebRTCDiagnostics;
4
+ exports.logWebRTCDiagnostics = logWebRTCDiagnostics;
5
+ const react_1 = require("react");
6
+ function useWebRTCDiagnostics() {
7
+ const [diagnostics, setDiagnostics] = (0, react_1.useState)({
8
+ done: false,
9
+ browserSupport: false,
10
+ rtcPeerConnection: false,
11
+ rtcSessionDescription: false,
12
+ getUserMedia: false,
13
+ getDisplayMedia: false,
14
+ errors: [],
15
+ warnings: [],
16
+ });
17
+ (0, react_1.useEffect)(() => {
18
+ const errors = [];
19
+ const warnings = [];
20
+ // Check if we're in a browser environment
21
+ if (typeof window === "undefined") {
22
+ errors.push("Running in non-browser environment");
23
+ setDiagnostics({
24
+ done: false,
25
+ browserSupport: false,
26
+ rtcPeerConnection: false,
27
+ rtcSessionDescription: false,
28
+ getUserMedia: false,
29
+ getDisplayMedia: false,
30
+ errors,
31
+ warnings,
32
+ });
33
+ return;
34
+ }
35
+ // Check RTCPeerConnection support
36
+ const rtcPeerConnection = !!(window.RTCPeerConnection ||
37
+ window.webkitRTCPeerConnection ||
38
+ window.mozRTCPeerConnection);
39
+ if (!rtcPeerConnection) {
40
+ errors.push("RTCPeerConnection is not supported");
41
+ }
42
+ // Check RTCSessionDescription support
43
+ const rtcSessionDescription = !!(window.RTCSessionDescription ||
44
+ window.webkitRTCSessionDescription ||
45
+ window.mozRTCSessionDescription);
46
+ if (!rtcSessionDescription) {
47
+ errors.push("RTCSessionDescription is not supported");
48
+ }
49
+ // Check getUserMedia support
50
+ const getUserMedia = !!(navigator.mediaDevices?.getUserMedia ||
51
+ navigator.getUserMedia ||
52
+ navigator.webkitGetUserMedia ||
53
+ navigator.mozGetUserMedia);
54
+ if (!getUserMedia) {
55
+ warnings.push("getUserMedia is not supported - webcam features unavailable");
56
+ }
57
+ // Check getDisplayMedia support
58
+ const getDisplayMedia = !!navigator.mediaDevices?.getDisplayMedia;
59
+ if (!getDisplayMedia) {
60
+ warnings.push("getDisplayMedia is not supported - screen sharing unavailable");
61
+ }
62
+ // Check if running over HTTPS (required for some WebRTC features)
63
+ if (location.protocol !== "https:" &&
64
+ location.hostname !== "localhost" &&
65
+ location.hostname !== "127.0.0.1") {
66
+ warnings.push("WebRTC features may be limited over HTTP connections");
67
+ }
68
+ // Check browser-specific issues
69
+ const userAgent = navigator.userAgent.toLowerCase();
70
+ if (userAgent.includes("safari") && !userAgent.includes("chrome")) {
71
+ warnings.push("Safari may have limited WebRTC codec support");
72
+ }
73
+ const browserSupport = rtcPeerConnection && rtcSessionDescription;
74
+ setDiagnostics({
75
+ done: true,
76
+ browserSupport,
77
+ rtcPeerConnection,
78
+ rtcSessionDescription,
79
+ getUserMedia,
80
+ getDisplayMedia,
81
+ errors,
82
+ warnings,
83
+ });
84
+ }, []);
85
+ return diagnostics;
86
+ }
87
+ function logWebRTCDiagnostics() {
88
+ console.group("WebRTC Diagnostics");
89
+ // Log browser support
90
+ console.log("RTCPeerConnection:", !!window.RTCPeerConnection);
91
+ console.log("RTCSessionDescription:", !!window.RTCSessionDescription);
92
+ console.log("getUserMedia:", !!navigator.mediaDevices?.getUserMedia);
93
+ console.log("getDisplayMedia:", !!navigator.mediaDevices?.getDisplayMedia);
94
+ // Log browser info
95
+ console.log("User Agent:", navigator.userAgent);
96
+ console.log("Protocol:", location.protocol);
97
+ console.log("Host:", location.hostname);
98
+ // Test basic WebRTC functionality
99
+ if (window.RTCPeerConnection) {
100
+ try {
101
+ const pc = new RTCPeerConnection();
102
+ console.log("RTCPeerConnection creation: ✓ Success");
103
+ pc.close();
104
+ }
105
+ catch (error) {
106
+ console.error("RTCPeerConnection creation: ✗ Failed", error);
107
+ }
108
+ }
109
+ console.groupEnd();
110
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkWebRTCSupport = exports.mediaDevices = exports.WebRTCMediaStream = exports.RTCSessionDescription = exports.RTCPeerConnection = void 0;
4
+ // Browser compatibility checks for WebRTC
5
+ const checkWebRTCSupport = () => {
6
+ if (typeof window === "undefined") {
7
+ throw new Error("WebRTC is not available in non-browser environments");
8
+ }
9
+ if (!window.RTCPeerConnection) {
10
+ throw new Error("RTCPeerConnection is not supported in this browser. Please use a modern browser that supports WebRTC.");
11
+ }
12
+ if (!window.RTCSessionDescription) {
13
+ throw new Error("RTCSessionDescription is not supported in this browser. Please use a modern browser that supports WebRTC.");
14
+ }
15
+ };
16
+ exports.checkWebRTCSupport = checkWebRTCSupport;
17
+ // Check support immediately
18
+ try {
19
+ checkWebRTCSupport();
20
+ }
21
+ catch (error) {
22
+ console.error("WebRTC Compatibility Error:", error.message);
23
+ }
24
+ exports.RTCPeerConnection = window.RTCPeerConnection;
25
+ exports.RTCSessionDescription = window.RTCSessionDescription;
26
+ exports.WebRTCMediaStream = window.MediaStream;
27
+ exports.mediaDevices = navigator.mediaDevices;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mediaDevices = exports.WebRTCMediaStream = exports.RTCSessionDescription = exports.RTCPeerConnection = void 0;
4
+ var react_native_webrtc_1 = require("react-native-webrtc");
5
+ Object.defineProperty(exports, "RTCPeerConnection", { enumerable: true, get: function () { return react_native_webrtc_1.RTCPeerConnection; } });
6
+ Object.defineProperty(exports, "RTCSessionDescription", { enumerable: true, get: function () { return react_native_webrtc_1.RTCSessionDescription; } });
7
+ Object.defineProperty(exports, "WebRTCMediaStream", { enumerable: true, get: function () { return react_native_webrtc_1.MediaStream; } });
8
+ Object.defineProperty(exports, "mediaDevices", { enumerable: true, get: function () { return react_native_webrtc_1.mediaDevices; } });