@streamplace/components 0.7.13 → 0.7.15

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/package.json +13 -16
  2. package/src/components/mobile-player/fullscreen.native.tsx +15 -20
  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 +2 -0
  6. package/src/components/mobile-player/video.native.tsx +28 -11
  7. package/src/components/mobile-player/video.tsx +14 -3
  8. package/src/hooks/useLivestreamInfo.ts +6 -2
  9. package/src/lib/browser.ts +27 -0
  10. package/src/livestream-store/stream-key.tsx +1 -28
  11. package/src/streamplace-store/stream.tsx +51 -13
  12. package/dist/assets/emoji-data.json +0 -19371
  13. package/dist/components/chat/chat-box.js +0 -314
  14. package/dist/components/chat/chat-message.js +0 -87
  15. package/dist/components/chat/chat.js +0 -149
  16. package/dist/components/chat/emoji-suggestions.js +0 -35
  17. package/dist/components/chat/mention-suggestions.js +0 -42
  18. package/dist/components/chat/mod-view.js +0 -94
  19. package/dist/components/chat/system-message.js +0 -19
  20. package/dist/components/dashboard/chat-panel.js +0 -38
  21. package/dist/components/dashboard/header.js +0 -80
  22. package/dist/components/dashboard/index.js +0 -14
  23. package/dist/components/dashboard/information-widget.js +0 -234
  24. package/dist/components/dashboard/mod-actions.js +0 -71
  25. package/dist/components/dashboard/problems.js +0 -74
  26. package/dist/components/icons/bluesky-icon.js +0 -9
  27. package/dist/components/keep-awake.js +0 -7
  28. package/dist/components/keep-awake.native.js +0 -16
  29. package/dist/components/mobile-player/fullscreen.js +0 -74
  30. package/dist/components/mobile-player/fullscreen.native.js +0 -155
  31. package/dist/components/mobile-player/player.js +0 -94
  32. package/dist/components/mobile-player/props.js +0 -2
  33. package/dist/components/mobile-player/shared.js +0 -54
  34. package/dist/components/mobile-player/ui/countdown.js +0 -83
  35. package/dist/components/mobile-player/ui/index.js +0 -11
  36. package/dist/components/mobile-player/ui/input.js +0 -42
  37. package/dist/components/mobile-player/ui/metrics.js +0 -44
  38. package/dist/components/mobile-player/ui/report-modal.js +0 -90
  39. package/dist/components/mobile-player/ui/streamer-context-menu.js +0 -7
  40. package/dist/components/mobile-player/ui/streamer-loading-overlay.js +0 -104
  41. package/dist/components/mobile-player/ui/viewer-context-menu.js +0 -51
  42. package/dist/components/mobile-player/ui/viewer-loading-overlay.js +0 -49
  43. package/dist/components/mobile-player/ui/viewers.js +0 -23
  44. package/dist/components/mobile-player/use-webrtc.js +0 -243
  45. package/dist/components/mobile-player/video-retry.js +0 -29
  46. package/dist/components/mobile-player/video.js +0 -460
  47. package/dist/components/mobile-player/video.native.js +0 -276
  48. package/dist/components/mobile-player/webrtc-diagnostics.js +0 -110
  49. package/dist/components/mobile-player/webrtc-primitives.js +0 -27
  50. package/dist/components/mobile-player/webrtc-primitives.native.js +0 -8
  51. package/dist/components/share/sharesheet.js +0 -91
  52. package/dist/components/ui/button.js +0 -223
  53. package/dist/components/ui/dialog.js +0 -206
  54. package/dist/components/ui/dropdown.js +0 -172
  55. package/dist/components/ui/icons.js +0 -25
  56. package/dist/components/ui/index.js +0 -34
  57. package/dist/components/ui/info-box.js +0 -31
  58. package/dist/components/ui/info-row.js +0 -23
  59. package/dist/components/ui/input.js +0 -205
  60. package/dist/components/ui/loader.js +0 -10
  61. package/dist/components/ui/primitives/button.js +0 -125
  62. package/dist/components/ui/primitives/input.js +0 -206
  63. package/dist/components/ui/primitives/modal.js +0 -206
  64. package/dist/components/ui/primitives/text.js +0 -292
  65. package/dist/components/ui/resizeable.js +0 -121
  66. package/dist/components/ui/slider.js +0 -5
  67. package/dist/components/ui/text.js +0 -177
  68. package/dist/components/ui/textarea.js +0 -19
  69. package/dist/components/ui/toast.js +0 -175
  70. package/dist/components/ui/view.js +0 -252
  71. package/dist/hooks/index.js +0 -14
  72. package/dist/hooks/useAvatars.js +0 -35
  73. package/dist/hooks/useCameraToggle.js +0 -12
  74. package/dist/hooks/useKeyboard.js +0 -36
  75. package/dist/hooks/useKeyboardSlide.js +0 -14
  76. package/dist/hooks/useLivestreamInfo.js +0 -65
  77. package/dist/hooks/useOuterAndInnerDimensions.js +0 -30
  78. package/dist/hooks/usePlayerDimensions.js +0 -22
  79. package/dist/hooks/usePointerDevice.js +0 -71
  80. package/dist/hooks/useSegmentDimensions.js +0 -17
  81. package/dist/hooks/useSegmentTiming.js +0 -65
  82. package/dist/index.js +0 -34
  83. package/dist/lib/facet.js +0 -92
  84. package/dist/lib/system-messages.js +0 -101
  85. package/dist/lib/theme/atoms.js +0 -646
  86. package/dist/lib/theme/atoms.types.js +0 -6
  87. package/dist/lib/theme/index.js +0 -35
  88. package/dist/lib/theme/theme.js +0 -256
  89. package/dist/lib/theme/tokens.js +0 -659
  90. package/dist/lib/utils.js +0 -105
  91. package/dist/livestream-provider/index.js +0 -30
  92. package/dist/livestream-provider/websocket.js +0 -45
  93. package/dist/livestream-store/chat.js +0 -286
  94. package/dist/livestream-store/context.js +0 -5
  95. package/dist/livestream-store/index.js +0 -7
  96. package/dist/livestream-store/livestream-state.js +0 -2
  97. package/dist/livestream-store/livestream-store.js +0 -58
  98. package/dist/livestream-store/problems.js +0 -76
  99. package/dist/livestream-store/stream-key.js +0 -119
  100. package/dist/livestream-store/websocket-consumer.js +0 -94
  101. package/dist/player-store/context.js +0 -5
  102. package/dist/player-store/index.js +0 -9
  103. package/dist/player-store/player-provider.js +0 -57
  104. package/dist/player-store/player-state.js +0 -25
  105. package/dist/player-store/player-store.js +0 -199
  106. package/dist/player-store/single-player-provider.js +0 -121
  107. package/dist/streamplace-provider/context.js +0 -5
  108. package/dist/streamplace-provider/index.js +0 -20
  109. package/dist/streamplace-provider/poller.js +0 -49
  110. package/dist/streamplace-provider/xrpc.js +0 -0
  111. package/dist/streamplace-store/block.js +0 -65
  112. package/dist/streamplace-store/index.js +0 -6
  113. package/dist/streamplace-store/stream.js +0 -218
  114. package/dist/streamplace-store/streamplace-store.js +0 -47
  115. package/dist/streamplace-store/user.js +0 -52
  116. package/dist/streamplace-store/xrpc.js +0 -15
  117. package/dist/ui/index.js +0 -79
  118. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  119. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/56540125 +0 -0
  120. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/67b1eb60 +0 -0
  121. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/7c275f90 +0 -0
  122. 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
- }