@@ -32,7 +32,6 @@ import { ParsedPart } from '@app/utils/chat/replaceTextWithEmotes';
3232import { lightenColor } from '@app/utils/color/lightenColor' ;
3333import { clearImageCache } from '@app/utils/image/clearImageCache' ;
3434import { logger } from '@app/utils/logger' ;
35- import { BottomSheetModal } from '@gorhom/bottom-sheet' ;
3635import { batch } from '@legendapp/state' ;
3736import { useSelector } from '@legendapp/state/react' ;
3837import { TrueSheet } from '@lodev09/react-native-true-sheet' ;
@@ -111,13 +110,8 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
111110 const listRef = useRef < FlashListRef < AnyChatMessageType > | null > ( null ) ;
112111 const emoteSheetRef = useRef < TrueSheet > ( null ) ;
113112 const settingsSheetRef = useRef < TrueSheet > ( null ) ;
114- const debugModalRef = useRef < BottomSheetModal > ( null ) ;
115113 const chatInputRef = useRef < TextInput > ( null ) ;
116114
117- const badgePreviewSheetRef = useRef < BottomSheetModal > ( null ) ;
118- const emotePreviewSheetRef = useRef < BottomSheetModal > ( null ) ;
119- const actionSheetRef = useRef < BottomSheetModal > ( null ) ;
120-
121115 const [ messageInput , setMessageInput ] = useState ( '' ) ;
122116 const [ replyTo , setReplyTo ] = useState < ReplyToData | null > ( null ) ;
123117 const [ , setIsInputFocused ] = useState ( false ) ;
@@ -130,6 +124,7 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
130124 const [ selectedEmote , setSelectedEmote ] = useState < EmotePressData | null > (
131125 null ,
132126 ) ;
127+ const [ isDebugModalVisible , setIsDebugModalVisible ] = useState ( false ) ;
133128
134129 const mentionColorCache = useRef < Map < string , string > > ( new Map ( ) ) ;
135130 const lightenedColorCache = useRef < Map < string , string > > ( new Map ( ) ) ;
@@ -169,7 +164,6 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
169164 return ;
170165 }
171166
172- // Mark as fetching to prevent duplicate requests
173167 fetchedCosmeticsUsers . current . add ( twitchUserId ) ;
174168
175169 const existingPaintId = chatStore$ . userPaintIds [ twitchUserId ] ?. peek ( ) ;
@@ -393,7 +387,6 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
393387 [ clearLocalMessages , channelId , channelName , messages$ ] ,
394388 ) ;
395389
396- // If chat becomes empty unexpectedly during active usage, record it.
397390 useEffect ( ( ) => {
398391 if ( hasMessages ) {
399392 hasEverHadMessagesRef . current = true ;
@@ -405,7 +398,6 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
405398 if ( ! isMessagesEmpty ) return ;
406399
407400 const now = Date . now ( ) ;
408- // Avoid log spam if we temporarily clear/re-populate.
409401 if ( now - lastEmptyLogAtRef . current < 2000 ) return ;
410402 lastEmptyLogAtRef . current = now ;
411403
@@ -696,30 +688,23 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
696688
697689 const handleBadgeLongPress = useCallback ( ( badge : BadgePressData ) => {
698690 setSelectedBadge ( badge ) ;
699- globalThis . requestAnimationFrame ( ( ) => {
700- badgePreviewSheetRef . current ?. present ( ) ;
701- } ) ;
702691 } , [ ] ) ;
703692
704693 const handleMessageLongPress = useCallback (
705694 ( data : MessageActionData < 'usernotice' > ) => {
706695 setSelectedMessage ( data ) ;
707- actionSheetRef . current ?. present ( ) ;
708696 } ,
709697 [ ] ,
710698 ) ;
711699
712700 const handleEmotePress = useCallback ( ( emote : EmotePressData ) => {
713701 setSelectedEmote ( emote ) ;
714- globalThis . requestAnimationFrame ( ( ) => {
715- emotePreviewSheetRef . current ?. present ( ) ;
716- } ) ;
717702 } , [ ] ) ;
718703
719704 const handleActionSheetReply = useCallback ( ( ) => {
720705 if ( ! selectedMessage ) return ;
721706 handleReply ( selectedMessage . messageData ) ;
722- actionSheetRef . current ?. dismiss ( ) ;
707+ setSelectedMessage ( null ) ;
723708 } , [ selectedMessage , handleReply ] ) ;
724709
725710 const handleActionSheetCopy = useCallback ( ( ) => {
@@ -728,10 +713,9 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
728713 void Clipboard . setStringAsync ( messageText ) . then ( ( ) =>
729714 toast . success ( 'Copied to clipboard' ) ,
730715 ) ;
731- actionSheetRef . current ?. dismiss ( ) ;
716+ setSelectedMessage ( null ) ;
732717 } , [ selectedMessage ] ) ;
733718
734- // Stable getMentionColor - uses observable peek() to avoid renderItem recreation
735719 const getMentionColor = useCallback (
736720 ( username : string ) : string => {
737721 const lowerUsername = username . toLowerCase ( ) ;
@@ -759,7 +743,7 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
759743
760744 return color ;
761745 } ,
762- [ messages$ ] , // messages$ is stable observable reference
746+ [ messages$ ] ,
763747 ) ;
764748
765749 const parseTextForEmotes = useCallback (
@@ -838,7 +822,6 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
838822 if ( cached ) return cached ;
839823 const lightened = lightenColor ( color ) ;
840824 lightenedColorCache . current . set ( color , lightened ) ;
841- // Limit cache size to prevent memory leak
842825 if ( lightenedColorCache . current . size > 500 ) {
843826 const firstKey = lightenedColorCache . current . keys ( ) . next ( ) . value as
844827 | string
@@ -886,6 +869,8 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
886869 getMentionColor = { getMentionColorRef . current }
887870 parseTextForEmotes = { parseTextForEmotesRef . current }
888871 userPaints = { userPaintsRef . current }
872+ isChannelPointRedemption = { msg . isChannelPointRedemption }
873+ isTwitchSystemNotice = { msg . isTwitchSystemNotice }
889874 // @ts -expect-error - notice_tags union type not narrowing correctly
890875 notice_tags = {
891876 'notice_tags' in msg && msg . notice_tags ? msg . notice_tags : undefined
@@ -954,7 +939,7 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
954939 onSubmit = { handleSendMessage }
955940 onOpenEmoteSheet = { handleOpenEmoteSheet }
956941 onOpenSettingsSheet = { handleOpenSettingsSheet }
957- onOpenDebugModal = { ( ) => debugModalRef . current ?. present ( ) }
942+ onOpenDebugModal = { ( ) => setIsDebugModalVisible ( true ) }
958943 replyTo = { replyTo }
959944 onClearReply = { ( ) => setReplyTo ( null ) }
960945 isConnected = { connected }
@@ -969,7 +954,6 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
969954 ref = { settingsSheetRef }
970955 onRefetchEmotes = { ( ) => {
971956 void refetchEmotes ( ) . then ( ( ) => {
972- // Reprocess existing messages with new emote/badge data
973957 reprocessAllMessages ( ) ;
974958 } ) ;
975959 } }
@@ -982,29 +966,33 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
982966 />
983967
984968 < ChatDebugModal
985- ref = { debugModalRef }
969+ visible = { isDebugModalVisible }
970+ onClose = { ( ) => setIsDebugModalVisible ( false ) }
986971 onTestMessage = { handleTestMessage }
987972 onClearChatCache = { handleClearChatCache }
988973 onClearImageCache = { ( ) => void handleClearImageCache ( ) }
989974 />
990975
991976 { selectedBadge && (
992977 < BadgePreviewSheet
993- ref = { badgePreviewSheetRef }
978+ visible = { Boolean ( selectedBadge ) }
979+ onClose = { ( ) => setSelectedBadge ( null ) }
994980 selectedBadge = { selectedBadge }
995981 />
996982 ) }
997983
998984 { selectedEmote && (
999985 < EmotePreviewSheet
1000- ref = { emotePreviewSheetRef }
986+ visible = { Boolean ( selectedEmote ) }
987+ onClose = { ( ) => setSelectedEmote ( null ) }
1001988 selectedEmote = { selectedEmote }
1002989 />
1003990 ) }
1004991
1005992 { selectedMessage && (
1006993 < ActionSheet
1007- ref = { actionSheetRef }
994+ visible = { Boolean ( selectedMessage ) }
995+ onClose = { ( ) => setSelectedMessage ( null ) }
1008996 message = { selectedMessage . message }
1009997 username = { selectedMessage . username }
1010998 handleReply = { handleActionSheetReply }
0 commit comments