@streamplace/components 0.7.3 → 0.7.7

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 (85) hide show
  1. package/dist/components/chat/chat-box.js +212 -24
  2. package/dist/components/chat/chat-message.js +5 -5
  3. package/dist/components/chat/chat.js +83 -5
  4. package/dist/components/chat/emoji-suggestions.js +35 -0
  5. package/dist/components/chat/mod-view.js +59 -8
  6. package/dist/components/chat/system-message.js +19 -0
  7. package/dist/components/icons/bluesky-icon.js +9 -0
  8. package/dist/components/keep-awake.js +7 -0
  9. package/dist/components/keep-awake.native.js +16 -0
  10. package/dist/components/mobile-player/fullscreen.js +2 -1
  11. package/dist/components/mobile-player/fullscreen.native.js +3 -3
  12. package/dist/components/mobile-player/player.js +15 -30
  13. package/dist/components/mobile-player/ui/index.js +2 -1
  14. package/dist/components/mobile-player/ui/report-modal.js +90 -0
  15. package/dist/components/mobile-player/ui/{loading.js → streamer-loading-overlay.js} +1 -1
  16. package/dist/components/mobile-player/ui/viewer-context-menu.js +20 -1
  17. package/dist/components/mobile-player/ui/viewer-loading-overlay.js +49 -0
  18. package/dist/components/mobile-player/use-webrtc.js +7 -1
  19. package/dist/components/mobile-player/video-retry.js +29 -0
  20. package/dist/components/mobile-player/video.js +84 -9
  21. package/dist/components/mobile-player/video.native.js +24 -10
  22. package/dist/components/share/sharesheet.js +91 -0
  23. package/dist/components/ui/dialog.js +1 -1
  24. package/dist/components/ui/dropdown.js +6 -6
  25. package/dist/components/ui/index.js +2 -0
  26. package/dist/components/ui/primitives/modal.js +0 -1
  27. package/dist/components/ui/slider.js +5 -0
  28. package/dist/hooks/index.js +1 -0
  29. package/dist/hooks/usePointerDevice.js +71 -0
  30. package/dist/index.js +10 -3
  31. package/dist/lib/system-messages.js +101 -0
  32. package/dist/livestream-store/chat.js +111 -18
  33. package/dist/livestream-store/livestream-store.js +3 -0
  34. package/dist/livestream-store/problems.js +76 -0
  35. package/dist/livestream-store/websocket-consumer.js +39 -4
  36. package/dist/player-store/player-store.js +30 -4
  37. package/dist/streamplace-store/block.js +51 -12
  38. package/dist/ui/index.js +79 -0
  39. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  40. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/56540125 +0 -0
  41. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/67b1eb60 +0 -0
  42. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/7c275f90 +0 -0
  43. package/package.json +6 -2
  44. package/src/components/chat/chat-box.tsx +295 -25
  45. package/src/components/chat/chat-message.tsx +6 -7
  46. package/src/components/chat/chat.tsx +192 -41
  47. package/src/components/chat/emoji-suggestions.tsx +94 -0
  48. package/src/components/chat/mod-view.tsx +119 -40
  49. package/src/components/chat/system-message.tsx +38 -0
  50. package/src/components/icons/bluesky-icon.tsx +9 -0
  51. package/src/components/keep-awake.native.tsx +13 -0
  52. package/src/components/keep-awake.tsx +3 -0
  53. package/src/components/mobile-player/fullscreen.native.tsx +12 -3
  54. package/src/components/mobile-player/fullscreen.tsx +10 -3
  55. package/src/components/mobile-player/player.tsx +28 -36
  56. package/src/components/mobile-player/props.tsx +1 -0
  57. package/src/components/mobile-player/ui/index.ts +2 -1
  58. package/src/components/mobile-player/ui/report-modal.tsx +195 -0
  59. package/src/components/mobile-player/ui/{loading.tsx → streamer-loading-overlay.tsx} +1 -1
  60. package/src/components/mobile-player/ui/viewer-context-menu.tsx +31 -3
  61. package/src/components/mobile-player/ui/viewer-loading-overlay.tsx +66 -0
  62. package/src/components/mobile-player/use-webrtc.tsx +10 -2
  63. package/src/components/mobile-player/video-retry.tsx +28 -0
  64. package/src/components/mobile-player/video.native.tsx +24 -10
  65. package/src/components/mobile-player/video.tsx +100 -21
  66. package/src/components/share/sharesheet.tsx +185 -0
  67. package/src/components/ui/dialog.tsx +1 -1
  68. package/src/components/ui/dropdown.tsx +13 -13
  69. package/src/components/ui/index.ts +2 -0
  70. package/src/components/ui/primitives/modal.tsx +0 -1
  71. package/src/components/ui/slider.tsx +1 -0
  72. package/src/hooks/index.ts +1 -0
  73. package/src/hooks/usePointerDevice.ts +89 -0
  74. package/src/index.tsx +11 -2
  75. package/src/lib/system-messages.ts +135 -0
  76. package/src/livestream-store/chat.tsx +145 -17
  77. package/src/livestream-store/livestream-state.tsx +10 -0
  78. package/src/livestream-store/livestream-store.tsx +3 -0
  79. package/src/livestream-store/problems.tsx +96 -0
  80. package/src/livestream-store/websocket-consumer.tsx +44 -4
  81. package/src/player-store/player-state.tsx +21 -4
  82. package/src/player-store/player-store.tsx +38 -5
  83. package/src/streamplace-store/block.tsx +55 -13
  84. package/src/ui/index.ts +86 -0
  85. package/tsconfig.tsbuildinfo +1 -1
@@ -1,33 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ChatBox = ChatBox;
4
+ const tslib_1 = require("tslib");
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = tslib_1.__importDefault(require("@emoji-mart/react"));
5
7
  const lucide_react_native_1 = require("lucide-react-native");
6
- const react_1 = require("react");
8
+ const react_2 = require("react");
7
9
  const react_native_1 = require("react-native");
8
10
  const __1 = require("../../");
9
11
  const atoms_1 = require("../../lib/theme/atoms");
10
12
  const xrpc_1 = require("../../streamplace-store/xrpc");
11
13
  const textarea_1 = require("../ui/textarea");
12
14
  const chat_message_1 = require("./chat-message");
15
+ const emoji_suggestions_1 = require("./emoji-suggestions");
13
16
  const mention_suggestions_1 = require("./mention-suggestions");
14
- function ChatBox({ isPopout, chatBoxStyle, }) {
15
- const [submitting, setSubmitting] = (0, react_1.useState)(false);
16
- const [message, setMessage] = (0, react_1.useState)("");
17
- const [showSuggestions, setShowSuggestions] = (0, react_1.useState)(false);
18
- const [highlightedIndex, setHighlightedIndex] = (0, react_1.useState)(0);
19
- const [filteredAuthors, setFilteredAuthors] = (0, react_1.useState)(new Map());
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)();
20
31
  const chat = (0, __1.useChat)();
21
32
  const createChatMessage = (0, __1.useCreateChatMessage)();
22
33
  const replyTo = (0, __1.useReplyToMessage)();
23
34
  const setReplyToMessage = (0, __1.useSetReplyToMessage)();
24
- const textAreaRef = (0, react_1.useRef)(null);
35
+ const textAreaRef = (0, react_2.useRef)(null);
25
36
  // are we logged in?
26
37
  let agent = (0, xrpc_1.usePDSAgent)();
27
38
  if (!agent?.did) {
28
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." }) });
29
40
  }
30
- const authors = (0, react_1.useMemo)(() => {
41
+ const authors = (0, react_2.useMemo)(() => {
31
42
  if (!chat)
32
43
  return null;
33
44
  return chat.reduce((acc, msg) => {
@@ -40,17 +51,133 @@ function ChatBox({ isPopout, chatBoxStyle, }) {
40
51
  setMessage(`${beforeAt}@${handle} `);
41
52
  setShowSuggestions(false);
42
53
  };
54
+ const handleEmojiSelect = (emoji) => {
55
+ const beforeColon = message.slice(0, message.lastIndexOf(":"));
56
+ setMessage(`${beforeColon}${emoji.skins[0]?.native} `);
57
+ setShowEmojiSuggestions(false);
58
+ };
43
59
  const updateSuggestions = (text) => {
60
+ // Handle mentions
44
61
  const atIndex = text.lastIndexOf("@");
45
- if (atIndex === -1 || !authors) {
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 {
46
71
  setShowSuggestions(false);
47
- return;
48
72
  }
49
- const searchText = text.slice(atIndex + 1).toLowerCase();
50
- const filteredAuthorsMap = new Map(Array.from(authors.entries()).filter(([handle]) => handle.toLowerCase().includes(searchText)));
51
- setFilteredAuthors(filteredAuthorsMap);
52
- setHighlightedIndex(0);
53
- setShowSuggestions(filteredAuthorsMap.size > 0);
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
+ }
54
181
  };
55
182
  const submit = () => {
56
183
  if (!message.trim())
@@ -64,7 +191,7 @@ function ChatBox({ isPopout, chatBoxStyle, }) {
64
191
  });
65
192
  setSubmitting(false);
66
193
  };
67
- (0, react_1.useEffect)(() => {
194
+ (0, react_2.useEffect)(() => {
68
195
  if (replyTo && textAreaRef.current) {
69
196
  textAreaRef.current.focus();
70
197
  }
@@ -73,10 +200,11 @@ function ChatBox({ isPopout, chatBoxStyle, }) {
73
200
  atoms_1.layout.flex.row,
74
201
  atoms_1.layout.flex.alignCenter,
75
202
  atoms_1.layout.flex.spaceBetween,
76
- atoms_1.h[12],
77
203
  atoms_1.pl[2],
78
- atoms_1.pr[10],
204
+ atoms_1.pr[6],
205
+ atoms_1.mr[6],
79
206
  atoms_1.mb[2],
207
+ atoms_1.py[1],
80
208
  atoms_1.bg.gray[800],
81
209
  { borderRadius: 16 },
82
210
  ], 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: [
@@ -87,7 +215,19 @@ function ChatBox({ isPopout, chatBoxStyle, }) {
87
215
  atoms_1.w[12],
88
216
  atoms_1.bg.gray[600],
89
217
  { borderRadius: 999 },
90
- ], children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.X, { size: 24 }) }) })] })), (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: submit, multiline: false, onChangeText: (text) => {
218
+ ], 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: {
219
+ position: "absolute",
220
+ top: 0,
221
+ left: 0,
222
+ right: 0,
223
+ bottom: 0,
224
+ zIndex: 200,
225
+ }, onPress: () => setShowEmojiSelector(false) }), (0, jsx_runtime_1.jsx)(__1.View, { style: {
226
+ position: "absolute",
227
+ bottom: "100%",
228
+ left: 0,
229
+ zIndex: 2001,
230
+ }, 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: submit, multiline: false, onChangeText: (text) => {
91
231
  setMessage(text);
92
232
  updateSuggestions(text);
93
233
  }, onKeyPress: (k) => {
@@ -99,14 +239,62 @@ function ChatBox({ isPopout, chatBoxStyle, }) {
99
239
  handleMentionSelect(handles[highlightedIndex]);
100
240
  }
101
241
  }
102
- else
242
+ else if (showEmojiSuggestions) {
243
+ k.preventDefault();
244
+ if (filteredEmojis.length > 0) {
245
+ handleEmojiSelect(filteredEmojis[highlightedIndex]);
246
+ }
247
+ }
248
+ else {
103
249
  submit();
250
+ }
104
251
  }
105
252
  else if (k.nativeEvent.key === "ArrowUp") {
106
- setHighlightedIndex((prev) => Math.max(prev - 1, 0));
253
+ if (showSuggestions || showEmojiSuggestions) {
254
+ k.preventDefault();
255
+ setHighlightedIndex((prev) => Math.max(prev - 1, 0));
256
+ }
107
257
  }
108
258
  else if (k.nativeEvent.key === "ArrowDown") {
109
- setHighlightedIndex((prev) => Math.min(prev + 1, Array.from(filteredAuthors.keys()).length - 1));
259
+ if (showSuggestions) {
260
+ k.preventDefault();
261
+ setHighlightedIndex((prev) => Math.min(prev + 1, Array.from(filteredAuthors.keys()).length - 1));
262
+ }
263
+ else if (showEmojiSuggestions) {
264
+ k.preventDefault();
265
+ setHighlightedIndex((prev) => Math.min(prev + 1, filteredEmojis.length - 1));
266
+ }
110
267
  }
111
- }, style: [chatBoxStyle] }), (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 || [], highlightedIndex: highlightedIndex, onSelect: handleMentionSelect }))] }));
268
+ else if (k.nativeEvent.key === "Escape") {
269
+ if (showSuggestions || showEmojiSuggestions) {
270
+ k.preventDefault();
271
+ setShowSuggestions(false);
272
+ setShowEmojiSuggestions(false);
273
+ }
274
+ }
275
+ }, style: [chatBoxStyle] }), (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: [
276
+ atoms_1.layout.flex.row,
277
+ atoms_1.mb[2],
278
+ atoms_1.gap.all[2],
279
+ { justifyContent: "flex-end" },
280
+ ], children: [(0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => {
281
+ // if the last character is not @, add it
282
+ !message.endsWith("@") && setMessage(message + "@");
283
+ // get all the text after the last @
284
+ const atIndex = message.lastIndexOf("@");
285
+ const searchText = message.slice(atIndex + 1).toLowerCase();
286
+ updateSuggestions(searchText);
287
+ setShowSuggestions(true);
288
+ // focus the textarea
289
+ textAreaRef.current?.focus();
290
+ }, 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: () => {
291
+ setEmojiIconIndex(Math.floor(Math.random() * COOL_EMOJI_LIST.length));
292
+ }, 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: () => {
293
+ if (!linfo)
294
+ return;
295
+ const u = new URL(window.location.href);
296
+ u.pathname = `/chat-popout/${linfo?.author?.did}`;
297
+ window.open(u.toString(), "_blank", "popup=true");
298
+ setIsChatVisible?.(false);
299
+ }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.ExternalLink, { size: 16 }) }))] }))] }));
112
300
  }
@@ -9,7 +9,7 @@ const atoms_1 = require("../../lib/theme/atoms");
9
9
  const ui_1 = require("../ui");
10
10
  const livestream_store_1 = require("../../livestream-store");
11
11
  const text_1 = require("../ui/text");
12
- const getRgbColor = (color) => color ? `rgb(${color.red}, ${color.green}, ${color.blue})` : "$accentColor";
12
+ const getRgbColor = (color) => color ? `rgb(${color.red}, ${color.green}, ${color.blue})` : ui_1.colors.gray[500];
13
13
  const segmentedObject = (obj, index, userCache) => {
14
14
  if (obj.features && obj.features.length > 0) {
15
15
  let ftr = obj.features[0];
@@ -21,7 +21,6 @@ const segmentedObject = (obj, index, userCache) => {
21
21
  else if (ftr.$type === "app.bsky.richtext.facet#mention") {
22
22
  let mtnftr = ftr;
23
23
  const profile = userCache?.[mtnftr.did];
24
- console.log(profile, mtnftr.did, userCache);
25
24
  return ((0, jsx_runtime_1.jsx)(text_1.Text, { style: [
26
25
  {
27
26
  cursor: "pointer",
@@ -62,11 +61,11 @@ exports.RenderChatMessage = (0, react_1.memo)(function RenderChatMessage({ item,
62
61
  color: getRgbColor(item.replyTo.chatProfile.color),
63
62
  fontWeight: "thin",
64
63
  }, children: ["@", item.replyTo.author.handle] }), " ", (0, jsx_runtime_1.jsx)(text_1.Text, { style: {
65
- color: ui_1.atoms.colors.gray[300],
64
+ color: ui_1.colors.gray[300],
66
65
  fontStyle: "italic",
67
66
  }, children: item.replyTo.record.text })] }) })), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [atoms_1.gap.all[2], ui_1.layout.flex.row, atoms_1.w.percent[100]], children: [showTime && ((0, jsx_runtime_1.jsx)(text_1.Text, { style: {
68
67
  fontVariant: ["tabular-nums"],
69
- color: ui_1.atoms.colors.gray[300],
68
+ color: ui_1.colors.gray[400],
70
69
  }, children: formatTime(item.record.createdAt) })), (0, jsx_runtime_1.jsxs)(text_1.Text, { weight: "bold", color: "default", style: [atoms_1.flex.shrink[1]], children: [(0, jsx_runtime_1.jsxs)(text_1.Text, { style: [
71
70
  {
72
71
  cursor: "pointer",
@@ -75,5 +74,6 @@ exports.RenderChatMessage = (0, react_1.memo)(function RenderChatMessage({ item,
75
74
  ], children: ["@", item.author.handle] }), ":", " ", (0, jsx_runtime_1.jsx)(RichTextMessage, { text: item.record.text, facets: item.record.facets || [] })] })] })] }));
76
75
  }, (prevProps, nextProps) => {
77
76
  return (prevProps.item.author.handle === nextProps.item.author.handle &&
78
- prevProps.item.record.text === nextProps.item.record.text);
77
+ prevProps.item.record.text === nextProps.item.record.text &&
78
+ prevProps.item.uri === nextProps.item.uri);
79
79
  });
@@ -28,15 +28,93 @@ function LeftAction(prog, drag) {
28
28
  });
29
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
30
  }
31
- const SHOWN_MSGS = react_native_1.Platform.OS === "android" || react_native_1.Platform.OS === "ios" ? 100 : 25;
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;
32
33
  const keyExtractor = (item, index) => {
33
34
  return `${item.uri}`;
34
35
  };
35
- const ChatLine = (0, react_1.memo)(({ item }) => {
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
+ },
55
+ ], children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: () => setReply(item), style: [
56
+ {
57
+ padding: 6,
58
+ borderRadius: 4,
59
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
60
+ },
61
+ ], onHoverIn: () => {
62
+ // Keep the actions bar visible when hovering over it
63
+ if (hoverTimeoutRef.current) {
64
+ clearTimeout(hoverTimeoutRef.current);
65
+ hoverTimeoutRef.current = null;
66
+ }
67
+ }, 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: [
68
+ {
69
+ padding: 6,
70
+ borderRadius: 4,
71
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
72
+ },
73
+ ], onHoverIn: () => {
74
+ // Keep the actions bar visible when hovering over it
75
+ if (hoverTimeoutRef.current) {
76
+ clearTimeout(hoverTimeoutRef.current);
77
+ hoverTimeoutRef.current = null;
78
+ }
79
+ }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Ellipsis, { color: "white", size: 16 }) })] }));
80
+ });
81
+ const ChatLine = (0, react_1.memo)(({ item, canModerate, }) => {
36
82
  const setReply = (0, __1.useSetReplyToMessage)();
37
83
  const setModMsg = (0, __1.usePlayerStore)((state) => state.setModMessage);
38
84
  const swipeableRef = (0, react_1.useRef)(null);
39
- return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onLongPress: () => setModMsg(item), children: (0, jsx_runtime_1.jsx)(ReanimatedSwipeable_1.default, { containerStyle: [atoms_1.py[1]], friction: 2, enableTrackpadTwoFingerGesture: true, rightThreshold: 40, renderRightActions: react_native_1.Platform.OS === "android" ? undefined : RightAction, renderLeftActions: react_native_1.Platform.OS === "android" ? undefined : LeftAction, overshootFriction: 9, ref: (ref) => {
85
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
86
+ const hoverTimeoutRef = (0, react_1.useRef)(null);
87
+ const handleHoverIn = () => {
88
+ if (hoverTimeoutRef.current) {
89
+ clearTimeout(hoverTimeoutRef.current);
90
+ hoverTimeoutRef.current = null;
91
+ }
92
+ setIsHovered(true);
93
+ };
94
+ const handleHoverOut = () => {
95
+ hoverTimeoutRef.current = setTimeout(() => {
96
+ setIsHovered(false);
97
+ }, 50);
98
+ };
99
+ (0, react_1.useEffect)(() => {
100
+ return () => {
101
+ if (hoverTimeoutRef.current) {
102
+ clearTimeout(hoverTimeoutRef.current);
103
+ }
104
+ };
105
+ }, []);
106
+ if (item.author.did === "did:sys:system") {
107
+ return ((0, jsx_runtime_1.jsx)(__1.SystemMessage, { timestamp: new Date(item.record.createdAt), title: item.record.text }));
108
+ }
109
+ if (react_native_1.Platform.OS === "web") {
110
+ return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [
111
+ atoms_1.py[1],
112
+ atoms_1.px[2],
113
+ { position: "relative", borderRadius: 8 },
114
+ isHovered && atoms_1.bg.gray[950],
115
+ ], onPointerEnter: handleHoverIn, onPointerLeave: handleHoverOut, children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { children: (0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: item }) }), (0, jsx_runtime_1.jsx)(ActionsBar, { item: item, visible: isHovered, hoverTimeoutRef: hoverTimeoutRef })] }));
116
+ }
117
+ 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) => {
40
118
  swipeableRef.current = ref;
41
119
  }, onSwipeableOpen: (r) => {
42
120
  if (r === (react_native_1.Platform.OS === "android" ? "right" : "left")) {
@@ -52,9 +130,9 @@ const ChatLine = (0, react_1.memo)(({ item }) => {
52
130
  }
53
131
  }, children: (0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: item }) }) }));
54
132
  });
55
- function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, ...props }) {
133
+ function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, canModerate = false, ...props }) {
56
134
  const chat = (0, __1.useChat)();
57
135
  if (!chat)
58
136
  return ((0, jsx_runtime_1.jsx)(__1.View, { style: [atoms_1.flex.shrink[1]], children: (0, jsx_runtime_1.jsx)(__1.Text, { children: "Loading chaat..." }) }));
59
- return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.flex.shrink[1]].concat(propsStyle || []), children: [(0, jsx_runtime_1.jsx)(react_native_1.FlatList, { style: [atoms_1.flex.grow[1], atoms_1.flex.shrink[1], atoms_1.w.percent[100]], data: chat, inverted: true, keyExtractor: keyExtractor, renderItem: ({ item, index }) => (0, jsx_runtime_1.jsx)(ChatLine, { item: item }), removeClippedSubviews: true, maxToRenderPerBatch: 10, initialNumToRender: 10, updateCellsBatchingPeriod: 50 }), (0, jsx_runtime_1.jsx)(mod_view_1.ModView, {})] }));
137
+ return ((0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.flex.shrink[1]].concat(propsStyle || []), children: [(0, jsx_runtime_1.jsx)(react_native_1.FlatList, { style: [atoms_1.flex.grow[1], atoms_1.flex.shrink[1], atoms_1.w.percent[100]], 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, {})] }));
60
138
  }
@@ -0,0 +1,35 @@
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,25 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModView = void 0;
4
+ exports.ReportButton = ReportButton;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const dropdown_menu_1 = require("@rn-primitives/dropdown-menu");
5
7
  const react_1 = require("react");
6
8
  const atoms_1 = require("../../lib/theme/atoms");
7
9
  const player_store_1 = require("../../player-store");
8
10
  const block_1 = require("../../streamplace-store/block");
9
11
  const xrpc_1 = require("../../streamplace-store/xrpc");
12
+ const react_native_1 = require("react-native");
13
+ const streamplace_store_1 = require("../../streamplace-store");
10
14
  const ui_1 = require("../ui");
11
- const chat_message_1 = require("./chat-message");
15
+ const BSKY_FRONTEND_DOMAIN = "bsky.app";
12
16
  exports.ModView = (0, react_1.forwardRef)(() => {
13
17
  const triggerRef = (0, react_1.useRef)(null);
14
18
  const message = (0, player_store_1.usePlayerStore)((state) => state.modMessage);
15
19
  let agent = (0, xrpc_1.usePDSAgent)();
16
- let createBlockRecord = (0, block_1.useCreateBlockRecord)();
20
+ let [messageRemoved, setMessageRemoved] = (0, react_1.useState)(false);
21
+ let { createBlock, isLoading: isBlockLoading } = (0, block_1.useCreateBlockRecord)();
22
+ let { createHideChat, isLoading: isHideLoading } = (0, block_1.useCreateHideChatRecord)();
23
+ // get the channel did
24
+ const channelId = (0, player_store_1.usePlayerStore)((state) => state.src);
25
+ // get the logged in user's identity
26
+ const handle = (0, streamplace_store_1.useStreamplaceStore)((state) => state.handle);
17
27
  if (!agent?.did) {
18
28
  (0, jsx_runtime_1.jsx)(ui_1.View, { style: [ui_1.layout.flex.row, ui_1.layout.flex.alignCenter, atoms_1.gap.all[2]], children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Log in to submit mod actions" }) });
19
29
  }
20
30
  (0, react_1.useEffect)(() => {
21
31
  if (message) {
22
32
  console.log("opening mod view");
33
+ setMessageRemoved(false);
23
34
  triggerRef.current?.open();
24
35
  }
25
36
  else {
@@ -27,10 +38,50 @@ exports.ModView = (0, react_1.forwardRef)(() => {
27
38
  triggerRef.current?.close();
28
39
  }
29
40
  }, [message]);
30
- return ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenu, { children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuTrigger, { ref: triggerRef, children: (0, jsx_runtime_1.jsx)(ui_1.View, {}) }), (0, jsx_runtime_1.jsx)(ui_1.ResponsiveDropdownMenuContent, { children: message && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { children: (0, jsx_runtime_1.jsx)(ui_1.View, { style: [ui_1.layout.flex.column, atoms_1.mr[5], { gap: 6 }], children: (0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: message }) }) }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: `Moderation actions`, children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { disabled: message.author.did === agent?.did, onPress: () => {
31
- console.log("Creating block record");
32
- createBlockRecord(message.author.did)
33
- .then((r) => console.log(r))
34
- .catch((e) => console.error(e));
35
- }, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { color: "destructive", children: message.author.did === agent?.did ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "Block yourself (you can't block yourself)" })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Block user @", message.author.handle, " from this channel"] })) }) }) })] })) })] }));
41
+ return ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenu, { style: [ui_1.layout.flex.row, ui_1.layout.flex.alignCenter, atoms_1.gap.all[2], atoms_1.w[80]], children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuTrigger, { ref: triggerRef, children: (0, jsx_runtime_1.jsx)(ui_1.View, {}) }), (0, jsx_runtime_1.jsx)(ui_1.ResponsiveDropdownMenuContent, { children: message && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { children: (0, jsx_runtime_1.jsx)(ui_1.View, { style: [
42
+ ui_1.layout.flex.column,
43
+ atoms_1.mr[5],
44
+ { gap: 6, maxWidth: "100%" },
45
+ ], children: (0, jsx_runtime_1.jsxs)(ui_1.Text, { style: {
46
+ fontVariant: ["tabular-nums"],
47
+ color: ui_1.atoms.colors.gray[300],
48
+ }, children: [new Date(message.record.createdAt).toLocaleTimeString([], {
49
+ hour: "2-digit",
50
+ minute: "2-digit",
51
+ hour12: false,
52
+ }), " ", "@", message.author.handle, ": ", message.record.text] }) }) }) }), channelId === handle && ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuGroup, { title: `Moderation actions`, children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { disabled: isHideLoading || messageRemoved, onPress: () => {
53
+ if (isHideLoading || messageRemoved)
54
+ return;
55
+ createHideChat(message.uri)
56
+ .then((r) => setMessageRemoved(true))
57
+ .catch((e) => console.error(e));
58
+ }, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { color: isHideLoading || messageRemoved ? "muted" : "destructive", children: isHideLoading
59
+ ? "Removing..."
60
+ : messageRemoved
61
+ ? "Message removed"
62
+ : "Remove this message" }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { disabled: message.author.did === agent?.did || isBlockLoading, onPress: () => {
63
+ createBlock(message.author.did)
64
+ .then((r) => console.log(r))
65
+ .catch((e) => console.error(e));
66
+ }, children: message.author.did === agent?.did ? ((0, jsx_runtime_1.jsx)(ui_1.Text, { color: "muted", children: "Block yourself (you can't block yourself)" })) : ((0, jsx_runtime_1.jsx)(ui_1.Text, { color: "destructive", children: isBlockLoading
67
+ ? "Blocking..."
68
+ : `Block user @${message.author.handle} from this channel` })) })] })), (0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuGroup, { title: `User actions`, children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { onPress: () => {
69
+ react_native_1.Linking.openURL(`https://${BSKY_FRONTEND_DOMAIN}/profile/${channelId}`);
70
+ }, children: (0, jsx_runtime_1.jsxs)(ui_1.Text, { color: "primary", children: ["View user on ", BSKY_FRONTEND_DOMAIN] }) }), (0, jsx_runtime_1.jsx)(ReportButton, { message: message })] })] })) })] }));
36
71
  });
72
+ function ReportButton({ message, }) {
73
+ const setReportModalOpen = (0, player_store_1.usePlayerStore)((x) => x.setReportModalOpen);
74
+ const setReportSubject = (0, player_store_1.usePlayerStore)((x) => x.setReportSubject);
75
+ const { onOpenChange } = (0, dropdown_menu_1.useRootContext)();
76
+ return ((0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { onPress: () => {
77
+ if (!message)
78
+ return;
79
+ onOpenChange?.(false);
80
+ setReportModalOpen(true);
81
+ setReportSubject({
82
+ $type: "com.atproto.repo.strongRef",
83
+ uri: message.uri,
84
+ cid: message.cid,
85
+ });
86
+ }, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { color: "warning", children: "Report chat..." }) }));
87
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SystemMessage = SystemMessage;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ const ui_1 = require("../../ui");
7
+ const ui_2 = require("../ui");
8
+ const text_1 = require("../ui/text");
9
+ function SystemMessage({ title, timestamp }) {
10
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [ui_1.w.percent[100], ui_1.px[2], ui_1.pb[2]], children: [(0, jsx_runtime_1.jsx)(text_1.Code, { color: "muted", tracking: "widest", style: [ui_1.pl[12], ui_1.ml[1]], children: "SYSTEM MESSAGE" }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [ui_1.gap.all[2], ui_1.layout.flex.row], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: {
11
+ fontVariant: ["tabular-nums"],
12
+ color: ui_2.atoms.colors.gray[300],
13
+ }, children: timestamp.toLocaleTimeString([], {
14
+ hour: "2-digit",
15
+ minute: "2-digit",
16
+ hour12: false,
17
+ }) }), (0, jsx_runtime_1.jsx)(text_1.Text, { weight: "bold", color: "default", style: [ui_1.flex.shrink[1]], children: title })] })] }));
18
+ }
19
+ exports.default = SystemMessage;
@@ -0,0 +1,9 @@
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
+ }
@@ -0,0 +1,7 @@
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
+ }