@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,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BlueskyIcon = BlueskyIcon;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const react_native_svg_1 = tslib_1.__importStar(require("react-native-svg"));
7
- function BlueskyIcon({ size = 20, color = "#000" }) {
8
- return ((0, jsx_runtime_1.jsx)(react_native_svg_1.default, { width: size, height: size, viewBox: "0 0 600 530", fill: color, children: (0, jsx_runtime_1.jsx)(react_native_svg_1.Path, { d: "M136 44c66 50 138 151 164 205 26-54 98-155 164-205 48-36 126-64 126 25 0 18-10 149-16 170-21 74-96 93-163 81 117 20 147 86 82 153-122 125-176-32-189-72-3-8-4-11-4-8 0-3-1 0-4 8-13 40-67 197-189 72-65-67-35-133 82-153-67 12-142-7-163-81-6-21-16-152-16-170 0-89 78-61 126-25z" }) }));
9
- }
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KeepAwake = KeepAwake;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- function KeepAwake() {
6
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
7
- }
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KeepAwake = KeepAwake;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const expo_keep_awake_1 = require("expo-keep-awake");
6
- const react_1 = require("react");
7
- function KeepAwake() {
8
- // useKeepAwake();
9
- (0, react_1.useEffect)(() => {
10
- (0, expo_keep_awake_1.activateKeepAwakeAsync)();
11
- return () => {
12
- (0, expo_keep_awake_1.deactivateKeepAwake)();
13
- };
14
- }, []);
15
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
16
- }
@@ -1,74 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Fullscreen = Fullscreen;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const react_1 = require("react");
7
- const __1 = require("../..");
8
- const ui_1 = require("../../components/ui");
9
- const video_1 = tslib_1.__importDefault(require("./video"));
10
- const video_retry_1 = tslib_1.__importDefault(require("./video-retry"));
11
- function Fullscreen(props) {
12
- const playerId = (0, __1.getFirstPlayerID)();
13
- const protocol = (0, __1.usePlayerStore)((x) => x.protocol, playerId);
14
- const fullscreen = (0, __1.usePlayerStore)((x) => x.fullscreen, playerId);
15
- const setFullscreen = (0, __1.usePlayerStore)((x) => x.setFullscreen, playerId);
16
- const setSrc = (0, __1.usePlayerStore)((x) => x.setSrc);
17
- const divRef = (0, react_1.useRef)(null);
18
- const videoRef = (0, react_1.useRef)(null);
19
- (0, react_1.useEffect)(() => {
20
- setSrc(props.src);
21
- }, [props.src]);
22
- (0, react_1.useEffect)(() => {
23
- if (!divRef.current) {
24
- return;
25
- }
26
- (async () => {
27
- if (fullscreen && !document.fullscreenElement) {
28
- try {
29
- const div = divRef.current;
30
- if (typeof div.requestFullscreen === "function") {
31
- await div.requestFullscreen();
32
- }
33
- else if (videoRef.current) {
34
- if (typeof videoRef.current.webkitEnterFullscreen ===
35
- "function") {
36
- await videoRef.current.webkitEnterFullscreen();
37
- }
38
- else if (typeof videoRef.current.requestFullscreen === "function") {
39
- await videoRef.current.requestFullscreen();
40
- }
41
- }
42
- setFullscreen(true);
43
- }
44
- catch (e) {
45
- console.error("fullscreen failed", e.message);
46
- }
47
- }
48
- if (!fullscreen) {
49
- if (document.fullscreenElement) {
50
- try {
51
- await document.exitFullscreen();
52
- }
53
- catch (e) {
54
- console.error("fullscreen exit failed", e.message);
55
- }
56
- }
57
- setFullscreen(false);
58
- }
59
- })();
60
- }, [fullscreen, protocol]);
61
- (0, react_1.useEffect)(() => {
62
- const listener = () => {
63
- console.log("fullscreenchange", document.fullscreenElement);
64
- setFullscreen(!!document.fullscreenElement);
65
- };
66
- document.body.addEventListener("fullscreenchange", listener);
67
- document.body.addEventListener("webkitfullscreenchange", listener);
68
- return () => {
69
- document.body.removeEventListener("fullscreenchange", listener);
70
- document.body.removeEventListener("webkitfullscreenchange", listener);
71
- };
72
- }, []);
73
- return ((0, jsx_runtime_1.jsxs)(ui_1.View, { ref: divRef, style: { width: "100%", height: "100%", overflow: "hidden" }, children: [(0, jsx_runtime_1.jsx)(video_retry_1.default, { children: (0, jsx_runtime_1.jsx)(video_1.default, {}) }), props.children] }));
74
- }
@@ -1,155 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Fullscreen = Fullscreen;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const native_1 = require("@react-navigation/native");
7
- const react_1 = require("react");
8
- const react_native_1 = require("react-native");
9
- const react_native_edge_to_edge_1 = require("react-native-edge-to-edge");
10
- const react_native_safe_area_context_1 = require("react-native-safe-area-context");
11
- const __1 = require("../..");
12
- const video_native_1 = tslib_1.__importDefault(require("./video.native"));
13
- // Standard 16:9 video aspect ratio
14
- const VIDEO_ASPECT_RATIO = 16 / 9;
15
- function Fullscreen(props) {
16
- const ref = (0, react_1.useRef)(null);
17
- const insets = (0, react_native_safe_area_context_1.useSafeAreaInsets)();
18
- const navigation = (0, native_1.useNavigation)();
19
- const [dimensions, setDimensions] = (0, react_1.useState)(react_native_1.Dimensions.get("window"));
20
- // Get state from player store
21
- const protocol = (0, __1.usePlayerStore)((x) => x.protocol);
22
- const fullscreen = (0, __1.usePlayerStore)((x) => x.fullscreen);
23
- const setFullscreen = (0, __1.usePlayerStore)((x) => x.setFullscreen);
24
- const handle = (0, __1.useLivestreamStore)((x) => x.profile?.handle);
25
- const setSrc = (0, __1.usePlayerStore)((x) => x.setSrc);
26
- (0, react_1.useEffect)(() => {
27
- setSrc(props.src);
28
- }, [props.src]);
29
- // Re-calculate dimensions on orientation change
30
- (0, react_1.useEffect)(() => {
31
- const updateDimensions = () => {
32
- setDimensions(react_native_1.Dimensions.get("window"));
33
- };
34
- const subscription = react_native_1.Dimensions.addEventListener("change", updateDimensions);
35
- return () => {
36
- subscription.remove();
37
- };
38
- }, []);
39
- // Hide status bar when in fullscreen mode
40
- (0, react_1.useEffect)(() => {
41
- if (fullscreen) {
42
- react_native_edge_to_edge_1.SystemBars.setHidden(true);
43
- console.log("setting sidebar hidden");
44
- // Hide the navigation header
45
- navigation.setOptions({
46
- headerShown: false,
47
- });
48
- // Handle hardware back button
49
- const backHandler = react_native_1.BackHandler.addEventListener("hardwareBackPress", () => {
50
- setFullscreen(false);
51
- return true;
52
- });
53
- return () => {
54
- backHandler.remove();
55
- };
56
- }
57
- else {
58
- react_native_edge_to_edge_1.SystemBars.setHidden(false);
59
- // Restore the navigation header
60
- navigation.setOptions({
61
- headerShown: true,
62
- });
63
- }
64
- return () => {
65
- react_native_edge_to_edge_1.SystemBars.setHidden(false);
66
- // Ensure header is restored if component unmounts
67
- navigation.setOptions({
68
- headerShown: true,
69
- });
70
- };
71
- }, [fullscreen, navigation, setFullscreen]);
72
- // Handle fullscreen state changes for native video players
73
- (0, react_1.useEffect)(() => {
74
- // For WebRTC, we handle fullscreen manually via the custom implementation
75
- if (protocol === __1.PlayerProtocol.WEBRTC) {
76
- return;
77
- }
78
- // For HLS and other protocols, sync with native fullscreen
79
- if (ref.current) {
80
- if (fullscreen) {
81
- ref.current.enterFullscreen();
82
- }
83
- else {
84
- ref.current.exitFullscreen();
85
- }
86
- }
87
- }, [fullscreen, protocol]);
88
- if (fullscreen && protocol === __1.PlayerProtocol.WEBRTC) {
89
- // Determine if we're in landscape mode
90
- const isLandscape = dimensions.width > dimensions.height;
91
- // Calculate video container dimensions based on screen size and orientation
92
- let videoWidth;
93
- let videoHeight;
94
- if (isLandscape) {
95
- // In landscape, account for safe areas and use available height
96
- const availableHeight = dimensions.height - (insets.top + insets.bottom);
97
- const availableWidth = dimensions.width - (insets.left + insets.right);
98
- videoHeight = availableHeight;
99
- videoWidth = videoHeight * VIDEO_ASPECT_RATIO;
100
- // If calculated width exceeds available width, constrain and maintain aspect ratio
101
- if (videoWidth > availableWidth) {
102
- videoWidth = availableWidth;
103
- videoHeight = videoWidth / VIDEO_ASPECT_RATIO;
104
- }
105
- }
106
- else {
107
- // In portrait, account for safe areas
108
- const availableWidth = dimensions.width - (insets.left + insets.right);
109
- videoWidth = availableWidth;
110
- videoHeight = videoWidth / VIDEO_ASPECT_RATIO;
111
- }
112
- // Calculate position to center the video, accounting for safe areas
113
- const leftPosition = (dimensions.width - videoWidth) / 2;
114
- const topPosition = (dimensions.height - videoHeight) / 2;
115
- // When in custom fullscreen mode
116
- return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
117
- styles.fullscreenContainer,
118
- {
119
- width: isLandscape ? dimensions.width + 40 : dimensions.width,
120
- height: dimensions.height,
121
- },
122
- ], children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
123
- styles.videoContainer,
124
- {
125
- width: isLandscape ? videoWidth + 40 : videoWidth,
126
- height: videoHeight,
127
- left: leftPosition,
128
- top: topPosition,
129
- },
130
- ], children: [(0, jsx_runtime_1.jsx)(video_native_1.default, {}), props.children] }) }));
131
- }
132
- // Normal non-fullscreen mode
133
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(__1.VideoRetry, { children: (0, jsx_runtime_1.jsx)(video_native_1.default, {}) }), props.children] }));
134
- }
135
- const styles = react_native_1.StyleSheet.create({
136
- fullscreenContainer: {
137
- position: "absolute",
138
- top: 0,
139
- left: 0,
140
- right: 0,
141
- bottom: 0,
142
- backgroundColor: "#000",
143
- zIndex: 9999,
144
- elevation: 9999,
145
- margin: 0,
146
- padding: 0,
147
- justifyContent: "center",
148
- alignItems: "center",
149
- },
150
- videoContainer: {
151
- position: "absolute",
152
- backgroundColor: "#111",
153
- overflow: "hidden",
154
- },
155
- });
@@ -1,94 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PlayerUI = void 0;
4
- exports.Player = Player;
5
- exports.usePlayerStatus = usePlayerStatus;
6
- const tslib_1 = require("tslib");
7
- const jsx_runtime_1 = require("react/jsx-runtime");
8
- const react_1 = require("react");
9
- const atoms_1 = require("../../lib/theme/atoms");
10
- const player_store_1 = require("../../player-store");
11
- const streamplace_store_1 = require("../../streamplace-store");
12
- const ui_1 = require("../ui");
13
- const fullscreen_1 = require("./fullscreen");
14
- const report_modal_1 = tslib_1.__importDefault(require("./ui/report-modal"));
15
- const OFFLINE_THRESHOLD = 10000;
16
- exports.PlayerUI = tslib_1.__importStar(require("./ui"));
17
- function Player(props) {
18
- const setIngest = (0, player_store_1.usePlayerStore)((x) => x.setIngestConnectionState);
19
- const clearControlsTimeout = (0, player_store_1.usePlayerStore)((x) => x.clearControlsTimeout);
20
- const setReportingURL = (0, player_store_1.usePlayerStore)((x) => x.setReportingURL);
21
- const reportModalOpen = (0, player_store_1.usePlayerStore)((x) => x.reportModalOpen);
22
- const setReportModalOpen = (0, player_store_1.usePlayerStore)((x) => x.setReportModalOpen);
23
- const reportSubject = (0, player_store_1.usePlayerStore)((x) => x.reportSubject);
24
- (0, react_1.useEffect)(() => {
25
- setReportingURL(props.reportingURL ?? null);
26
- }, [props.reportingURL]);
27
- // Will call back every few seconds to send health updates
28
- usePlayerStatus();
29
- (0, react_1.useEffect)(() => {
30
- setIngest(props.ingest ? "new" : null);
31
- }, []);
32
- if (typeof props.src !== "string") {
33
- return ((0, jsx_runtime_1.jsx)(ui_1.View, { children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "No source provided \uD83E\uDD37" }) }));
34
- }
35
- (0, react_1.useEffect)(() => {
36
- return () => {
37
- clearControlsTimeout();
38
- };
39
- }, []);
40
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)(ui_1.View, { style: [
41
- atoms_1.zIndex[0],
42
- atoms_1.w.percent[100],
43
- atoms_1.h.percent[100],
44
- atoms_1.flex.shrink[1],
45
- atoms_1.layout.flex.center,
46
- ], children: [(0, jsx_runtime_1.jsx)(report_modal_1.default, { open: reportModalOpen, onOpenChange: setReportModalOpen, subject: reportSubject }), (0, jsx_runtime_1.jsx)(fullscreen_1.Fullscreen, { src: props.src, children: props.children })] }) }));
47
- }
48
- const POLL_INTERVAL = 5000;
49
- function usePlayerStatus() {
50
- const playerStatus = (0, player_store_1.usePlayerStore)((x) => x.status);
51
- const url = (0, streamplace_store_1.useStreamplaceStore)((x) => x.url);
52
- const playerEvent = (0, player_store_1.usePlayerStore)((x) => x.playerEvent);
53
- const [whatDoing, setWhatDoing] = (0, react_1.useState)(player_store_1.PlayerStatus.START);
54
- const [whatDid, setWhatDid] = (0, react_1.useState)({});
55
- const [doingSince, setDoingSince] = (0, react_1.useState)(Date.now());
56
- const [lastUpdated, setLastUpdated] = (0, react_1.useState)(0);
57
- const updateWhatDid = (now) => {
58
- const prev = whatDid[whatDoing] ?? 0;
59
- const duration = now.getTime() - doingSince;
60
- const ret = {
61
- ...whatDid,
62
- [whatDoing]: prev + duration,
63
- };
64
- return ret;
65
- };
66
- // callback to update the status
67
- (0, react_1.useEffect)(() => {
68
- const now = new Date();
69
- if (playerStatus !== whatDoing) {
70
- setWhatDid(updateWhatDid(now));
71
- setWhatDoing(playerStatus);
72
- setDoingSince(now.getTime());
73
- }
74
- }, [playerStatus]);
75
- (0, react_1.useEffect)(() => {
76
- if (lastUpdated === 0) {
77
- return;
78
- }
79
- const now = new Date();
80
- const fullWhatDid = updateWhatDid(now);
81
- setWhatDid({});
82
- setDoingSince(now.getTime());
83
- playerEvent(url, now.toISOString(), "aq-played", {
84
- whatHappened: fullWhatDid,
85
- });
86
- }, [lastUpdated]);
87
- (0, react_1.useEffect)(() => {
88
- const interval = setInterval((_) => {
89
- setLastUpdated(Date.now());
90
- }, POLL_INTERVAL);
91
- return () => clearInterval(interval);
92
- }, []);
93
- return [whatDoing];
94
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,54 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.srcToUrl = srcToUrl;
4
- const react_1 = require("react");
5
- const __1 = require("../..");
6
- const protocolSuffixes = {
7
- m3u8: __1.PlayerProtocol.HLS,
8
- mp4: __1.PlayerProtocol.PROGRESSIVE_MP4,
9
- webm: __1.PlayerProtocol.PROGRESSIVE_WEBM,
10
- webrtc: __1.PlayerProtocol.WEBRTC,
11
- };
12
- function srcToUrl(props, protocol) {
13
- const url = (0, __1.useStreamplaceStore)((x) => x.url);
14
- return (0, react_1.useMemo)(() => {
15
- if (props.src.startsWith("http://") || props.src.startsWith("https://")) {
16
- const segments = props.src.split(/[./]/);
17
- const suffix = segments[segments.length - 1];
18
- if (protocolSuffixes[suffix]) {
19
- return {
20
- url: props.src,
21
- protocol: protocolSuffixes[suffix],
22
- };
23
- }
24
- else {
25
- throw new Error(`unknown playback protocol: ${suffix}`);
26
- }
27
- }
28
- let outUrl;
29
- if (protocol === __1.PlayerProtocol.HLS) {
30
- if (props.selectedRendition === "auto") {
31
- outUrl = `${url}/api/playback/${props.src}/hls/index.m3u8`;
32
- }
33
- else {
34
- outUrl = `${url}/api/playback/${props.src}/hls/index.m3u8?rendition=${props.selectedRendition || "source"}`;
35
- }
36
- }
37
- else if (protocol === __1.PlayerProtocol.PROGRESSIVE_MP4) {
38
- outUrl = `${url}/api/playback/${props.src}/stream.mp4`;
39
- }
40
- else if (protocol === __1.PlayerProtocol.PROGRESSIVE_WEBM) {
41
- outUrl = `${url}/api/playback/${props.src}/stream.webm`;
42
- }
43
- else if (protocol === __1.PlayerProtocol.WEBRTC) {
44
- outUrl = `${url}/api/playback/${props.src}/webrtc?rendition=${props.selectedRendition || "source"}`;
45
- }
46
- else {
47
- throw new Error(`unknown playback protocol: ${protocol}`);
48
- }
49
- return {
50
- protocol: protocol,
51
- url: outUrl,
52
- };
53
- }, [props.src, props.selectedRendition, protocol, url]);
54
- }
@@ -1,83 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CountdownOverlay = CountdownOverlay;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const react_1 = require("react");
7
- const react_native_reanimated_1 = tslib_1.__importStar(require("react-native-reanimated"));
8
- function CountdownOverlay({ visible, width, height, startFrom = 3, onDone, }) {
9
- const [countdown, setCountdown] = (0, react_1.useState)(startFrom);
10
- const startTimestamp = (0, react_native_reanimated_1.useSharedValue)(null);
11
- const done = (0, react_native_reanimated_1.useSharedValue)(false);
12
- // Animation values
13
- const scale = (0, react_native_reanimated_1.useSharedValue)(1);
14
- const opacity = (0, react_native_reanimated_1.useSharedValue)(1);
15
- const updateCountdown = (value) => {
16
- setCountdown(value);
17
- };
18
- const handleDone = () => {
19
- if (onDone)
20
- onDone();
21
- };
22
- // Accurate countdown using useFrameCallback
23
- (0, react_native_reanimated_1.useFrameCallback)(({ timestamp }) => {
24
- if (!visible)
25
- return;
26
- // Set start timestamp on first frame
27
- if (startTimestamp.value === null) {
28
- startTimestamp.value = timestamp;
29
- return;
30
- }
31
- const elapsed = (timestamp - startTimestamp.value) / 1000; // Convert to seconds
32
- const remaining = Math.max(0, startFrom - Math.floor(elapsed));
33
- // Use runOnJS to call JavaScript functions from worklet
34
- (0, react_native_reanimated_1.runOnJS)(updateCountdown)(remaining);
35
- if (remaining === 0 && !done.value) {
36
- done.value = true;
37
- (0, react_native_reanimated_1.runOnJS)(handleDone)();
38
- }
39
- });
40
- (0, react_1.useEffect)(() => {
41
- if (visible) {
42
- startTimestamp.value = null; // Will be set on first frame
43
- setCountdown(startFrom);
44
- done.value = false;
45
- }
46
- else {
47
- setCountdown(startFrom);
48
- }
49
- }, [visible, startFrom]);
50
- // Animate scale and opacity on countdown change
51
- (0, react_1.useEffect)(() => {
52
- if (visible && countdown > 0) {
53
- scale.value = 1;
54
- opacity.value = 1;
55
- scale.value = (0, react_native_reanimated_1.withTiming)(1.5, { duration: 1000 });
56
- opacity.value = (0, react_native_reanimated_1.withTiming)(0, { duration: 1000 });
57
- }
58
- }, [countdown, visible, scale, opacity]);
59
- const animatedStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => ({
60
- transform: [{ scale: scale.value }],
61
- opacity: opacity.value,
62
- }));
63
- if (!visible || countdown === 0)
64
- return null;
65
- return ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: {
66
- position: "absolute",
67
- top: 0,
68
- left: 0,
69
- width,
70
- height,
71
- backgroundColor: "rgba(0,0,0,0.7)",
72
- alignItems: "center",
73
- justifyContent: "center",
74
- zIndex: 1000,
75
- }, children: (0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.Text, { style: [
76
- {
77
- color: "white",
78
- fontSize: 120,
79
- fontWeight: "bold",
80
- },
81
- animatedStyle,
82
- ], children: typeof countdown === "number" ? countdown : "" }) }));
83
- }
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./countdown"), exports);
5
- tslib_1.__exportStar(require("./input"), exports);
6
- tslib_1.__exportStar(require("./metrics"), exports);
7
- tslib_1.__exportStar(require("./streamer-context-menu"), exports);
8
- tslib_1.__exportStar(require("./streamer-loading-overlay"), exports);
9
- tslib_1.__exportStar(require("./viewer-context-menu"), exports);
10
- tslib_1.__exportStar(require("./viewer-loading-overlay"), exports);
11
- tslib_1.__exportStar(require("./viewers"), exports);
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InputPanel = InputPanel;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const react_native_1 = require("react-native");
7
- const hooks_1 = require("../../../hooks");
8
- const atoms = tslib_1.__importStar(require("../../../lib/theme/atoms"));
9
- const ui_1 = require("../../ui");
10
- const { gap, h, layout, mt, p, position, px, py, sizes, w } = atoms;
11
- function InputPanel({ title, setTitle, ingestStarting, toggleGoLive, }) {
12
- const { slideKeyboard } = (0, hooks_1.useKeyboardSlide)();
13
- return ((0, jsx_runtime_1.jsx)(ui_1.View, { style: [
14
- layout.position.absolute,
15
- h.percent[30],
16
- position.bottom[0],
17
- w.percent[100],
18
- layout.flex.center,
19
- { transform: [{ translateY: slideKeyboard }] },
20
- ], children: (0, jsx_runtime_1.jsxs)(ui_1.View, { style: [
21
- layout.flex.column,
22
- gap.all[2],
23
- sizes.maxWidth[80],
24
- { padding: 10 },
25
- ], children: [(0, jsx_runtime_1.jsx)(ui_1.View, { backgroundColor: "rgba(64,64,64,0.8)", borderRadius: 12, children: (0, jsx_runtime_1.jsx)(ui_1.Input, { value: title, onChange: setTitle, placeholder: "Enter stream title", onEndEditing: react_native_1.Keyboard.dismiss }) }), ingestStarting ? ((0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Starting your stream..." })) : ((0, jsx_runtime_1.jsxs)(ui_1.View, { style: [layout.flex.center], children: [(0, jsx_runtime_1.jsxs)(react_native_1.Pressable, { onPress: toggleGoLive, style: [
26
- px[4],
27
- py[2],
28
- layout.flex.row,
29
- layout.flex.center,
30
- gap.all[1],
31
- {
32
- backgroundColor: "rgba(64,64,64, 0.8)",
33
- borderRadius: 12,
34
- },
35
- ], children: [(0, jsx_runtime_1.jsx)(ui_1.View, { style: [
36
- p[2],
37
- {
38
- backgroundColor: "rgba(256,0,0, 0.8)",
39
- borderRadius: 12,
40
- },
41
- ] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { center: true, children: "Go Live" })] }), (0, jsx_runtime_1.jsx)(ui_1.Text, { color: "muted", size: "xs", style: [mt[2]], children: "We'll announce that you're live on Bluesky." })] }))] }) }));
42
- }
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MetricsPanel = MetricsPanel;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const lucide_react_native_1 = require("lucide-react-native");
7
- const useSegmentTiming_1 = require("../../../hooks/useSegmentTiming");
8
- const atoms = tslib_1.__importStar(require("../../../lib/theme/atoms"));
9
- const ui_1 = require("../../ui");
10
- function MetricsPanel({ showMetrics }) {
11
- const { connectionQuality, segmentDeltas, mean, range } = (0, useSegmentTiming_1.useSegmentTiming)();
12
- let icon = (0, jsx_runtime_1.jsx)(lucide_react_native_1.CircleX, { color: "#d44" });
13
- let color = "#d44";
14
- if (connectionQuality === "good") {
15
- icon = (0, jsx_runtime_1.jsx)(lucide_react_native_1.CircleCheck, { color: "#4d4" });
16
- color = "#4d4";
17
- }
18
- else if (connectionQuality === "degraded") {
19
- icon = (0, jsx_runtime_1.jsx)(lucide_react_native_1.AlertCircle, { color: "#aa4" });
20
- color = "#aa4";
21
- }
22
- else {
23
- icon = (0, jsx_runtime_1.jsx)(lucide_react_native_1.CircleX, { color: "#d44" });
24
- color = "#d44";
25
- }
26
- return ((0, jsx_runtime_1.jsxs)(ui_1.View, { style: {
27
- alignItems: "center",
28
- gap: 8,
29
- }, children: [(0, jsx_runtime_1.jsxs)(ui_1.View, { style: {
30
- flexDirection: "row",
31
- alignItems: "center",
32
- padding: 10,
33
- backgroundColor: "rgba(0, 0, 0, 0.5)",
34
- borderRadius: 8,
35
- gap: 4,
36
- }, children: [icon, (0, jsx_runtime_1.jsx)(ui_1.Text, { style: [
37
- atoms.pt[0],
38
- {
39
- color,
40
- },
41
- ], children: connectionQuality.toUpperCase() })] }), showMetrics && ((0, jsx_runtime_1.jsxs)(ui_1.View, { children: [(0, jsx_runtime_1.jsxs)(ui_1.Text, { children: ["last \u0394:", " ", segmentDeltas.length > 0
42
- ? segmentDeltas[segmentDeltas.length - 1]
43
- : "—"] }), (0, jsx_runtime_1.jsxs)(ui_1.Text, { children: ["mean: ", mean] }), (0, jsx_runtime_1.jsxs)(ui_1.Text, { children: ["range: ", range] })] }))] }));
44
- }