@streamplace/components 0.7.32 → 0.7.34

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.
@@ -81,7 +81,7 @@ const ActionsBar = (0, react_1.memo)(({ item, visible, hoverTimeoutRef, }) => {
81
81
  }
82
82
  }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Ellipsis, { color: "white", size: 16 }) })] }));
83
83
  });
84
- const ChatLine = (0, react_1.memo)(({ item, canModerate, }) => {
84
+ const ChatLine = (0, react_1.memo)(({ item }) => {
85
85
  const setReply = (0, __1.useSetReplyToMessage)();
86
86
  const setModMsg = (0, __1.usePlayerStore)((state) => state.setModMessage);
87
87
  const swipeableRef = (0, react_1.useRef)(null);
@@ -136,7 +136,7 @@ const ChatLine = (0, react_1.memo)(({ item, canModerate, }) => {
136
136
  }
137
137
  }, children: (0, jsx_runtime_1.jsx)(chat_message_1.RenderChatMessage, { item: item }) }) }));
138
138
  });
139
- function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, canModerate = false, ...props }) {
139
+ function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, ...props }) {
140
140
  const chat = (0, __1.useChat)();
141
141
  const [isScrolledUp, setIsScrolledUp] = (0, react_1.useState)(false);
142
142
  const handleScroll = (event) => {
@@ -151,10 +151,10 @@ function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, canModerate = fal
151
151
  }
152
152
  };
153
153
  if (!chat)
154
- 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..." }) }));
154
+ 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 chat..." }) }));
155
155
  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_gesture_handler_1.FlatList, { style: [
156
156
  atoms_1.flex.grow[1],
157
157
  atoms_1.flex.shrink[1],
158
158
  { minWidth: 0, maxWidth: "100%" },
159
- ], 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, onScroll: handleScroll, scrollEventThrottle: 16, nestedScrollEnabled: true }), (0, jsx_runtime_1.jsx)(mod_view_1.ModView, {})] }));
159
+ ], data: chat.slice(0, shownMessages), inverted: true, keyExtractor: keyExtractor, renderItem: ({ item, index }) => (0, jsx_runtime_1.jsx)(ChatLine, { item: item }), removeClippedSubviews: true, maxToRenderPerBatch: 10, initialNumToRender: 10, updateCellsBatchingPeriod: 50, onScroll: handleScroll, scrollEventThrottle: 16, nestedScrollEnabled: true }), (0, jsx_runtime_1.jsx)(mod_view_1.ModView, {})] }));
160
160
  }
@@ -26,6 +26,7 @@ exports.ModView = (0, react_1.forwardRef)(() => {
26
26
  const setReportSubject = (0, player_store_1.usePlayerStore)((x) => x.setReportSubject);
27
27
  const setModMessage = (0, player_store_1.usePlayerStore)((x) => x.setModMessage);
28
28
  const deleteChatMessage = (0, livestream_store_1.useDeleteChatMessage)();
29
+ const isMyStream = (0, player_store_1.useIsMyStream)();
29
30
  // get the channel did
30
31
  const channelId = (0, player_store_1.usePlayerStore)((state) => state.src);
31
32
  // get the logged in user's identity
@@ -60,7 +61,7 @@ exports.ModView = (0, react_1.forwardRef)(() => {
60
61
  hour: "2-digit",
61
62
  minute: "2-digit",
62
63
  hour12: false,
63
- }), " ", "@", 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: () => {
64
+ }), " ", "@", message.author.handle, ": ", message.record.text] }) }) }) }), isMyStream() && ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuGroup, { title: `Moderation actions`, children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuItem, { disabled: isHideLoading || messageRemoved, onPress: () => {
64
65
  if (isHideLoading || messageRemoved)
65
66
  return;
66
67
  createHideChat(message.uri)
@@ -9,7 +9,7 @@ const zero = tslib_1.__importStar(require("../../ui"));
9
9
  const chat_1 = require("../chat/chat");
10
10
  const chat_box_1 = require("../chat/chat-box");
11
11
  const { flex, bg, r, borders, p, px, py, text, layout } = zero;
12
- function ChatPanel({ isLive, isConnected, messagesPerMinute = 0, canModerate = false, shownMessages = 50, }) {
12
+ function ChatPanel({ isLive, isConnected, messagesPerMinute = 0, shownMessages = 50, }) {
13
13
  return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
14
14
  flex.values[1],
15
15
  bg.neutral[900],
@@ -27,7 +27,7 @@ function ChatPanel({ isLive, isConnected, messagesPerMinute = 0, canModerate = f
27
27
  ], children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [text.white, { fontSize: 18, fontWeight: "600" }], children: "Chat" }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [layout.flex.row, layout.flex.alignCenter], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
28
28
  { width: 6, height: 6, borderRadius: 3 },
29
29
  isLive && isConnected ? bg.green[500] : bg.gray[500],
30
- ] }), (0, jsx_runtime_1.jsxs)(react_native_1.Text, { style: [text.gray[400], { fontSize: 12, marginLeft: 8 }], children: [messagesPerMinute, " msg/min"] })] })] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [flex.values[1], px[2], { minHeight: 0 }], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1], { minHeight: 0 }], children: (0, jsx_runtime_1.jsx)(chat_1.Chat, { canModerate: canModerate, shownMessages: shownMessages }) }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [{ flexShrink: 0 }], children: (0, jsx_runtime_1.jsx)(chat_box_1.ChatBox, { emojiData: emoji_data_json_1.default, chatBoxStyle: [
30
+ ] }), (0, jsx_runtime_1.jsxs)(react_native_1.Text, { style: [text.gray[400], { fontSize: 12, marginLeft: 8 }], children: [messagesPerMinute, " msg/min"] })] })] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [flex.values[1], px[2], { minHeight: 0 }], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1], { minHeight: 0 }], children: (0, jsx_runtime_1.jsx)(chat_1.Chat, { shownMessages: shownMessages }) }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [{ flexShrink: 0 }], children: (0, jsx_runtime_1.jsx)(chat_box_1.ChatBox, { emojiData: emoji_data_json_1.default, chatBoxStyle: [
31
31
  bg.gray[700],
32
32
  borders.width.thin,
33
33
  borders.color.gray[600],
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useOffline = exports.intoPlayerProtocol = exports.usePlayerProtocol = exports.makePlayerStore = void 0;
3
+ exports.useIsMyStream = exports.useOffline = exports.intoPlayerProtocol = exports.usePlayerProtocol = exports.makePlayerStore = void 0;
4
4
  exports.usePlayerContext = usePlayerContext;
5
5
  exports.getPlayerStoreById = getPlayerStoreById;
6
6
  exports.getFirstPlayerID = getFirstPlayerID;
@@ -9,6 +9,7 @@ exports.usePlayerStore = usePlayerStore;
9
9
  const react_1 = require("react");
10
10
  const zustand_1 = require("zustand");
11
11
  const livestream_store_1 = require("../livestream-store");
12
+ const streamplace_store_1 = require("../streamplace-store");
12
13
  const context_1 = require("./context");
13
14
  const player_state_1 = require("./player-state");
14
15
  const makePlayerStore = (id) => {
@@ -195,3 +196,12 @@ const useOffline = () => {
195
196
  return now - Date.parse(segment.startTime) > 10000;
196
197
  };
197
198
  exports.useOffline = useOffline;
199
+ const useIsMyStream = () => {
200
+ const myHandle = (0, streamplace_store_1.useStreamplaceStore)((state) => state.handle);
201
+ const myDid = (0, streamplace_store_1.useStreamplaceStore)((state) => state.oauthSession?.did);
202
+ const channelId = usePlayerStore((state) => state.src);
203
+ return () => {
204
+ return myHandle === channelId || myDid === channelId;
205
+ };
206
+ };
207
+ exports.useIsMyStream = useIsMyStream;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamplace/components",
3
- "version": "0.7.32",
3
+ "version": "0.7.34",
4
4
  "description": "Streamplace React (Native) Components",
5
5
  "main": "dist/index.js",
6
6
  "types": "src/index.tsx",
@@ -54,5 +54,5 @@
54
54
  "start": "tsc --watch --preserveWatchOutput",
55
55
  "prepare": "tsc"
56
56
  },
57
- "gitHead": "8c9f6186d1e718bcc4dfe84fe8c681680dddcf0e"
57
+ "gitHead": "8d33e4f6129af71ccf3c5d959e347f78b6eb609a"
58
58
  }
@@ -136,124 +136,112 @@ const ActionsBar = memo(
136
136
  },
137
137
  );
138
138
 
139
- const ChatLine = memo(
140
- ({
141
- item,
142
- canModerate,
143
- }: {
144
- item: ChatMessageViewHydrated;
145
- canModerate: boolean;
146
- }) => {
147
- const setReply = useSetReplyToMessage();
148
- const setModMsg = usePlayerStore((state) => state.setModMessage);
149
- const swipeableRef = useRef<SwipeableMethods | null>(null);
150
- const [isHovered, setIsHovered] = useState(false);
151
- const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
139
+ const ChatLine = memo(({ item }: { item: ChatMessageViewHydrated }) => {
140
+ const setReply = useSetReplyToMessage();
141
+ const setModMsg = usePlayerStore((state) => state.setModMessage);
142
+ const swipeableRef = useRef<SwipeableMethods | null>(null);
143
+ const [isHovered, setIsHovered] = useState(false);
144
+ const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
152
145
 
153
- const handleHoverIn = () => {
146
+ const handleHoverIn = () => {
147
+ if (hoverTimeoutRef.current) {
148
+ clearTimeout(hoverTimeoutRef.current);
149
+ hoverTimeoutRef.current = null;
150
+ }
151
+ setIsHovered(true);
152
+ };
153
+
154
+ const handleHoverOut = () => {
155
+ hoverTimeoutRef.current = setTimeout(() => {
156
+ setIsHovered(false);
157
+ }, 50);
158
+ };
159
+
160
+ useEffect(() => {
161
+ return () => {
154
162
  if (hoverTimeoutRef.current) {
155
163
  clearTimeout(hoverTimeoutRef.current);
156
- hoverTimeoutRef.current = null;
157
164
  }
158
- setIsHovered(true);
159
- };
160
-
161
- const handleHoverOut = () => {
162
- hoverTimeoutRef.current = setTimeout(() => {
163
- setIsHovered(false);
164
- }, 50);
165
165
  };
166
+ }, []);
166
167
 
167
- useEffect(() => {
168
- return () => {
169
- if (hoverTimeoutRef.current) {
170
- clearTimeout(hoverTimeoutRef.current);
171
- }
172
- };
173
- }, []);
174
-
175
- if (item.author.did === "did:sys:system") {
176
- return (
177
- <SystemMessage
178
- timestamp={new Date(item.record.createdAt)}
179
- title={item.record.text}
180
- />
181
- );
182
- }
183
-
184
- if (Platform.OS === "web") {
185
- return (
186
- <View
187
- style={[
188
- py[1],
189
- px[2],
190
- {
191
- position: "relative",
192
- borderRadius: 8,
193
- minWidth: 0,
194
- maxWidth: "100%",
195
- },
196
- isHovered && bg.gray[950],
197
- ]}
198
- onPointerEnter={handleHoverIn}
199
- onPointerLeave={handleHoverOut}
200
- >
201
- <Pressable style={[{ minWidth: 0, maxWidth: "100%" }]}>
202
- <RenderChatMessage item={item} />
203
- </Pressable>
204
- <ActionsBar
205
- item={item}
206
- visible={isHovered}
207
- hoverTimeoutRef={hoverTimeoutRef}
208
- />
209
- </View>
210
- );
211
- }
168
+ if (item.author.did === "did:sys:system") {
169
+ return (
170
+ <SystemMessage
171
+ timestamp={new Date(item.record.createdAt)}
172
+ title={item.record.text}
173
+ />
174
+ );
175
+ }
212
176
 
177
+ if (Platform.OS === "web") {
213
178
  return (
214
- <>
215
- <Swipeable
216
- containerStyle={[py[1]]}
217
- friction={2}
218
- enableTrackpadTwoFingerGesture
219
- rightThreshold={40}
220
- leftThreshold={40}
221
- renderRightActions={
222
- Platform.OS === "android" ? undefined : RightAction
223
- }
224
- renderLeftActions={Platform.OS === "android" ? undefined : LeftAction}
225
- overshootFriction={9}
226
- ref={swipeableRef}
227
- onSwipeableOpen={(r) => {
228
- if (r === (Platform.OS === "android" ? "right" : "left")) {
229
- setReply(item);
230
- }
231
- if (r === (Platform.OS === "android" ? "left" : "right")) {
232
- setModMsg(item);
233
- }
234
- // close this swipeable
235
- const swipeable = swipeableRef.current;
236
- if (swipeable) {
237
- swipeable.close();
238
- }
239
- }}
240
- >
179
+ <View
180
+ style={[
181
+ py[1],
182
+ px[2],
183
+ {
184
+ position: "relative",
185
+ borderRadius: 8,
186
+ minWidth: 0,
187
+ maxWidth: "100%",
188
+ },
189
+ isHovered && bg.gray[950],
190
+ ]}
191
+ onPointerEnter={handleHoverIn}
192
+ onPointerLeave={handleHoverOut}
193
+ >
194
+ <Pressable style={[{ minWidth: 0, maxWidth: "100%" }]}>
241
195
  <RenderChatMessage item={item} />
242
- </Swipeable>
243
- </>
196
+ </Pressable>
197
+ <ActionsBar
198
+ item={item}
199
+ visible={isHovered}
200
+ hoverTimeoutRef={hoverTimeoutRef}
201
+ />
202
+ </View>
244
203
  );
245
- },
246
- );
204
+ }
205
+
206
+ return (
207
+ <>
208
+ <Swipeable
209
+ containerStyle={[py[1]]}
210
+ friction={2}
211
+ enableTrackpadTwoFingerGesture
212
+ rightThreshold={40}
213
+ leftThreshold={40}
214
+ renderRightActions={Platform.OS === "android" ? undefined : RightAction}
215
+ renderLeftActions={Platform.OS === "android" ? undefined : LeftAction}
216
+ overshootFriction={9}
217
+ ref={swipeableRef}
218
+ onSwipeableOpen={(r) => {
219
+ if (r === (Platform.OS === "android" ? "right" : "left")) {
220
+ setReply(item);
221
+ }
222
+ if (r === (Platform.OS === "android" ? "left" : "right")) {
223
+ setModMsg(item);
224
+ }
225
+ // close this swipeable
226
+ const swipeable = swipeableRef.current;
227
+ if (swipeable) {
228
+ swipeable.close();
229
+ }
230
+ }}
231
+ >
232
+ <RenderChatMessage item={item} />
233
+ </Swipeable>
234
+ </>
235
+ );
236
+ });
247
237
 
248
238
  export function Chat({
249
239
  shownMessages = SHOWN_MSGS,
250
240
  style: propsStyle,
251
- canModerate = false,
252
241
  ...props
253
242
  }: ComponentProps<typeof View> & {
254
243
  shownMessages?: number;
255
244
  style?: ComponentProps<typeof View>["style"];
256
- canModerate?: boolean;
257
245
  }) {
258
246
  const chat = useChat();
259
247
  const [isScrolledUp, setIsScrolledUp] = useState(false);
@@ -276,7 +264,7 @@ export function Chat({
276
264
  if (!chat)
277
265
  return (
278
266
  <View style={[flex.shrink[1], { minWidth: 0, maxWidth: "100%" }]}>
279
- <Text>Loading chaat...</Text>
267
+ <Text>Loading chat...</Text>
280
268
  </View>
281
269
  );
282
270
 
@@ -295,9 +283,7 @@ export function Chat({
295
283
  data={chat.slice(0, shownMessages)}
296
284
  inverted={true}
297
285
  keyExtractor={keyExtractor}
298
- renderItem={({ item, index }) => (
299
- <ChatLine item={item} canModerate={canModerate} />
300
- )}
286
+ renderItem={({ item, index }) => <ChatLine item={item} />}
301
287
  removeClippedSubviews={true}
302
288
  maxToRenderPerBatch={10}
303
289
  initialNumToRender={10}
@@ -1,7 +1,7 @@
1
1
  import { TriggerRef, useRootContext } from "@rn-primitives/dropdown-menu";
2
2
  import { forwardRef, useEffect, useRef, useState } from "react";
3
3
  import { gap, mr, w } from "../../lib/theme/atoms";
4
- import { usePlayerStore } from "../../player-store";
4
+ import { useIsMyStream, usePlayerStore } from "../../player-store";
5
5
  import {
6
6
  useCreateBlockRecord,
7
7
  useCreateHideChatRecord,
@@ -51,6 +51,7 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
51
51
  const setReportSubject = usePlayerStore((x) => x.setReportSubject);
52
52
  const setModMessage = usePlayerStore((x) => x.setModMessage);
53
53
  const deleteChatMessage = useDeleteChatMessage();
54
+ const isMyStream = useIsMyStream();
54
55
 
55
56
  // get the channel did
56
57
  const channelId = usePlayerStore((state) => state.src);
@@ -119,7 +120,7 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
119
120
  </DropdownMenuGroup>
120
121
 
121
122
  {/* TODO: Checking for non-owner moderators */}
122
- {channelId === handle && (
123
+ {isMyStream() && (
123
124
  <DropdownMenuGroup title={`Moderation actions`}>
124
125
  <DropdownMenuItem
125
126
  disabled={isHideLoading || messageRemoved}
@@ -10,7 +10,6 @@ interface ChatPanelProps {
10
10
  isLive: boolean;
11
11
  isConnected: boolean;
12
12
  messagesPerMinute?: number;
13
- canModerate?: boolean;
14
13
  shownMessages?: number;
15
14
  }
16
15
 
@@ -18,7 +17,6 @@ export default function ChatPanel({
18
17
  isLive,
19
18
  isConnected,
20
19
  messagesPerMinute = 0,
21
- canModerate = false,
22
20
  shownMessages = 50,
23
21
  }: ChatPanelProps) {
24
22
  return (
@@ -59,7 +57,7 @@ export default function ChatPanel({
59
57
  </View>
60
58
  <View style={[flex.values[1], px[2], { minHeight: 0 }]}>
61
59
  <View style={[flex.values[1], { minHeight: 0 }]}>
62
- <Chat canModerate={canModerate} shownMessages={shownMessages} />
60
+ <Chat shownMessages={shownMessages} />
63
61
  </View>
64
62
  <View style={[{ flexShrink: 0 }]}>
65
63
  <ChatBox
@@ -3,6 +3,7 @@ import { useContext, useEffect, useState } from "react";
3
3
  import { ChatMessageViewHydrated } from "streamplace";
4
4
  import { createStore, StoreApi, useStore } from "zustand";
5
5
  import { useLivestreamStore } from "../livestream-store";
6
+ import { useStreamplaceStore } from "../streamplace-store";
6
7
  import { PlayerContext } from "./context";
7
8
  import {
8
9
  IngestMediaSource,
@@ -271,3 +272,12 @@ export const useOffline = () => {
271
272
  }
272
273
  return now - Date.parse(segment.startTime) > 10000;
273
274
  };
275
+
276
+ export const useIsMyStream = () => {
277
+ const myHandle = useStreamplaceStore((state) => state.handle);
278
+ const myDid = useStreamplaceStore((state) => state.oauthSession?.did);
279
+ const channelId = usePlayerStore((state) => state.src);
280
+ return () => {
281
+ return myHandle === channelId || myDid === channelId;
282
+ };
283
+ };