@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
package/dist/lib/utils.js DELETED
@@ -1,105 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mergeStyles = mergeStyles;
4
- exports.createStyleMerger = createStyleMerger;
5
- exports.conditionalStyle = conditionalStyle;
6
- exports.responsiveValue = responsiveValue;
7
- exports.platformStyle = platformStyle;
8
- exports.hexToRgba = hexToRgba;
9
- exports.debounce = debounce;
10
- exports.throttle = throttle;
11
- exports.forwardProps = forwardProps;
12
- const react_native_1 = require("react-native");
13
- /**
14
- * Merges React Native styles similar to how cn() merges CSS classes
15
- * Handles arrays, objects, and falsy values
16
- */
17
- function mergeStyles(...styles) {
18
- const validStyles = styles.filter(Boolean).flat();
19
- return react_native_1.StyleSheet.flatten(validStyles) || {};
20
- }
21
- /**
22
- * Creates a style merger function that includes base styles
23
- * Useful for component variants
24
- */
25
- function createStyleMerger(baseStyle) {
26
- return (...styles) => {
27
- return mergeStyles(baseStyle, ...styles);
28
- };
29
- }
30
- /**
31
- * Conditionally applies styles based on boolean conditions
32
- */
33
- function conditionalStyle(condition, trueStyle, falseStyle) {
34
- return condition ? trueStyle : falseStyle;
35
- }
36
- /**
37
- * Creates responsive values based on screen dimensions
38
- */
39
- function responsiveValue(values, screenWidth) {
40
- if (screenWidth >= 1280 && values.xl !== undefined)
41
- return values.xl;
42
- if (screenWidth >= 1024 && values.lg !== undefined)
43
- return values.lg;
44
- if (screenWidth >= 768 && values.md !== undefined)
45
- return values.md;
46
- if (screenWidth >= 640 && values.sm !== undefined)
47
- return values.sm;
48
- return values.default;
49
- }
50
- /**
51
- * Creates platform-specific styles
52
- */
53
- function platformStyle(styles) {
54
- const Platform = require("react-native").Platform;
55
- if (Platform.OS === "ios" && styles.ios)
56
- return styles.ios;
57
- if (Platform.OS === "android" && styles.android)
58
- return styles.android;
59
- if (Platform.OS === "web" && styles.web)
60
- return styles.web;
61
- return styles.default || {};
62
- }
63
- /**
64
- * Converts hex color to rgba
65
- */
66
- function hexToRgba(hex, alpha = 1) {
67
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
68
- if (!result)
69
- return hex;
70
- const r = parseInt(result[1], 16);
71
- const g = parseInt(result[2], 16);
72
- const b = parseInt(result[3], 16);
73
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
74
- }
75
- /**
76
- * Creates a debounced function for performance
77
- */
78
- function debounce(func, delay) {
79
- let timeoutId;
80
- return (...args) => {
81
- clearTimeout(timeoutId);
82
- timeoutId = setTimeout(() => func(...args), delay);
83
- };
84
- }
85
- /**
86
- * Creates a throttled function for performance
87
- */
88
- function throttle(func, delay) {
89
- let lastCall = 0;
90
- return (...args) => {
91
- const now = Date.now();
92
- if (now - lastCall >= delay) {
93
- lastCall = now;
94
- func(...args);
95
- }
96
- };
97
- }
98
- /**
99
- * Type-safe component prop forwarding
100
- */
101
- function forwardProps(props, omit) {
102
- const result = { ...props };
103
- omit.forEach((key) => delete result[key]);
104
- return result;
105
- }
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LivestreamProvider = LivestreamProvider;
4
- exports.WebsocketWatcher = WebsocketWatcher;
5
- exports.LivestreamPoller = LivestreamPoller;
6
- const jsx_runtime_1 = require("react/jsx-runtime");
7
- const react_1 = require("react");
8
- const livestream_store_1 = require("../livestream-store");
9
- const websocket_1 = require("./websocket");
10
- function LivestreamProvider({ children, src, }) {
11
- const context = (0, react_1.useContext)(livestream_store_1.LivestreamContext);
12
- const store = (0, react_1.useRef)((0, livestream_store_1.makeLivestreamStore)()).current;
13
- if (context) {
14
- // this is ok, there's use cases for having one in another
15
- // like having a player component that's independently usable
16
- // but can also be embedded within an entire livestream page
17
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
18
- }
19
- window.livestreamStore = store;
20
- return ((0, jsx_runtime_1.jsx)(livestream_store_1.LivestreamContext.Provider, { value: { store: store }, children: (0, jsx_runtime_1.jsx)(LivestreamPoller, { src: src, children: children }) }));
21
- }
22
- function WebsocketWatcher({ src }) {
23
- (0, websocket_1.useLivestreamWebsocket)(src);
24
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
25
- }
26
- function LivestreamPoller({ children, src, }) {
27
- // Websocket watcher is a sibling instead of a parent to avoid
28
- // re-rendering when the websocket does stuff
29
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(WebsocketWatcher, { src: src }), children] }));
30
- }
@@ -1,45 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useLivestreamWebsocket = useLivestreamWebsocket;
4
- const tslib_1 = require("tslib");
5
- const react_1 = require("react");
6
- const react_use_websocket_1 = tslib_1.__importDefault(require("react-use-websocket"));
7
- const livestream_store_1 = require("../livestream-store");
8
- const streamplace_store_1 = require("../streamplace-store");
9
- function useLivestreamWebsocket(src) {
10
- const url = (0, streamplace_store_1.useUrl)();
11
- const handleWebSocketMessages = (0, livestream_store_1.useHandleWebsocketMessages)();
12
- let wsUrl = url.replace(/^http\:/, "ws:");
13
- wsUrl = wsUrl.replace(/^https\:/, "wss:");
14
- const ref = (0, react_1.useRef)([]);
15
- const handle = (0, react_1.useRef)(null);
16
- const { readyState } = (0, react_use_websocket_1.default)(`${wsUrl}/api/websocket/${src}`, {
17
- reconnectInterval: 1000,
18
- shouldReconnect: () => true,
19
- onOpen: () => {
20
- ref.current = [];
21
- },
22
- onError: (e) => {
23
- console.log("onError", e);
24
- },
25
- // spamming the redux store with messages causes a zillion re-renders,
26
- // so we batch them up a bit
27
- onMessage: (msg) => {
28
- try {
29
- const data = JSON.parse(msg.data);
30
- ref.current.push(data);
31
- if (handle.current) {
32
- return;
33
- }
34
- handle.current = setTimeout(() => {
35
- handleWebSocketMessages(ref.current);
36
- ref.current = [];
37
- handle.current = null;
38
- }, 250);
39
- }
40
- catch (e) {
41
- console.log("onMessage parse error", e);
42
- }
43
- },
44
- });
45
- }
@@ -1,286 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.reduceChat = exports.useReportChatMessage = exports.useSubmitReport = exports.reduceChatIncremental = exports.useCreateChatMessage = exports.useAddPendingHide = exports.usePendingHides = exports.useSetReplyToMessage = exports.useReplyToMessage = void 0;
4
- const api_1 = require("@atproto/api");
5
- const react_1 = require("react");
6
- const streamplace_store_1 = require("../streamplace-store");
7
- const xrpc_1 = require("../streamplace-store/xrpc");
8
- const livestream_store_1 = require("./livestream-store");
9
- const useReplyToMessage = () => (0, livestream_store_1.useLivestreamStore)((state) => state.replyToMessage);
10
- exports.useReplyToMessage = useReplyToMessage;
11
- const useSetReplyToMessage = () => {
12
- const store = (0, livestream_store_1.getStoreFromContext)();
13
- return (0, react_1.useCallback)((message) => {
14
- store.setState({ replyToMessage: message });
15
- }, [store]);
16
- };
17
- exports.useSetReplyToMessage = useSetReplyToMessage;
18
- const usePendingHides = () => (0, livestream_store_1.useLivestreamStore)((state) => state.pendingHides);
19
- exports.usePendingHides = usePendingHides;
20
- const useAddPendingHide = () => {
21
- const store = (0, livestream_store_1.getStoreFromContext)();
22
- return (0, react_1.useCallback)((messageUri) => {
23
- const state = store.getState();
24
- if (!state.pendingHides.includes(messageUri)) {
25
- const newPendingHides = [...state.pendingHides, messageUri];
26
- const newState = (0, exports.reduceChat)(state, [], [], [messageUri]);
27
- store.setState({
28
- ...newState,
29
- pendingHides: newPendingHides,
30
- });
31
- }
32
- }, [store]);
33
- };
34
- exports.useAddPendingHide = useAddPendingHide;
35
- const useCreateChatMessage = () => {
36
- const pdsAgent = (0, xrpc_1.usePDSAgent)();
37
- const store = (0, livestream_store_1.getStoreFromContext)();
38
- const userDID = (0, streamplace_store_1.useDID)();
39
- const userHandle = (0, streamplace_store_1.useHandle)();
40
- const chatProfile = (0, streamplace_store_1.useChatProfile)();
41
- return async (msg) => {
42
- if (!pdsAgent || !userDID) {
43
- throw new Error("No PDS agent or user DID found");
44
- }
45
- let state = store.getState();
46
- const streamerProfile = state.profile;
47
- if (!streamerProfile) {
48
- throw new Error("Profile not found");
49
- }
50
- const rt = new api_1.RichText({ text: msg.text });
51
- await rt.detectFacets(pdsAgent);
52
- const record = {
53
- text: msg.text,
54
- createdAt: new Date().toISOString(),
55
- streamer: streamerProfile.did,
56
- facets: rt.facets,
57
- ...(msg.reply
58
- ? {
59
- reply: {
60
- root: {
61
- cid: msg.reply.cid,
62
- uri: msg.reply.uri,
63
- },
64
- parent: {
65
- cid: msg.reply.cid,
66
- uri: msg.reply.uri,
67
- },
68
- },
69
- }
70
- : {}),
71
- };
72
- const localChat = {
73
- uri: `local-${Date.now()}`,
74
- cid: "",
75
- author: {
76
- did: userDID,
77
- handle: userHandle || userDID,
78
- },
79
- record: record,
80
- indexedAt: new Date().toISOString(),
81
- chatProfile: chatProfile || undefined,
82
- };
83
- state = (0, exports.reduceChat)(state, [localChat], [], []);
84
- store.setState(state);
85
- await pdsAgent.com.atproto.repo.createRecord({
86
- repo: userDID,
87
- collection: "place.stream.chat.message",
88
- record,
89
- });
90
- };
91
- };
92
- exports.useCreateChatMessage = useCreateChatMessage;
93
- const buildSortedChatList = (chatIndex, existingChatList, newMessages, removedKeys) => {
94
- const sortedKeys = Object.keys(chatIndex).sort((a, b) => {
95
- const aTime = parseInt(a.split("-")[0], 10);
96
- const bTime = parseInt(b.split("-")[0], 10);
97
- return bTime - aTime;
98
- });
99
- return sortedKeys
100
- .map((key) => chatIndex[key])
101
- .filter((msg) => !removedKeys.has(msg.uri));
102
- };
103
- const profileIsDifferent = (newProfile, oldProfile) => {
104
- if (!oldProfile) {
105
- return true;
106
- }
107
- if (!newProfile) {
108
- return false;
109
- }
110
- if (!oldProfile.color) {
111
- return true;
112
- }
113
- if (!newProfile.color) {
114
- // idk. shouldn't happen.
115
- return false;
116
- }
117
- const { red: newRed, green: newGreen, blue: newBlue } = newProfile.color;
118
- const { red: oldRed, green: oldGreen, blue: oldBlue } = oldProfile.color;
119
- return newRed !== oldRed || newGreen !== oldGreen || newBlue !== oldBlue;
120
- };
121
- const reduceChatIncremental = (state, newMessages, blocks, hideUris = []) => {
122
- if (newMessages.length === 0 &&
123
- blocks.length === 0 &&
124
- hideUris.length === 0) {
125
- return state;
126
- }
127
- const newChatIndex = { ...state.chatIndex };
128
- const newAuthors = { ...state.authors };
129
- let hasChanges = false;
130
- const removedKeys = new Set();
131
- console.log("newMessages", newMessages);
132
- for (const msg of newMessages) {
133
- if (msg.deleted) {
134
- hasChanges = true;
135
- console.log("deleted", msg.uri);
136
- removedKeys.add(msg.uri);
137
- }
138
- }
139
- newMessages = newMessages.filter((msg) => msg.deleted !== true);
140
- // handle blocks
141
- if (blocks.length > 0) {
142
- const blockedDIDs = new Set(blocks.map((block) => block.record.subject));
143
- for (const [key, message] of Object.entries(newChatIndex)) {
144
- if (blockedDIDs.has(message.author.did)) {
145
- delete newChatIndex[key];
146
- removedKeys.add(key);
147
- hasChanges = true;
148
- }
149
- }
150
- }
151
- if (hideUris.length > 0) {
152
- for (const [key, message] of Object.entries(newChatIndex)) {
153
- if (hideUris.includes(message.uri)) {
154
- delete newChatIndex[key];
155
- removedKeys.add(key);
156
- hasChanges = true;
157
- }
158
- }
159
- }
160
- const messagesToAdd = [];
161
- for (const message of newMessages) {
162
- // don't worry about messages that will be hidden
163
- if (state.pendingHides.includes(message.uri)) {
164
- continue;
165
- }
166
- const date = new Date(message.record.createdAt);
167
- const key = `${date.getTime()}-${message.uri}`;
168
- // only change the ref if the profile is different to avoid re-renders elsewhere
169
- if (profileIsDifferent(message.chatProfile, newAuthors[message.author.did])) {
170
- newAuthors[message.author.did] = message.chatProfile;
171
- }
172
- // skip messages we already have
173
- if (newChatIndex[key] && newChatIndex[key].uri === message.uri) {
174
- continue;
175
- }
176
- // if we have a local message, replace it with the new one
177
- if (!message.uri.startsWith("local-")) {
178
- const existingLocalKey = Object.keys(newChatIndex).find((k) => {
179
- const msg = newChatIndex[k];
180
- return (msg.uri.startsWith("local-") &&
181
- msg.record.text === message.record.text &&
182
- msg.author.did === message.author.did &&
183
- Math.abs(new Date(msg.record.createdAt).getTime() - date.getTime()) <
184
- 10000 // Within 10 seconds
185
- );
186
- });
187
- if (existingLocalKey) {
188
- delete newChatIndex[existingLocalKey];
189
- removedKeys.add(existingLocalKey);
190
- hasChanges = true;
191
- }
192
- }
193
- // add reply info
194
- let processedMessage = message;
195
- if (message.record.reply) {
196
- const reply = message.record.reply;
197
- const parentUri = reply?.parent?.uri || reply?.root?.uri;
198
- if (parentUri) {
199
- const parentMsgKey = Object.keys(newChatIndex).find((k) => newChatIndex[k].uri === parentUri);
200
- if (parentMsgKey) {
201
- const parentMsg = newChatIndex[parentMsgKey];
202
- // Don't allow replies to system messages
203
- if (parentMsg.author.did !== "did:sys:system") {
204
- processedMessage = {
205
- ...message,
206
- replyTo: {
207
- cid: parentMsg.cid,
208
- uri: parentMsg.uri,
209
- author: parentMsg.author,
210
- record: parentMsg.record,
211
- chatProfile: parentMsg.chatProfile,
212
- indexedAt: parentMsg.indexedAt,
213
- },
214
- };
215
- }
216
- }
217
- }
218
- }
219
- messagesToAdd.push({ key, message: processedMessage });
220
- hasChanges = true;
221
- }
222
- // Add new messages to index
223
- for (const { key, message } of messagesToAdd) {
224
- newChatIndex[key] = message;
225
- }
226
- // only rebuild if we have changes
227
- if (!hasChanges) {
228
- return state;
229
- }
230
- // Build the new sorted chat list efficiently
231
- const newChatList = buildSortedChatList(newChatIndex, state.chat, messagesToAdd, removedKeys);
232
- // Clean up pendingHides - remove URIs that we've now processed
233
- let newPendingHides = state.pendingHides;
234
- if (hideUris.length > 0) {
235
- newPendingHides = state.pendingHides.filter((uri) => !hideUris.includes(uri));
236
- }
237
- return {
238
- ...state,
239
- authors: newAuthors,
240
- chatIndex: newChatIndex,
241
- chat: newChatList,
242
- pendingHides: newPendingHides,
243
- };
244
- };
245
- exports.reduceChatIncremental = reduceChatIncremental;
246
- const useSubmitReport = () => {
247
- const pdsAgent = (0, xrpc_1.usePDSAgent)();
248
- const userDID = (0, streamplace_store_1.useDID)();
249
- return (0, react_1.useCallback)(async (subject, reasonType, reason,
250
- // no clue about this
251
- moderationSvcDid = "did:web:stream.place") => {
252
- if (!pdsAgent || !userDID) {
253
- throw new Error("No PDS agent or user DID found");
254
- }
255
- try {
256
- const response = await pdsAgent.com.atproto.moderation.createReport({
257
- reasonType,
258
- reason,
259
- subject: subject,
260
- }, {
261
- headers: {
262
- // "atproto-proxy": `${userDID}#atproto_labeler`,
263
- },
264
- });
265
- return response;
266
- }
267
- catch (error) {
268
- console.error("Failed to submit report:", error);
269
- throw error;
270
- }
271
- }, [pdsAgent, userDID]);
272
- };
273
- exports.useSubmitReport = useSubmitReport;
274
- const useReportChatMessage = () => {
275
- const submitReport = (0, exports.useSubmitReport)();
276
- return (0, react_1.useCallback)(async (message, reasonType, reason) => {
277
- const reportSubject = {
278
- $type: "com.atproto.repo.strongRef",
279
- uri: message.uri,
280
- cid: message.cid,
281
- };
282
- return await submitReport(reportSubject, reasonType, reason);
283
- }, [submitReport]);
284
- };
285
- exports.useReportChatMessage = useReportChatMessage;
286
- exports.reduceChat = exports.reduceChatIncremental;
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LivestreamContext = void 0;
4
- const react_1 = require("react");
5
- exports.LivestreamContext = (0, react_1.createContext)(null);
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./chat"), exports);
5
- tslib_1.__exportStar(require("./context"), exports);
6
- tslib_1.__exportStar(require("./livestream-store"), exports);
7
- tslib_1.__exportStar(require("./stream-key"), exports);
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,58 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useRenditions = exports.useSegment = exports.useLivestream = exports.useViewers = exports.useProfile = exports.useChat = exports.useHandleWebsocketMessages = exports.makeLivestreamStore = void 0;
4
- exports.getStoreFromContext = getStoreFromContext;
5
- exports.useLivestreamStore = useLivestreamStore;
6
- const react_1 = require("react");
7
- const zustand_1 = require("zustand");
8
- const context_1 = require("./context");
9
- const websocket_consumer_1 = require("./websocket-consumer");
10
- const makeLivestreamStore = () => {
11
- return (0, zustand_1.createStore)()((set) => ({
12
- profile: null,
13
- chatIndex: {},
14
- chat: [],
15
- livestream: null,
16
- viewers: null,
17
- pendingHides: [],
18
- segment: null,
19
- renditions: [],
20
- replyToMessage: null,
21
- streamKey: null,
22
- setStreamKey: (sk) => set({ streamKey: sk }),
23
- authors: {},
24
- recentSegments: [],
25
- problems: [],
26
- }));
27
- };
28
- exports.makeLivestreamStore = makeLivestreamStore;
29
- function getStoreFromContext() {
30
- const context = (0, react_1.useContext)(context_1.LivestreamContext);
31
- if (!context) {
32
- throw new Error("useLivestreamStore must be used within a LivestreamProvider");
33
- }
34
- return context.store;
35
- }
36
- function useLivestreamStore(selector) {
37
- const store = getStoreFromContext();
38
- return (0, zustand_1.useStore)(store, selector);
39
- }
40
- const useHandleWebsocketMessages = () => {
41
- const store = getStoreFromContext();
42
- return (messages) => {
43
- store.setState((state) => (0, websocket_consumer_1.handleWebSocketMessages)(state, messages));
44
- };
45
- };
46
- exports.useHandleWebsocketMessages = useHandleWebsocketMessages;
47
- const useChat = () => useLivestreamStore((x) => x.chat);
48
- exports.useChat = useChat;
49
- const useProfile = () => useLivestreamStore((x) => x.profile);
50
- exports.useProfile = useProfile;
51
- const useViewers = () => useLivestreamStore((x) => x.viewers);
52
- exports.useViewers = useViewers;
53
- const useLivestream = () => useLivestreamStore((x) => x.livestream);
54
- exports.useLivestream = useLivestream;
55
- const useSegment = () => useLivestreamStore((x) => x.segment);
56
- exports.useSegment = useSegment;
57
- const useRenditions = () => useLivestreamStore((x) => x.renditions);
58
- exports.useRenditions = useRenditions;
@@ -1,76 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findProblems = void 0;
4
- const VARIANCE_THRESHOLD = 0.5;
5
- const DURATION_THRESHOLD = 5000000000; // 5s in ns
6
- const detectVariableSegmentLength = (segments) => {
7
- if (segments.length < 3) {
8
- // Need at least 3 segments to detect variability
9
- return { variable: false, duration: false };
10
- }
11
- const durations = segments
12
- .map((segment) => segment.duration)
13
- .filter((duration) => duration !== undefined && duration > 0);
14
- if (durations.length < 3) {
15
- return { variable: false, duration: false };
16
- }
17
- // Calculate mean
18
- const mean = durations.reduce((sum, duration) => sum + duration, 0) /
19
- durations.length;
20
- // Calculate standard deviation
21
- const variance = durations.reduce((sum, duration) => {
22
- const diff = duration - mean;
23
- return sum + diff * diff;
24
- }, 0) / durations.length;
25
- const stdDev = Math.sqrt(variance);
26
- // Calculate coefficient of variation (CV)
27
- const cv = stdDev / mean;
28
- // CV > 0.5 indicates high variability
29
- // This threshold can be adjusted based on testing
30
- return {
31
- variable: cv > VARIANCE_THRESHOLD,
32
- duration: mean > DURATION_THRESHOLD,
33
- };
34
- };
35
- const findProblems = (segments) => {
36
- const problems = [];
37
- let hasBFrames = false;
38
- for (const segment of segments) {
39
- const video = segment.video?.[0];
40
- if (!video) {
41
- // i mean yes this is a problem but it can't happen yet
42
- continue;
43
- }
44
- if (video.bframes === true) {
45
- hasBFrames = true;
46
- break;
47
- }
48
- }
49
- if (hasBFrames) {
50
- problems.push({
51
- code: "bframes",
52
- message: "Your stream contains B-Frames, which are not supported in Streamplace. Your stream will stutter.",
53
- severity: "error",
54
- link: "https://stream.place/docs/guides/start-streaming/obs/#obs-configuration",
55
- });
56
- }
57
- const { variable, duration } = detectVariableSegmentLength(segments);
58
- if (variable) {
59
- problems.push({
60
- code: "variable_segment_length",
61
- message: "Your stream contains variable segment lengths, which may cause playback issues.",
62
- severity: "warning",
63
- link: "https://stream.place/docs/guides/start-streaming/obs/#obs-configuration",
64
- });
65
- }
66
- if (duration) {
67
- problems.push({
68
- code: "long_segments",
69
- message: "Your stream contains long segments (>5s). This will work fine, but increases the delay of the livestream.",
70
- severity: "warning",
71
- link: "https://stream.place/docs/guides/start-streaming/obs/#obs-configuration",
72
- });
73
- }
74
- return problems;
75
- };
76
- exports.findProblems = findProblems;