@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,314 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChatBox = ChatBox;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const react_1 = tslib_1.__importDefault(require("@emoji-mart/react"));
7
- const lucide_react_native_1 = require("lucide-react-native");
8
- const react_2 = require("react");
9
- const react_native_1 = require("react-native");
10
- const __1 = require("../../");
11
- const atoms_1 = require("../../lib/theme/atoms");
12
- const xrpc_1 = require("../../streamplace-store/xrpc");
13
- const textarea_1 = require("../ui/textarea");
14
- const chat_message_1 = require("./chat-message");
15
- const emoji_suggestions_1 = require("./emoji-suggestions");
16
- const mention_suggestions_1 = require("./mention-suggestions");
17
- const COOL_EMOJI_LIST = [
18
- ..."😀🥸😍😘😁🥸😆🥸😜🥸😂😅🥸🙂🤫😱🥸🤣😗😄🥸😎🤓😲😯😰🥸😥🥸😣🥸😞😓🥸😩😩🥸😤🥱",
19
- ];
20
- function ChatBox({ isPopout, chatBoxStyle, emojiData, setIsChatVisible, }) {
21
- const [submitting, setSubmitting] = (0, react_2.useState)(false);
22
- const [message, setMessage] = (0, react_2.useState)("");
23
- const [showSuggestions, setShowSuggestions] = (0, react_2.useState)(false);
24
- const [showEmojiSuggestions, setShowEmojiSuggestions] = (0, react_2.useState)(false);
25
- const [showEmojiSelector, setShowEmojiSelector] = (0, react_2.useState)(false);
26
- const [emojiIconIndex, setEmojiIconIndex] = (0, react_2.useState)(Math.floor(Math.random() * COOL_EMOJI_LIST.length));
27
- const [highlightedIndex, setHighlightedIndex] = (0, react_2.useState)(0);
28
- const [filteredAuthors, setFilteredAuthors] = (0, react_2.useState)(new Map());
29
- const [filteredEmojis, setFilteredEmojis] = (0, react_2.useState)([]);
30
- let linfo = (0, __1.useLivestream)();
31
- const chat = (0, __1.useChat)();
32
- const createChatMessage = (0, __1.useCreateChatMessage)();
33
- const replyTo = (0, __1.useReplyToMessage)();
34
- const setReplyToMessage = (0, __1.useSetReplyToMessage)();
35
- const textAreaRef = (0, react_2.useRef)(null);
36
- // are we logged in?
37
- let agent = (0, xrpc_1.usePDSAgent)();
38
- if (!agent?.did) {
39
- (0, jsx_runtime_1.jsx)(__1.View, { style: [atoms_1.layout.flex.row, atoms_1.layout.flex.alignCenter, atoms_1.gap.all[2]], children: (0, jsx_runtime_1.jsx)(__1.Text, { children: "Log in to chat." }) });
40
- }
41
- const authors = (0, react_2.useMemo)(() => {
42
- if (!chat)
43
- return null;
44
- return chat.reduce((acc, msg) => {
45
- acc.set(msg.author.handle, msg.chatProfile);
46
- return acc;
47
- }, new Map());
48
- }, [chat]);
49
- const handleMentionSelect = (handle) => {
50
- const beforeAt = message.slice(0, message.lastIndexOf("@"));
51
- setMessage(`${beforeAt}@${handle} `);
52
- setShowSuggestions(false);
53
- };
54
- const handleEmojiSelect = (emoji) => {
55
- const beforeColon = message.slice(0, message.lastIndexOf(":"));
56
- setMessage(`${beforeColon}${emoji.skins[0]?.native} `);
57
- setShowEmojiSuggestions(false);
58
- };
59
- const updateSuggestions = (text) => {
60
- // Handle mentions
61
- const atIndex = text.lastIndexOf("@");
62
- if (atIndex !== -1 && authors) {
63
- const searchText = text.slice(atIndex + 1).toLowerCase();
64
- const filteredAuthorsMap = new Map(Array.from(authors.entries()).filter(([handle]) => handle.toLowerCase().includes(searchText)));
65
- setFilteredAuthors(filteredAuthorsMap);
66
- setHighlightedIndex(0);
67
- setShowSuggestions(filteredAuthorsMap.size > 0);
68
- setShowEmojiSuggestions(false);
69
- }
70
- else {
71
- setShowSuggestions(false);
72
- }
73
- const colonIndex = text.lastIndexOf(":");
74
- if (colonIndex !== -1) {
75
- const searchText = text.slice(colonIndex + 1).toLowerCase();
76
- if (searchText.length > 0) {
77
- const aliasMatches = Object.entries(emojiData.aliases)
78
- .map(([alias, emojiId]) => {
79
- const aliasLower = alias.toLowerCase();
80
- if (aliasLower === searchText) {
81
- return { emojiId, alias, matchType: 0, index: 0 };
82
- }
83
- else if (aliasLower.startsWith(searchText)) {
84
- return { emojiId, alias, matchType: 1, index: 0 };
85
- }
86
- else if (aliasLower.includes(searchText)) {
87
- return {
88
- emojiId,
89
- alias,
90
- matchType: 2,
91
- index: aliasLower.indexOf(searchText),
92
- }; // includes
93
- }
94
- return null;
95
- })
96
- .filter(Boolean);
97
- // Map emojiId to best alias match info
98
- const bestAliasMatch = {};
99
- for (const match of aliasMatches) {
100
- if (!match)
101
- continue;
102
- const prev = bestAliasMatch[match.emojiId];
103
- if (!prev ||
104
- match?.matchType < prev.matchType ||
105
- (match.matchType === prev.matchType && match.index < prev.index)) {
106
- bestAliasMatch[match.emojiId] = match;
107
- }
108
- }
109
- // Collect all matching emojis by id, name, keywords, or alias
110
- const allEmojis = Object.values(emojiData.emojis);
111
- const filtered = allEmojis
112
- .map((emoji) => {
113
- // Check alias match
114
- const aliasMatch = bestAliasMatch[emoji.id];
115
- if (aliasMatch) {
116
- return {
117
- emoji,
118
- sort: [aliasMatch.matchType, aliasMatch.index, 0],
119
- };
120
- }
121
- // Check id, name, keywords
122
- if (emoji.id.toLowerCase() === searchText) {
123
- return { emoji, sort: [3, 0, 0] }; // exact id
124
- }
125
- if (emoji.id.toLowerCase().startsWith(searchText)) {
126
- return { emoji, sort: [4, 0, 0] }; // startsWith id
127
- }
128
- if (emoji.id.toLowerCase().includes(searchText)) {
129
- return {
130
- emoji,
131
- sort: [5, emoji.id.toLowerCase().indexOf(searchText), 0],
132
- }; // includes id
133
- }
134
- if (emoji.name.toLowerCase().includes(searchText)) {
135
- return {
136
- emoji,
137
- sort: [6, emoji.name.toLowerCase().indexOf(searchText), 0],
138
- };
139
- }
140
- if (emoji.keywords &&
141
- emoji.keywords.some((keyword) => keyword.toLowerCase().includes(searchText))) {
142
- return { emoji, sort: [7, 0, 0] };
143
- }
144
- return null;
145
- })
146
- .filter(Boolean)
147
- // Remove duplicates by emoji id (keep best match)
148
- .reduce((acc, curr) => {
149
- if (!acc.find((e) => e.emoji.id === curr.emoji.id)) {
150
- acc.push(curr);
151
- }
152
- return acc;
153
- }, [])
154
- // Sort by alias match type, then position, then fallback
155
- .sort((a, b) => {
156
- for (let i = 0; i < a.sort.length; ++i) {
157
- if (a.sort[i] !== b.sort[i])
158
- return a.sort[i] - b.sort[i];
159
- }
160
- return 0;
161
- })
162
- .slice(0, 10) // Limit to 10 results
163
- .map((entry) => entry.emoji);
164
- setFilteredEmojis(filtered);
165
- setHighlightedIndex(0);
166
- setShowEmojiSuggestions(filtered.length > 0);
167
- setShowSuggestions(false);
168
- }
169
- else {
170
- setShowEmojiSuggestions(false);
171
- }
172
- }
173
- else {
174
- setShowEmojiSuggestions(false);
175
- }
176
- // If neither mention nor emoji, hide all suggestions
177
- if (atIndex === -1 && colonIndex === -1) {
178
- setShowSuggestions(false);
179
- setShowEmojiSuggestions(false);
180
- }
181
- };
182
- const submit = () => {
183
- if (!message.trim())
184
- return;
185
- setMessage("");
186
- setReplyToMessage(null);
187
- setSubmitting(true);
188
- createChatMessage({
189
- text: message,
190
- reply: replyTo || undefined,
191
- });
192
- setSubmitting(false);
193
- // if we press "send" button, we want the same action as pressing "Enter"
194
- // if we're already focused no need to do extra work
195
- if (textAreaRef.current && !textAreaRef.current.isFocused()) {
196
- textAreaRef.current.focus();
197
- requestAnimationFrame(() => {
198
- textAreaRef.current?.focus();
199
- });
200
- }
201
- };
202
- (0, react_2.useEffect)(() => {
203
- if (replyTo && textAreaRef.current) {
204
- textAreaRef.current.focus();
205
- }
206
- }, [replyTo]);
207
- return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.layout.flex.column, atoms_1.flex.shrink[1], atoms_1.gap.all[2]], children: [replyTo && ((0, jsx_runtime_1.jsxs)(__1.View, { style: [
208
- atoms_1.layout.flex.row,
209
- atoms_1.layout.flex.alignCenter,
210
- atoms_1.layout.flex.spaceBetween,
211
- atoms_1.pl[2],
212
- atoms_1.pr[6],
213
- atoms_1.mr[6],
214
- atoms_1.mb[2],
215
- atoms_1.py[1],
216
- atoms_1.bg.gray[800],
217
- { borderRadius: 16 },
218
- ], children: [(0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: replyTo, showReply: false, userCache: authors || new Map() }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: () => setReplyToMessage(null), children: (0, jsx_runtime_1.jsx)(__1.View, { style: [
219
- atoms_1.layout.flex.row,
220
- atoms_1.layout.flex.alignCenter,
221
- atoms_1.layout.flex.justifyCenter,
222
- atoms_1.h[12],
223
- atoms_1.w[12],
224
- atoms_1.bg.gray[600],
225
- { borderRadius: 999 },
226
- ], children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.X, { size: 24 }) }) })] })), showEmojiSelector && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: {
227
- position: "absolute",
228
- top: 0,
229
- left: 0,
230
- right: 0,
231
- bottom: 0,
232
- zIndex: 200,
233
- }, onPress: () => setShowEmojiSelector(false) }), (0, jsx_runtime_1.jsx)(__1.View, { style: {
234
- position: "absolute",
235
- bottom: "100%",
236
- left: 0,
237
- zIndex: 2001,
238
- }, children: (0, jsx_runtime_1.jsx)(react_1.default, { data: emojiData, onEmojiSelect: (e) => setMessage(message + e.native) }) })] })), (0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.layout.flex.row, atoms_1.layout.flex.alignCenter, atoms_1.gap.all[2]], children: [(0, jsx_runtime_1.jsx)(textarea_1.Textarea, { ref: textAreaRef, numberOfLines: 1, value: message, enterKeyHint: "send", onSubmitEditing: (e) => {
239
- e.preventDefault();
240
- submit();
241
- }, multiline: false, onChangeText: (text) => {
242
- setMessage(text);
243
- updateSuggestions(text);
244
- }, onKeyPress: (k) => {
245
- if (k.nativeEvent.key === "Enter") {
246
- if (showSuggestions) {
247
- k.preventDefault();
248
- const handles = Array.from(filteredAuthors.keys());
249
- if (handles.length > 0) {
250
- handleMentionSelect(handles[highlightedIndex]);
251
- }
252
- }
253
- else if (showEmojiSuggestions) {
254
- k.preventDefault();
255
- if (filteredEmojis.length > 0) {
256
- handleEmojiSelect(filteredEmojis[highlightedIndex]);
257
- }
258
- }
259
- else {
260
- k.preventDefault();
261
- submit();
262
- }
263
- }
264
- else if (k.nativeEvent.key === "ArrowUp") {
265
- if (showSuggestions || showEmojiSuggestions) {
266
- k.preventDefault();
267
- setHighlightedIndex((prev) => Math.max(prev - 1, 0));
268
- }
269
- }
270
- else if (k.nativeEvent.key === "ArrowDown") {
271
- if (showSuggestions) {
272
- k.preventDefault();
273
- setHighlightedIndex((prev) => Math.min(prev + 1, Array.from(filteredAuthors.keys()).length - 1));
274
- }
275
- else if (showEmojiSuggestions) {
276
- k.preventDefault();
277
- setHighlightedIndex((prev) => Math.min(prev + 1, filteredEmojis.length - 1));
278
- }
279
- }
280
- else if (k.nativeEvent.key === "Escape") {
281
- if (showSuggestions || showEmojiSuggestions) {
282
- k.preventDefault();
283
- setShowSuggestions(false);
284
- setShowEmojiSuggestions(false);
285
- }
286
- }
287
- }, style: [chatBoxStyle],
288
- // "submit" won't blur on enter
289
- submitBehavior: "submit", placeholder: "Type a message..." }), (0, jsx_runtime_1.jsx)(__1.Button, { disabled: submitting, variant: "secondary", style: { borderRadius: 16, height: 36, minWidth: 80 }, onPress: submit, children: submitting ? (0, jsx_runtime_1.jsx)(__1.Loader, {}) : "Send" })] }), showSuggestions && ((0, jsx_runtime_1.jsx)(mention_suggestions_1.MentionSuggestions, { authors: filteredAuthors || new Map(), highlightedIndex: highlightedIndex, onSelect: handleMentionSelect })), showEmojiSuggestions && ((0, jsx_runtime_1.jsx)(emoji_suggestions_1.EmojiSuggestions, { emojis: filteredEmojis, highlightedIndex: highlightedIndex, onSelect: handleEmojiSelect })), react_native_1.Platform.OS === "web" && ((0, jsx_runtime_1.jsxs)(__1.View, { style: [
290
- atoms_1.layout.flex.row,
291
- atoms_1.mb[2],
292
- atoms_1.gap.all[2],
293
- { justifyContent: "flex-end" },
294
- ], children: [(0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => {
295
- // if the last character is not @, add it
296
- !message.endsWith("@") && setMessage(message + "@");
297
- // get all the text after the last @
298
- const atIndex = message.lastIndexOf("@");
299
- const searchText = message.slice(atIndex + 1).toLowerCase();
300
- updateSuggestions(searchText);
301
- setShowSuggestions(true);
302
- // focus the textarea
303
- textAreaRef.current?.focus();
304
- }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.AtSignIcon, { size: 20, color: "white" }) }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onHoverOut: () => {
305
- setEmojiIconIndex(Math.floor(Math.random() * COOL_EMOJI_LIST.length));
306
- }, children: (0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => setShowEmojiSelector(!showEmojiSelector), children: (0, jsx_runtime_1.jsx)(__1.Text, { children: COOL_EMOJI_LIST[emojiIconIndex] }) }) }), !isPopout && ((0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => {
307
- if (!linfo)
308
- return;
309
- const u = new URL(window.location.href);
310
- u.pathname = `/chat-popout/${linfo?.author?.did}`;
311
- window.open(u.toString(), "_blank", "popup=true");
312
- setIsChatVisible?.(false);
313
- }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.ExternalLink, { size: 16 }) }))] }))] }));
314
- }
@@ -1,87 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RenderChatMessage = void 0;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
6
- const react_native_1 = require("react-native");
7
- const facet_1 = require("../../lib/facet");
8
- const atoms_1 = require("../../lib/theme/atoms");
9
- const ui_1 = require("../ui");
10
- const livestream_store_1 = require("../../livestream-store");
11
- const text_1 = require("../ui/text");
12
- const getRgbColor = (color) => color ? `rgb(${color.red}, ${color.green}, ${color.blue})` : ui_1.colors.gray[500];
13
- const segmentedObject = (obj, index, userCache) => {
14
- if (obj.features && obj.features.length > 0) {
15
- let ftr = obj.features[0];
16
- // afaik there shouldn't be a case where facets overlap, at least currently
17
- if (ftr.$type === "app.bsky.richtext.facet#link") {
18
- let linkftr = ftr;
19
- return ((0, jsx_runtime_1.jsx)(text_1.Text, { style: [{ color: ui_1.atoms.colors.ios.systemBlue, cursor: "pointer" }], onPress: () => react_native_1.Linking.openURL(linkftr.uri || ""), children: obj.text }, `mention-${index}`));
20
- }
21
- else if (ftr.$type === "app.bsky.richtext.facet#mention") {
22
- let mtnftr = ftr;
23
- const profile = userCache?.[mtnftr.did];
24
- return ((0, jsx_runtime_1.jsx)(text_1.Text, { style: [
25
- {
26
- cursor: "pointer",
27
- color: getRgbColor(profile?.color),
28
- },
29
- ], onPress: () => react_native_1.Linking.openURL(`https://bsky.app/profile/${mtnftr.did || ""}`), children: obj.text }, `mention-${index}`));
30
- }
31
- }
32
- else {
33
- return (0, jsx_runtime_1.jsx)(text_1.Text, { children: obj.text }, `text-${index}`);
34
- }
35
- };
36
- const RichTextMessage = ({ text, facets, }) => {
37
- if (!facets?.length)
38
- return (0, jsx_runtime_1.jsx)(text_1.Text, { children: text });
39
- const userCache = (0, livestream_store_1.useLivestreamStore)((state) => state.authors);
40
- let segs = (0, facet_1.segmentize)(text, facets);
41
- return segs.map((seg, i) => segmentedObject(seg, i, userCache));
42
- };
43
- exports.RenderChatMessage = (0, react_1.memo)(function RenderChatMessage({ item, showReply = true, showTime = true, }) {
44
- const formatTime = (0, react_1.useCallback)((dateString) => {
45
- return new Date(dateString).toLocaleString(undefined, {
46
- hour: "2-digit",
47
- minute: "2-digit",
48
- hour12: false,
49
- });
50
- }, []);
51
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [item.replyTo && showReply && ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
52
- atoms_1.gap.all[2],
53
- ui_1.layout.flex.row,
54
- { minWidth: 0, maxWidth: "100%" },
55
- atoms_1.borders.left.width.medium,
56
- atoms_1.borders.left.color.gray[700],
57
- atoms_1.ml[4],
58
- atoms_1.pl[4],
59
- atoms_1.opacity[80],
60
- ], children: (0, jsx_runtime_1.jsxs)(text_1.Text, { numberOfLines: 1, style: [
61
- atoms_1.flex.shrink[1],
62
- atoms_1.mr[4],
63
- { minWidth: 0, overflow: "hidden" },
64
- ], children: [(0, jsx_runtime_1.jsxs)(text_1.Text, { style: {
65
- color: getRgbColor(item.replyTo.chatProfile.color),
66
- fontWeight: "thin",
67
- }, children: ["@", item.replyTo.author.handle] }), " ", (0, jsx_runtime_1.jsx)(text_1.Text, { style: {
68
- color: ui_1.colors.gray[300],
69
- fontStyle: "italic",
70
- }, children: item.replyTo.record.text })] }) })), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
71
- atoms_1.gap.all[2],
72
- ui_1.layout.flex.row,
73
- { minWidth: 0, maxWidth: "100%" },
74
- ], children: [showTime && ((0, jsx_runtime_1.jsx)(text_1.Text, { style: {
75
- fontVariant: ["tabular-nums"],
76
- color: ui_1.colors.gray[400],
77
- }, children: formatTime(item.record.createdAt) })), (0, jsx_runtime_1.jsxs)(text_1.Text, { weight: "bold", color: "default", style: [atoms_1.flex.shrink[1], { minWidth: 0, overflow: "hidden" }], children: [(0, jsx_runtime_1.jsxs)(text_1.Text, { style: [
78
- {
79
- cursor: "pointer",
80
- color: getRgbColor(item.chatProfile?.color),
81
- },
82
- ], children: ["@", item.author.handle] }), ":", " ", (0, jsx_runtime_1.jsx)(RichTextMessage, { text: item.record.text, facets: item.record.facets || [] })] })] })] }));
83
- }, (prevProps, nextProps) => {
84
- return (prevProps.item.author.handle === nextProps.item.author.handle &&
85
- prevProps.item.record.text === nextProps.item.record.text &&
86
- prevProps.item.uri === nextProps.item.uri);
87
- });
@@ -1,149 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Chat = Chat;
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 react_1 = require("react");
8
- const react_native_1 = require("react-native");
9
- const ReanimatedSwipeable_1 = tslib_1.__importDefault(require("react-native-gesture-handler/ReanimatedSwipeable"));
10
- const react_native_reanimated_1 = tslib_1.__importStar(require("react-native-reanimated"));
11
- const __1 = require("../../");
12
- const atoms_1 = require("../../lib/theme/atoms");
13
- const chat_message_1 = require("./chat-message");
14
- const mod_view_1 = require("./mod-view");
15
- function RightAction(prog, drag) {
16
- const styleAnimation = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
17
- return {
18
- transform: [{ translateX: drag.value + 25 }],
19
- };
20
- });
21
- return ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: [styleAnimation], children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Reply, { color: "white" }) }));
22
- }
23
- function LeftAction(prog, drag) {
24
- const styleAnimation = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
25
- return {
26
- transform: [{ translateX: drag.value - 25 }],
27
- };
28
- });
29
- return ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: [styleAnimation], children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.ShieldEllipsis, { color: "white" }) }));
30
- }
31
- // ios/android, 25, else 100 msgs
32
- const SHOWN_MSGS = react_native_1.Platform.OS === "ios" || react_native_1.Platform.OS === "android" ? 25 : 100;
33
- const keyExtractor = (item, index) => {
34
- return `${item.uri}`;
35
- };
36
- // Actions bar for larger screens
37
- const ActionsBar = (0, react_1.memo)(({ item, visible, hoverTimeoutRef, }) => {
38
- const setReply = (0, __1.useSetReplyToMessage)();
39
- const setModMsg = (0, __1.usePlayerStore)((state) => state.setModMessage);
40
- if (!visible)
41
- return null;
42
- return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [
43
- {
44
- position: "absolute",
45
- top: -14,
46
- right: 8,
47
- flexDirection: "row",
48
- backgroundColor: "rgba(180,180,180, 0.5)",
49
- borderRadius: 6,
50
- borderWidth: 1,
51
- padding: 1,
52
- gap: 4,
53
- zIndex: 10,
54
- maxWidth: 120,
55
- flexShrink: 0,
56
- },
57
- ], children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: () => setReply(item), style: [
58
- {
59
- padding: 6,
60
- borderRadius: 4,
61
- backgroundColor: "rgba(255, 255, 255, 0.1)",
62
- },
63
- ], onHoverIn: () => {
64
- // Keep the actions bar visible when hovering over it
65
- if (hoverTimeoutRef.current) {
66
- clearTimeout(hoverTimeoutRef.current);
67
- hoverTimeoutRef.current = null;
68
- }
69
- }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Reply, { color: "white", size: 16 }) }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: () => setModMsg(item), style: [
70
- {
71
- padding: 6,
72
- borderRadius: 4,
73
- backgroundColor: "rgba(255, 255, 255, 0.1)",
74
- },
75
- ], onHoverIn: () => {
76
- // Keep the actions bar visible when hovering over it
77
- if (hoverTimeoutRef.current) {
78
- clearTimeout(hoverTimeoutRef.current);
79
- hoverTimeoutRef.current = null;
80
- }
81
- }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Ellipsis, { color: "white", size: 16 }) })] }));
82
- });
83
- const ChatLine = (0, react_1.memo)(({ item, canModerate, }) => {
84
- const setReply = (0, __1.useSetReplyToMessage)();
85
- const setModMsg = (0, __1.usePlayerStore)((state) => state.setModMessage);
86
- const swipeableRef = (0, react_1.useRef)(null);
87
- const [isHovered, setIsHovered] = (0, react_1.useState)(false);
88
- const hoverTimeoutRef = (0, react_1.useRef)(null);
89
- const handleHoverIn = () => {
90
- if (hoverTimeoutRef.current) {
91
- clearTimeout(hoverTimeoutRef.current);
92
- hoverTimeoutRef.current = null;
93
- }
94
- setIsHovered(true);
95
- };
96
- const handleHoverOut = () => {
97
- hoverTimeoutRef.current = setTimeout(() => {
98
- setIsHovered(false);
99
- }, 50);
100
- };
101
- (0, react_1.useEffect)(() => {
102
- return () => {
103
- if (hoverTimeoutRef.current) {
104
- clearTimeout(hoverTimeoutRef.current);
105
- }
106
- };
107
- }, []);
108
- if (item.author.did === "did:sys:system") {
109
- return ((0, jsx_runtime_1.jsx)(__1.SystemMessage, { timestamp: new Date(item.record.createdAt), title: item.record.text }));
110
- }
111
- if (react_native_1.Platform.OS === "web") {
112
- return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [
113
- atoms_1.py[1],
114
- atoms_1.px[2],
115
- {
116
- position: "relative",
117
- borderRadius: 8,
118
- minWidth: 0,
119
- maxWidth: "100%",
120
- },
121
- isHovered && atoms_1.bg.gray[950],
122
- ], onPointerEnter: handleHoverIn, onPointerLeave: handleHoverOut, children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [{ minWidth: 0, maxWidth: "100%" }], children: (0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: item }) }), (0, jsx_runtime_1.jsx)(ActionsBar, { item: item, visible: isHovered, hoverTimeoutRef: hoverTimeoutRef })] }));
123
- }
124
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(ReanimatedSwipeable_1.default, { containerStyle: [atoms_1.py[1]], friction: 2, enableTrackpadTwoFingerGesture: true, rightThreshold: 40, leftThreshold: 40, renderRightActions: react_native_1.Platform.OS === "android" ? undefined : RightAction, renderLeftActions: react_native_1.Platform.OS === "android" ? undefined : LeftAction, overshootFriction: 9, ref: (ref) => {
125
- swipeableRef.current = ref;
126
- }, onSwipeableOpen: (r) => {
127
- if (r === (react_native_1.Platform.OS === "android" ? "right" : "left")) {
128
- setReply(item);
129
- }
130
- if (r === (react_native_1.Platform.OS === "android" ? "left" : "right")) {
131
- setModMsg(item);
132
- }
133
- // close this swipeable
134
- const swipeable = swipeableRef.current;
135
- if (swipeable) {
136
- swipeable.close();
137
- }
138
- }, children: (0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: item }) }) }));
139
- });
140
- function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, canModerate = false, ...props }) {
141
- const chat = (0, __1.useChat)();
142
- if (!chat)
143
- return ((0, jsx_runtime_1.jsx)(__1.View, { style: [atoms_1.flex.shrink[1], { minWidth: 0, maxWidth: "100%" }], children: (0, jsx_runtime_1.jsx)(__1.Text, { children: "Loading chaat..." }) }));
144
- return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.flex.shrink[1], { minWidth: 0, maxWidth: "100%" }].concat(propsStyle || []), children: [(0, jsx_runtime_1.jsx)(react_native_1.FlatList, { style: [
145
- atoms_1.flex.grow[1],
146
- atoms_1.flex.shrink[1],
147
- { minWidth: 0, maxWidth: "100%" },
148
- ], data: chat.slice(0, shownMessages), inverted: true, keyExtractor: keyExtractor, renderItem: ({ item, index }) => ((0, jsx_runtime_1.jsx)(ChatLine, { item: item, canModerate: canModerate })), removeClippedSubviews: true, maxToRenderPerBatch: 10, initialNumToRender: 10, updateCellsBatchingPeriod: 50 }), (0, jsx_runtime_1.jsx)(mod_view_1.ModView, {})] }));
149
- }
@@ -1,35 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EmojiSuggestions = EmojiSuggestions;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_native_1 = require("react-native");
6
- const __1 = require("../..");
7
- const atoms_1 = require("../../lib/theme/atoms");
8
- function EmojiSuggestions({ emojis, onSelect, highlightedIndex, }) {
9
- if (!emojis || emojis.length === 0) {
10
- return null;
11
- }
12
- return ((0, jsx_runtime_1.jsx)(__1.View, { style: [
13
- atoms_1.bg.gray[800],
14
- atoms_1.layout.position.absolute,
15
- atoms_1.left[0],
16
- atoms_1.right[0],
17
- atoms_1.zIndex[50],
18
- {
19
- bottom: "100%",
20
- borderRadius: 8,
21
- boxShadow: "0px 4px 6px rgba(0, 0, 0, 0.1)",
22
- maxHeight: 200,
23
- overflow: "auto",
24
- },
25
- ], children: emojis.map((emoji, index) => ((0, jsx_runtime_1.jsxs)(react_native_1.Pressable, { onPress: () => onSelect(emoji), style: [
26
- {
27
- padding: 8,
28
- flexDirection: "row",
29
- alignItems: "center",
30
- backgroundColor: index === highlightedIndex
31
- ? "rgba(255, 255, 255, 0.1)"
32
- : "transparent",
33
- },
34
- ], children: [(0, jsx_runtime_1.jsx)(__1.Text, { style: { fontSize: 16, marginRight: 8 }, children: emoji.skins[0]?.native }), (0, jsx_runtime_1.jsxs)(__1.Text, { style: { color: "white", fontSize: 14 }, children: [(0, jsx_runtime_1.jsxs)(__1.Code, { style: [atoms_1.bg.gray[950]], children: [":", emoji.id, ":"] }), " ", emoji.name] })] }, emoji.id))) }));
35
- }
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MentionSuggestions = MentionSuggestions;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_native_1 = require("react-native");
6
- const __1 = require("../..");
7
- const atoms_1 = require("../../lib/theme/atoms");
8
- function MentionSuggestions({ authors, onSelect, highlightedIndex, }) {
9
- if (!authors || authors.size === 0) {
10
- return null; // No authors to display
11
- }
12
- const authorHandles = Array.from(authors.keys());
13
- return ((0, jsx_runtime_1.jsx)(__1.View, { style: [
14
- atoms_1.bg.gray[800],
15
- atoms_1.layout.position.absolute,
16
- atoms_1.left[0],
17
- atoms_1.right[0],
18
- atoms_1.zIndex[50],
19
- {
20
- bottom: "100%",
21
- borderRadius: 8,
22
- boxShadow: "0px 4px 6px rgba(0, 0, 0, 0.1)",
23
- },
24
- ], children: authorHandles.map((handle, index) => {
25
- let profile = authors.get(handle);
26
- return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: () => onSelect(handle), style: [
27
- {
28
- padding: 8,
29
- flexDirection: "row",
30
- alignItems: "center",
31
- backgroundColor: index === highlightedIndex
32
- ? "rgba(0, 0, 0, 0.1)"
33
- : "rgba(0, 0, 0, 0.5)",
34
- },
35
- ], children: (0, jsx_runtime_1.jsxs)(__1.Text, { style: {
36
- color: profile?.color
37
- ? `rgb(${profile.color.red}, ${profile.color.green}, ${profile.color.blue})`
38
- : "black",
39
- fontWeight: "bold",
40
- }, children: ["@", handle] }) }, handle));
41
- }) }));
42
- }