11import { useEffect , useRef , useState } from "react" ;
2- import ElectricBorder from "react-bits/src/content/Animations/ElectricBorder/ElectricBorder" ;
32import GradientText from "react-bits/src/ts-default/TextAnimations/GradientText/GradientText" ;
43
54import catisaVideo from "@/assets/catisa.mp4" ;
65import { ChatMessage } from "@/shared/api" ;
6+ import ElectricBorder from "@/shared/components/ElectricBorderLegacy" ;
77import useTwitchStore from "@/shared/twitchStore/twitchStore" ;
88import { parseContent , replaceBadges , replaceEmotes } from "@/shared/Utils" ;
99
@@ -33,8 +33,10 @@ export function Message({ message, onRemove }: Props) {
3333 const parser = useTwitchStore ( state => state . parser ) ;
3434 const parserToLink = useTwitchStore ( state => state . parseToLink ) ;
3535 const [ parts ] = useState ( ( ) => parseContent ( message . message ) ) ;
36+ const [ isMultilineMessage , setIsMultilineMessage ] = useState ( false ) ;
3637 const roleColor = getRoleColor ( message ) ;
3738 const msgRef = useRef < HTMLDivElement > ( null ) ;
39+ const messageContentRef = useRef < HTMLDivElement > ( null ) ;
3840
3941 // Появление/исчезновение управляется фреймером (в родителе)
4042
@@ -49,6 +51,35 @@ export function Message({ message, onRemove }: Props) {
4951 return ( ) => clearTimeout ( timer ) ;
5052 } , [ onRemove , message ] ) ;
5153
54+ useEffect ( ( ) => {
55+ const messageElement = messageContentRef . current ;
56+ if ( ! messageElement ) {
57+ return ;
58+ }
59+
60+ const updateMultilineState = ( ) => {
61+ const computedStyles = window . getComputedStyle ( messageElement ) ;
62+ const parsedLineHeight = Number . parseFloat ( computedStyles . lineHeight ) ;
63+ const parsedFontSize = Number . parseFloat ( computedStyles . fontSize ) ;
64+ const lineHeight = Number . isFinite ( parsedLineHeight )
65+ ? parsedLineHeight
66+ : ( Number . isFinite ( parsedFontSize ) ? parsedFontSize : 16 ) * 1.2 ;
67+ const messageHeight = messageElement . getBoundingClientRect ( ) . height ;
68+ const hasMultipleTextLines =
69+ ! isCatisa && messageHeight > lineHeight * 1.6 ;
70+ setIsMultilineMessage ( hasMultipleTextLines ) ;
71+ } ;
72+
73+ updateMultilineState ( ) ;
74+
75+ const resizeObserver = new ResizeObserver ( updateMultilineState ) ;
76+ resizeObserver . observe ( messageElement ) ;
77+
78+ return ( ) => {
79+ resizeObserver . disconnect ( ) ;
80+ } ;
81+ } , [ isCatisa , message . message ] ) ;
82+
5283 return (
5384 < >
5485 < div className = { styles . wrapper } >
@@ -59,9 +90,12 @@ export function Message({ message, onRemove }: Props) {
5990 speed = { 1.2 }
6091 >
6192 < div style = { { display : "block" , padding : "3px 15px" } } >
62- < div ref = { msgRef } className = { styles . container } >
93+ < div
94+ ref = { msgRef }
95+ className = { `${ styles . container } ${ isMultilineMessage ? styles . containerLargeMessage : "" } ` }
96+ >
6397 < div
64- className = { styles . userInfo }
98+ className = { ` ${ styles . userInfo } ${ isMultilineMessage ? styles . userInfoLargeMessage : "" } ` }
6599 style = { { backgroundColor : roleColor ?? "transparent" } }
66100 >
67101 < div className = { styles . badges } >
@@ -76,7 +110,10 @@ export function Message({ message, onRemove }: Props) {
76110 { message . displayName }
77111 </ div >
78112 </ div >
79- < div className = { styles . message } >
113+ < div
114+ ref = { messageContentRef }
115+ className = { `${ styles . message } ${ isMultilineMessage ? styles . messageLargeMessage : "" } ` }
116+ >
80117 { isCatisa ? (
81118 < video
82119 src = { catisaVideo }
0 commit comments