Live video on the AT Protocol

Revert "move hover ref up to chat so there is never multiple hovers"

This reverts commit 5672e4c7039a0a607e3c0ca3e760b532b4738770.

+32 -42
+32 -42
js/components/src/components/chat/chat.tsx
··· 142 142 }, 143 143 ); 144 144 145 - const ChatLine = memo(({ 146 - item, 147 - isHovered, 148 - onHoverIn, 149 - onHoverOut, 150 - hoverTimeoutRef, 151 - }: { 152 - item: ChatMessageViewHydrated; 153 - isHovered?: boolean; 154 - onHoverIn?: () => void; 155 - onHoverOut?: () => void; 156 - hoverTimeoutRef?: React.MutableRefObject<NodeJS.Timeout | null>; 157 - }) => { 145 + const ChatLine = memo(({ item }: { item: ChatMessageViewHydrated }) => { 158 146 const setReply = useSetReplyToMessage(); 159 147 const setModMsg = usePlayerStore((state) => state.setModMessage); 160 148 const swipeableRef = useRef<SwipeableMethods | null>(null); 149 + const [isHovered, setIsHovered] = useState(false); 150 + const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null); 151 + 152 + const handleHoverIn = () => { 153 + if (hoverTimeoutRef.current) { 154 + clearTimeout(hoverTimeoutRef.current); 155 + hoverTimeoutRef.current = null; 156 + } 157 + setIsHovered(true); 158 + }; 159 + 160 + const handleHoverOut = () => { 161 + hoverTimeoutRef.current = setTimeout(() => { 162 + setIsHovered(false); 163 + }, 50); 164 + }; 165 + 166 + useEffect(() => { 167 + return () => { 168 + if (hoverTimeoutRef.current) { 169 + clearTimeout(hoverTimeoutRef.current); 170 + } 171 + }; 172 + }, []); 161 173 162 174 if (item.author.did === "did:sys:system") { 163 175 return ( ··· 184 196 }, 185 197 isHovered && bg.gray[950], 186 198 ]} 187 - onPointerEnter={onHoverIn} 188 - onPointerLeave={onHoverOut} 199 + onPointerEnter={handleHoverIn} 200 + onPointerLeave={handleHoverOut} 189 201 > 190 202 <Pressable style={[{ minWidth: 0, maxWidth: "100%" }]}> 191 203 <RenderChatMessage item={item} /> 192 204 </Pressable> 193 205 <ActionsBar 194 206 item={item} 195 - visible={!!isHovered} 196 - hoverTimeoutRef={hoverTimeoutRef!} 207 + visible={isHovered} 208 + hoverTimeoutRef={hoverTimeoutRef} 197 209 /> 198 210 </View> 199 211 ); 200 212 } 201 213 202 214 return ( 215 + <> 203 216 <Swipeable 204 217 containerStyle={[py[1]]} 205 218 friction={2} ··· 226 239 > 227 240 <RenderChatMessage item={item} /> 228 241 </Swipeable> 242 + </> 229 243 ); 230 244 }); 231 245 ··· 241 255 const chat = useChat(); 242 256 const [isScrolledUp, setIsScrolledUp] = useState(false); 243 257 const flatListRef = useRef<FlatList>(null); 244 - const [hoveredMessageUri, setHoveredMessageUri] = useState<string | null>(null); 245 - const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null); 246 - 247 - const handleHoverIn = (uri: string) => { 248 - if (hoverTimeoutRef.current) { 249 - clearTimeout(hoverTimeoutRef.current); 250 - hoverTimeoutRef.current = null; 251 - } 252 - setHoveredMessageUri(uri); 253 - }; 254 - 255 - const handleHoverOut = () => { 256 - hoverTimeoutRef.current = setTimeout(() => { 257 - setHoveredMessageUri(null); 258 - }, 50); 259 - }; 260 258 261 259 // Animation for scroll-to-bottom button 262 260 const buttonOpacity = useSharedValue(0); ··· 323 321 data={chat.slice(0, shownMessages)} 324 322 inverted={true} 325 323 keyExtractor={keyExtractor} 326 - renderItem={({ item }) => ( 327 - <ChatLine 328 - item={item} 329 - isHovered={hoveredMessageUri === item.uri} 330 - onHoverIn={() => handleHoverIn(item.uri)} 331 - onHoverOut={handleHoverOut} 332 - hoverTimeoutRef={hoverTimeoutRef} 333 - /> 334 - )} 324 + renderItem={({ item, index }) => <ChatLine item={item} />} 335 325 removeClippedSubviews={true} 336 326 maxToRenderPerBatch={10} 337 327 initialNumToRender={10}