@streamplace/components 0.7.14 → 0.7.17

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 (123) hide show
  1. package/package.json +13 -15
  2. package/src/components/mobile-player/fullscreen.native.tsx +14 -3
  3. package/src/components/mobile-player/fullscreen.tsx +10 -2
  4. package/src/components/mobile-player/player.tsx +7 -1
  5. package/src/components/mobile-player/props.tsx +7 -0
  6. package/src/components/mobile-player/video-async.native.tsx +436 -0
  7. package/src/components/mobile-player/video.native.tsx +16 -406
  8. package/src/components/mobile-player/video.tsx +14 -3
  9. package/src/hooks/useLivestreamInfo.ts +6 -2
  10. package/src/lib/browser.ts +27 -0
  11. package/src/livestream-store/stream-key.tsx +1 -28
  12. package/src/streamplace-store/stream.tsx +52 -13
  13. package/dist/assets/emoji-data.json +0 -19371
  14. package/dist/components/chat/chat-box.js +0 -314
  15. package/dist/components/chat/chat-message.js +0 -87
  16. package/dist/components/chat/chat.js +0 -149
  17. package/dist/components/chat/emoji-suggestions.js +0 -35
  18. package/dist/components/chat/mention-suggestions.js +0 -42
  19. package/dist/components/chat/mod-view.js +0 -94
  20. package/dist/components/chat/system-message.js +0 -19
  21. package/dist/components/dashboard/chat-panel.js +0 -38
  22. package/dist/components/dashboard/header.js +0 -80
  23. package/dist/components/dashboard/index.js +0 -14
  24. package/dist/components/dashboard/information-widget.js +0 -234
  25. package/dist/components/dashboard/mod-actions.js +0 -71
  26. package/dist/components/dashboard/problems.js +0 -74
  27. package/dist/components/icons/bluesky-icon.js +0 -9
  28. package/dist/components/keep-awake.js +0 -7
  29. package/dist/components/keep-awake.native.js +0 -16
  30. package/dist/components/mobile-player/fullscreen.js +0 -74
  31. package/dist/components/mobile-player/fullscreen.native.js +0 -141
  32. package/dist/components/mobile-player/player.js +0 -94
  33. package/dist/components/mobile-player/props.js +0 -2
  34. package/dist/components/mobile-player/shared.js +0 -54
  35. package/dist/components/mobile-player/ui/countdown.js +0 -83
  36. package/dist/components/mobile-player/ui/index.js +0 -11
  37. package/dist/components/mobile-player/ui/input.js +0 -42
  38. package/dist/components/mobile-player/ui/metrics.js +0 -44
  39. package/dist/components/mobile-player/ui/report-modal.js +0 -90
  40. package/dist/components/mobile-player/ui/streamer-context-menu.js +0 -7
  41. package/dist/components/mobile-player/ui/streamer-loading-overlay.js +0 -104
  42. package/dist/components/mobile-player/ui/viewer-context-menu.js +0 -51
  43. package/dist/components/mobile-player/ui/viewer-loading-overlay.js +0 -49
  44. package/dist/components/mobile-player/ui/viewers.js +0 -23
  45. package/dist/components/mobile-player/use-webrtc.js +0 -243
  46. package/dist/components/mobile-player/video-retry.js +0 -29
  47. package/dist/components/mobile-player/video.js +0 -460
  48. package/dist/components/mobile-player/video.native.js +0 -276
  49. package/dist/components/mobile-player/webrtc-diagnostics.js +0 -110
  50. package/dist/components/mobile-player/webrtc-primitives.js +0 -27
  51. package/dist/components/mobile-player/webrtc-primitives.native.js +0 -8
  52. package/dist/components/share/sharesheet.js +0 -91
  53. package/dist/components/ui/button.js +0 -223
  54. package/dist/components/ui/dialog.js +0 -206
  55. package/dist/components/ui/dropdown.js +0 -172
  56. package/dist/components/ui/icons.js +0 -25
  57. package/dist/components/ui/index.js +0 -34
  58. package/dist/components/ui/info-box.js +0 -31
  59. package/dist/components/ui/info-row.js +0 -23
  60. package/dist/components/ui/input.js +0 -205
  61. package/dist/components/ui/loader.js +0 -10
  62. package/dist/components/ui/primitives/button.js +0 -125
  63. package/dist/components/ui/primitives/input.js +0 -206
  64. package/dist/components/ui/primitives/modal.js +0 -206
  65. package/dist/components/ui/primitives/text.js +0 -292
  66. package/dist/components/ui/resizeable.js +0 -121
  67. package/dist/components/ui/slider.js +0 -5
  68. package/dist/components/ui/text.js +0 -177
  69. package/dist/components/ui/textarea.js +0 -19
  70. package/dist/components/ui/toast.js +0 -175
  71. package/dist/components/ui/view.js +0 -252
  72. package/dist/hooks/index.js +0 -14
  73. package/dist/hooks/useAvatars.js +0 -35
  74. package/dist/hooks/useCameraToggle.js +0 -12
  75. package/dist/hooks/useKeyboard.js +0 -36
  76. package/dist/hooks/useKeyboardSlide.js +0 -14
  77. package/dist/hooks/useLivestreamInfo.js +0 -65
  78. package/dist/hooks/useOuterAndInnerDimensions.js +0 -30
  79. package/dist/hooks/usePlayerDimensions.js +0 -22
  80. package/dist/hooks/usePointerDevice.js +0 -71
  81. package/dist/hooks/useSegmentDimensions.js +0 -17
  82. package/dist/hooks/useSegmentTiming.js +0 -65
  83. package/dist/index.js +0 -34
  84. package/dist/lib/facet.js +0 -92
  85. package/dist/lib/system-messages.js +0 -101
  86. package/dist/lib/theme/atoms.js +0 -646
  87. package/dist/lib/theme/atoms.types.js +0 -6
  88. package/dist/lib/theme/index.js +0 -35
  89. package/dist/lib/theme/theme.js +0 -256
  90. package/dist/lib/theme/tokens.js +0 -659
  91. package/dist/lib/utils.js +0 -105
  92. package/dist/livestream-provider/index.js +0 -30
  93. package/dist/livestream-provider/websocket.js +0 -45
  94. package/dist/livestream-store/chat.js +0 -286
  95. package/dist/livestream-store/context.js +0 -5
  96. package/dist/livestream-store/index.js +0 -7
  97. package/dist/livestream-store/livestream-state.js +0 -2
  98. package/dist/livestream-store/livestream-store.js +0 -58
  99. package/dist/livestream-store/problems.js +0 -76
  100. package/dist/livestream-store/stream-key.js +0 -119
  101. package/dist/livestream-store/websocket-consumer.js +0 -94
  102. package/dist/player-store/context.js +0 -5
  103. package/dist/player-store/index.js +0 -9
  104. package/dist/player-store/player-provider.js +0 -57
  105. package/dist/player-store/player-state.js +0 -25
  106. package/dist/player-store/player-store.js +0 -199
  107. package/dist/player-store/single-player-provider.js +0 -121
  108. package/dist/streamplace-provider/context.js +0 -5
  109. package/dist/streamplace-provider/index.js +0 -20
  110. package/dist/streamplace-provider/poller.js +0 -49
  111. package/dist/streamplace-provider/xrpc.js +0 -0
  112. package/dist/streamplace-store/block.js +0 -65
  113. package/dist/streamplace-store/index.js +0 -6
  114. package/dist/streamplace-store/stream.js +0 -218
  115. package/dist/streamplace-store/streamplace-store.js +0 -47
  116. package/dist/streamplace-store/user.js +0 -52
  117. package/dist/streamplace-store/xrpc.js +0 -15
  118. package/dist/ui/index.js +0 -79
  119. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  120. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/56540125 +0 -0
  121. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/67b1eb60 +0 -0
  122. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/7c275f90 +0 -0
  123. package/tsconfig.tsbuildinfo +0 -1
@@ -1,276 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = VideoNative;
4
- exports.NativeVideo = NativeVideo;
5
- exports.NativeWHEP = NativeWHEP;
6
- exports.NativeIngestPlayer = NativeIngestPlayer;
7
- const tslib_1 = require("tslib");
8
- const jsx_runtime_1 = require("react/jsx-runtime");
9
- const expo_video_1 = require("expo-video");
10
- const lucide_react_native_1 = require("lucide-react-native");
11
- const react_1 = require("react");
12
- const react_native_1 = require("react-native");
13
- const react_native_webrtc_1 = require("react-native-webrtc");
14
- const __1 = require("../..");
15
- const atoms_1 = require("../../lib/theme/atoms");
16
- const shared_1 = require("./shared");
17
- const use_webrtc_1 = tslib_1.__importStar(require("./use-webrtc"));
18
- const webrtc_primitives_native_1 = require("./webrtc-primitives.native");
19
- // Add NativeIngestPlayer to the switch below!
20
- function VideoNative() {
21
- const protocol = (0, __1.usePlayerStore)((x) => x.protocol);
22
- const ingest = (0, __1.usePlayerStore)((x) => x.ingestConnectionState) != null;
23
- return ((0, jsx_runtime_1.jsx)(__1.View, { children: ingest ? ((0, jsx_runtime_1.jsx)(NativeIngestPlayer, {})) : protocol === __1.PlayerProtocol.WEBRTC ? ((0, jsx_runtime_1.jsx)(NativeWHEP, {})) : ((0, jsx_runtime_1.jsx)(NativeVideo, {})) }));
24
- }
25
- function NativeVideo() {
26
- const videoRef = (0, react_1.useRef)(null);
27
- const protocol = (0, __1.usePlayerStore)((x) => x.protocol);
28
- const selectedRendition = (0, __1.usePlayerStore)((x) => x.selectedRendition);
29
- const src = (0, __1.usePlayerStore)((x) => x.src);
30
- const { url } = (0, shared_1.srcToUrl)({ src: src, selectedRendition }, protocol);
31
- const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
32
- const muted = (0, __1.usePlayerStore)((x) => x.muted);
33
- const volume = (0, __1.usePlayerStore)((x) => x.volume);
34
- const setFullscreen = (0, __1.usePlayerStore)((x) => x.setFullscreen);
35
- const fullscreen = (0, __1.usePlayerStore)((x) => x.fullscreen);
36
- const playerEvent = (0, __1.usePlayerStore)((x) => x.playerEvent);
37
- const spurl = (0, __1.useStreamplaceStore)((x) => x.url);
38
- const setPlayerWidth = (0, __1.usePlayerStore)((x) => x.setPlayerWidth);
39
- const setPlayerHeight = (0, __1.usePlayerStore)((x) => x.setPlayerHeight);
40
- // State for live dimensions
41
- const [dimensions, setDimensions] = (0, react_1.useState)({ width: 0, height: 0 });
42
- const handleLayout = (0, react_1.useCallback)((event) => {
43
- const { width, height } = event.nativeEvent.layout;
44
- setDimensions({ width, height });
45
- setPlayerWidth(width);
46
- setPlayerHeight(height);
47
- }, []);
48
- (0, react_1.useEffect)(() => {
49
- return () => {
50
- setStatus(__1.PlayerStatus.START);
51
- };
52
- }, [setStatus]);
53
- const player = (0, expo_video_1.useVideoPlayer)(url, (player) => {
54
- player.addListener("playingChange", (newIsPlaying) => {
55
- console.log("playingChange", newIsPlaying);
56
- if (newIsPlaying) {
57
- setStatus(__1.PlayerStatus.PLAYING);
58
- }
59
- else {
60
- setStatus(__1.PlayerStatus.WAITING);
61
- }
62
- });
63
- player.loop = true;
64
- player.muted = muted;
65
- player.play();
66
- });
67
- (0, react_1.useEffect)(() => {
68
- player.muted = muted;
69
- }, [muted, player]);
70
- (0, react_1.useEffect)(() => {
71
- player.volume = volume;
72
- }, [volume, player]);
73
- (0, react_1.useEffect)(() => {
74
- const subs = [
75
- "playToEnd",
76
- "playbackRateChange",
77
- "playingChange",
78
- "sourceChange",
79
- "statusChange",
80
- "volumeChange",
81
- ].map((evType) => {
82
- return player.addListener(evType, (...args) => {
83
- const now = new Date();
84
- console.log("video native event", evType);
85
- playerEvent(spurl, now.toISOString(), evType, { args: args });
86
- });
87
- });
88
- subs.push(player.addListener("playingChange", (newIsPlaying) => {
89
- console.log("playingChange", newIsPlaying);
90
- if (newIsPlaying) {
91
- setStatus(__1.PlayerStatus.PLAYING);
92
- }
93
- else {
94
- setStatus(__1.PlayerStatus.WAITING);
95
- }
96
- }));
97
- return () => {
98
- for (const sub of subs) {
99
- sub.remove();
100
- }
101
- };
102
- }, [player, playerEvent, setStatus, spurl]);
103
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(expo_video_1.VideoView, { ref: videoRef, player: player, allowsFullscreen: true, nativeControls: fullscreen, onFullscreenEnter: () => {
104
- setFullscreen(true);
105
- }, onFullscreenExit: () => {
106
- setFullscreen(false);
107
- }, allowsPictureInPicture: true, onLayout: handleLayout }) }));
108
- }
109
- function NativeWHEP() {
110
- const selectedRendition = (0, __1.usePlayerStore)((x) => x.selectedRendition);
111
- const src = (0, __1.usePlayerStore)((x) => x.src);
112
- const { url } = (0, shared_1.srcToUrl)({ src: src, selectedRendition }, __1.PlayerProtocol.WEBRTC);
113
- const [stream, stuck] = (0, use_webrtc_1.default)(url);
114
- const status = (0, __1.usePlayerStore)((x) => x.status);
115
- const setPlayerWidth = (0, __1.usePlayerStore)((x) => x.setPlayerWidth);
116
- const setPlayerHeight = (0, __1.usePlayerStore)((x) => x.setPlayerHeight);
117
- // PiP support: wire up videoRef (no direct ref for RTCView)
118
- const setVideoRef = (0, __1.usePlayerStore)((x) => x.setVideoRef);
119
- // State for live dimensions
120
- const [dimensions, setDimensions] = (0, react_1.useState)({ width: 0, height: 0 });
121
- const handleLayout = (0, react_1.useCallback)((event) => {
122
- const { width, height } = event.nativeEvent.layout;
123
- setDimensions({ width, height });
124
- setPlayerWidth(width);
125
- setPlayerHeight(height);
126
- }, []);
127
- const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
128
- const muted = (0, __1.usePlayerStore)((x) => x.muted);
129
- const volume = (0, __1.usePlayerStore)((x) => x.volume);
130
- (0, react_1.useEffect)(() => {
131
- if (stuck && status === __1.PlayerStatus.PLAYING) {
132
- console.log("setting status to stalled", status);
133
- setStatus(__1.PlayerStatus.STALLED);
134
- }
135
- if (!stuck && status === __1.PlayerStatus.STALLED) {
136
- console.log("setting status to playing", status);
137
- setStatus(__1.PlayerStatus.PLAYING);
138
- }
139
- }, [stuck, status]);
140
- const mediaStream = stream;
141
- // useEffect(() => {
142
- // if (!mediaStream) {
143
- // setStatus(PlayerStatus.WAITING);
144
- // return;
145
- // }
146
- // setStatus(PlayerStatus.PLAYING);
147
- // }, [mediaStream, setStatus]);
148
- (0, react_1.useEffect)(() => {
149
- if (!mediaStream) {
150
- return;
151
- }
152
- mediaStream.getTracks().forEach((track) => {
153
- if (track.kind === "audio") {
154
- track._setVolume(muted ? 0 : volume);
155
- }
156
- });
157
- }, [mediaStream, muted, volume]);
158
- // Keep the playerStore videoRef in sync for PiP (if possible)
159
- (0, react_1.useEffect)(() => {
160
- if (typeof setVideoRef === "function") {
161
- setVideoRef(null); // No direct ref for RTCView, but keep API consistent
162
- }
163
- }, [setVideoRef]);
164
- if (!mediaStream) {
165
- return (0, jsx_runtime_1.jsx)(__1.View, {});
166
- }
167
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(react_native_webrtc_1.RTCView, { mirror: false, objectFit: "contain", streamURL: mediaStream.toURL(), onLayout: handleLayout, pictureInPictureEnabled: true, autoStartPictureInPicture: true, pictureInPicturePreferredSize: {
168
- width: 160,
169
- height: 90,
170
- }, style: {
171
- minWidth: "100%",
172
- minHeight: "100%",
173
- flex: 1,
174
- } }) }));
175
- }
176
- function NativeIngestPlayer() {
177
- const ingestStarting = (0, __1.usePlayerStore)((x) => x.ingestStarting);
178
- const ingestMediaSource = (0, __1.usePlayerStore)((x) => x.ingestMediaSource);
179
- const ingestAutoStart = (0, __1.usePlayerStore)((x) => x.ingestAutoStart);
180
- const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
181
- const setVideoRef = (0, __1.usePlayerStore)((x) => x.setVideoRef);
182
- const [error, setError] = (0, react_1.useState)(null);
183
- const ingestCamera = (0, __1.usePlayerStore)((x) => x.ingestCamera);
184
- (0, react_1.useEffect)(() => {
185
- setStatus(__1.PlayerStatus.PLAYING);
186
- }, [setStatus]);
187
- (0, react_1.useEffect)(() => {
188
- if (typeof setVideoRef === "function") {
189
- setVideoRef(null);
190
- }
191
- }, [setVideoRef]);
192
- const url = (0, __1.useStreamplaceStore)((x) => x.url);
193
- const [lms, setLocalMediaStream] = (0, react_1.useState)(null);
194
- const [, setRemoteMediaStream] = (0, use_webrtc_1.useWebRTCIngest)({
195
- endpoint: `${url}/api/ingest/webrtc`,
196
- });
197
- // Use lms directly as localMediaStream
198
- const localMediaStream = lms;
199
- (0, react_1.useEffect)(() => {
200
- if (ingestMediaSource === __1.IngestMediaSource.DISPLAY) {
201
- webrtc_primitives_native_1.mediaDevices
202
- .getDisplayMedia()
203
- .then((stream) => {
204
- console.log("display media", stream);
205
- setLocalMediaStream(stream);
206
- })
207
- .catch((e) => {
208
- console.log("error getting display media", e);
209
- console.error("error getting display media", e);
210
- });
211
- }
212
- else {
213
- webrtc_primitives_native_1.mediaDevices
214
- .getUserMedia({
215
- audio: {
216
- // deviceId: "audio-1",
217
- // echoCancellation: true,
218
- // autoGainControl: true,
219
- // noiseSuppression: true,
220
- // latency: false,
221
- // channelCount: false,
222
- },
223
- video: {
224
- facingMode: ingestCamera,
225
- width: { min: 200, ideal: 1080, max: 2160 },
226
- height: { min: 200, ideal: 1920, max: 3840 },
227
- },
228
- })
229
- .then((stream) => {
230
- setLocalMediaStream(stream);
231
- let errs = [];
232
- if (stream.getAudioTracks().length === 0) {
233
- console.warn("No audio tracks found in user media stream");
234
- errs.push("microphone");
235
- }
236
- if (stream.getVideoTracks().length === 0) {
237
- console.warn("No video tracks found in user media stream");
238
- errs.push("camera");
239
- }
240
- if (errs.length > 0) {
241
- setError(new Error(`We could not access your ${errs.join(" and ")}. To stream, you need to give us permission to access these.`));
242
- }
243
- else {
244
- setError(null);
245
- }
246
- })
247
- .catch((e) => {
248
- console.error("error getting user media", e);
249
- setError(new Error("We could not access your camera or microphone. To stream, you need to give us permission to access these."));
250
- });
251
- }
252
- }, [ingestMediaSource, ingestCamera]);
253
- (0, react_1.useEffect)(() => {
254
- if (!ingestStarting && !ingestAutoStart) {
255
- setRemoteMediaStream(null);
256
- return;
257
- }
258
- if (!localMediaStream) {
259
- return;
260
- }
261
- console.log("setting remote media stream", localMediaStream);
262
- // @ts-expect-error: WebRTCMediaStream may not have all MediaStream properties, but is compatible for our use
263
- setRemoteMediaStream(localMediaStream);
264
- }, [localMediaStream, ingestStarting, ingestAutoStart, setRemoteMediaStream]);
265
- if (!localMediaStream) {
266
- return null;
267
- }
268
- if (error) {
269
- return ((0, jsx_runtime_1.jsxs)(__1.View, { backgroundColor: atoms_1.colors.destructive[900], style: [atoms_1.p[4], atoms_1.m[4], atoms_1.gap.all[2], { borderRadius: atoms_1.borderRadius.md }], children: [(0, jsx_runtime_1.jsx)(__1.View, { children: (0, jsx_runtime_1.jsx)(__1.Text, { style: [atoms_1.fontWeight.semibold], size: "2xl", children: "Error encountered!" }) }), (0, jsx_runtime_1.jsx)(__1.Text, { children: error.message }), error.message.includes("To stream, you need to give us permission to access these.") && ((0, jsx_runtime_1.jsx)(__1.Button, { onPress: react_native_1.Linking.openSettings, style: [atoms_1.h[10]], variant: "secondary", children: (0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.layout.flex.row, atoms_1.gap.all[1]], children: [(0, jsx_runtime_1.jsx)(__1.Text, { children: "Open Settings" }), " ", (0, jsx_runtime_1.jsx)(lucide_react_native_1.ArrowRight, { color: "white", size: "18" })] }) }))] }));
270
- }
271
- return ((0, jsx_runtime_1.jsx)(react_native_webrtc_1.RTCView, { mirror: ingestCamera !== "environment", objectFit: "contain", streamURL: localMediaStream.toURL(), zOrder: 0, style: {
272
- minWidth: "100%",
273
- minHeight: "100%",
274
- flex: 1,
275
- } }));
276
- }
@@ -1,110 +0,0 @@
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
- }
@@ -1,27 +0,0 @@
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;
@@ -1,8 +0,0 @@
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; } });
@@ -1,91 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ShareSheet = ShareSheet;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const lucide_react_native_1 = require("lucide-react-native");
6
- const react_1 = require("react");
7
- const react_native_1 = require("react-native");
8
- const theme_1 = require("../../lib/theme");
9
- const livestream_store_1 = require("../../livestream-store");
10
- const streamplace_store_1 = require("../../streamplace-store");
11
- const bluesky_icon_1 = require("../icons/bluesky-icon");
12
- const ui_1 = require("../ui");
13
- function ShareSheet({ onShare } = {}) {
14
- const profile = (0, livestream_store_1.useLivestreamStore)((x) => x.profile);
15
- const [isCopying, setIsCopying] = (0, react_1.useState)(false);
16
- const url = (0, streamplace_store_1.useUrl)();
17
- // Get the current stream URL
18
- const getStreamUrl = (0, react_1.useCallback)(() => {
19
- return url + (profile ? `/@${profile.handle}` : "");
20
- }, [profile]);
21
- // Get the embed URL
22
- const getEmbedUrl = (0, react_1.useCallback)(() => {
23
- return url + (profile ? `/embed/${profile.handle}` : "");
24
- }, [profile]);
25
- // Get embed code
26
- const getEmbedCode = (0, react_1.useCallback)(() => {
27
- const embedUrl = getEmbedUrl();
28
- return `<iframe src="${embedUrl}" width="640" height="360" frameborder="0" allowfullscreen></iframe>`;
29
- }, [getEmbedUrl]);
30
- // Copy to clipboard handler
31
- const copyToClipboard = (0, react_1.useCallback)(async (text, label) => {
32
- setIsCopying(true);
33
- try {
34
- if (react_native_1.Platform.OS === "web") {
35
- await navigator.clipboard.writeText(text);
36
- }
37
- else {
38
- react_native_1.Clipboard.setString(text);
39
- }
40
- onShare?.(`copy_${label.toLowerCase().replace(/\s+/g, "_")}`, true);
41
- }
42
- catch (error) {
43
- onShare?.(`copy_${label.toLowerCase().replace(/\s+/g, "_")}`, false);
44
- }
45
- finally {
46
- setIsCopying(false);
47
- }
48
- }, [onShare]);
49
- // Share to Bluesky
50
- const shareToBluesky = (0, react_1.useCallback)(() => {
51
- const streamUrl = getStreamUrl();
52
- const text = profile
53
- ? `Check out @${profile.handle} live on Streamplace! ${streamUrl}`
54
- : `Check out this stream on Streamplace! ${streamUrl}`;
55
- const blueskyUrl = `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
56
- react_native_1.Linking.openURL(blueskyUrl);
57
- onShare?.("share_bluesky", true);
58
- }, [profile, getStreamUrl, onShare]);
59
- // Share to Twitter/X
60
- const shareToTwitter = (0, react_1.useCallback)(() => {
61
- const streamUrl = getStreamUrl();
62
- const text = profile
63
- ? `Check out @${profile.handle} live on Streamplace!`
64
- : `Check out this stream on Streamplace!`;
65
- const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(streamUrl)}`;
66
- react_native_1.Linking.openURL(twitterUrl);
67
- onShare?.("share_twitter", true);
68
- }, [profile, getStreamUrl, onShare]);
69
- // Native share (mobile)
70
- const nativeShare = (0, react_1.useCallback)(async () => {
71
- const streamUrl = getStreamUrl();
72
- const text = profile
73
- ? `Check out @${profile.handle} live on Streamplace!`
74
- : `Check out this stream on Streamplace!`;
75
- if (react_native_1.Platform.OS === "web" && navigator.share) {
76
- try {
77
- await navigator.share({
78
- title: "Streamplace",
79
- text: text,
80
- url: streamUrl,
81
- });
82
- onShare?.("share_native", true);
83
- }
84
- catch (error) {
85
- // User cancelled or error occurred
86
- onShare?.("share_native", false);
87
- }
88
- }
89
- }, [profile, getStreamUrl, onShare]);
90
- return ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenu, { children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuTrigger, { children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Share2, { color: theme_1.colors.gray[200] }) }), (0, jsx_runtime_1.jsxs)(ui_1.ResponsiveDropdownMenuContent, { children: [(0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuGroup, { title: "Share", children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { onPress: shareToBluesky, closeOnPress: true, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [(0, jsx_runtime_1.jsx)(bluesky_icon_1.BlueskyIcon, { size: 20, color: theme_1.colors.gray[400] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Share to Bluesky" })] }) }), react_native_1.Platform.OS !== "web" || (navigator && navigator.share) ? ((0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { onPress: nativeShare, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [(0, jsx_runtime_1.jsx)(lucide_react_native_1.Share2, { size: 20, color: theme_1.colors.gray[400] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "More Options..." })] }) })) : null] }), (0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuGroup, { title: "Copy", children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { onPress: () => copyToClipboard(getStreamUrl(), "Stream link"), disabled: isCopying, closeOnPress: true, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [(0, jsx_runtime_1.jsx)(lucide_react_native_1.Link2, { size: 20, color: theme_1.colors.gray[400] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Copy Link" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuSeparator, {}), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { onPress: () => copyToClipboard(getEmbedCode(), "Embed code"), disabled: isCopying, closeOnPress: true, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [(0, jsx_runtime_1.jsx)(lucide_react_native_1.Code, { size: 20, color: theme_1.colors.gray[400] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Copy Embed Code" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuSeparator, {}), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { closeOnPress: true, onPress: () => copyToClipboard(getEmbedUrl(), "Embed URL"), disabled: isCopying, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [(0, jsx_runtime_1.jsx)(lucide_react_native_1.Copy, { size: 20, color: theme_1.colors.gray[400] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Copy Embed URL" })] }) })] })] })] }));
91
- }