Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 33 additions & 26 deletions packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styles from './textbox.module.scss';
import { useEffect } from 'react';
import { useEffect, useMemo } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

useMemo 被导入了,但在这个文件中并未使用。为了保持代码整洁,建议移除未使用的导入。

Suggested change
import { useEffect, useMemo } from 'react';
import { useEffect } from 'react';

import { WebGAL } from '@/Core/WebGAL';
import { ITextboxProps } from './types';
import useApplyStyle from '@/hooks/useApplyStyle';
Expand All @@ -8,6 +8,11 @@ import { textSize } from '@/store/userDataInterface';
import { useSelector } from 'react-redux';
import { RootState } from '@/store/store';

const hasEmoji = (text: any): boolean => {
if (typeof text !== 'string') return false;
return /\p{Emoji}/u.test(text);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use stricter emoji detection before skipping text effects

The new hasEmoji check uses \p{Emoji}, which also matches non-emoji characters such as ASCII digits, #, and *; this makes ordinary text tokens containing those characters take the skipEffect path and lose outline/stroke rendering unexpectedly. In practice, lines like Version 2.0 or score strings will now render without the intended IMSS layered effect even though they contain no emoji glyphs.

Useful? React with 👍 / 👎.

};
Comment on lines +11 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

hasEmoji 函数的 text 参数使用了 any 类型。在 TypeScript 中,使用 unknown 是比 any 更安全的选择,因为它会强制在使用前进行类型检查。既然函数内部已经有了 typeof text !== 'string' 的检查,将 any 改为 unknown 可以在不改变功能的情况下增强类型安全。

Suggested change
const hasEmoji = (text: any): boolean => {
if (typeof text !== 'string') return false;
return /\p{Emoji}/u.test(text);
};
const hasEmoji = (text: unknown): boolean => {
if (typeof text !== 'string') return false;
return /\p{Emoji}/u.test(text);
};


export default function IMSSTextbox(props: ITextboxProps) {
const {
textArray,
Expand Down Expand Up @@ -72,24 +77,18 @@ export default function IMSSTextbox(props: ITextboxProps) {
}
const styleClassName = ' ' + css(style, { label: 'showname' });
const styleAllText = ' ' + css(style_alltext, { label: 'showname' });
if (isEnhanced) {
return (
<span key={index} style={{ position: 'relative' }}>
const skipEffect = hasEmoji(e);
return (
<span key={index} style={{ position: 'relative' }}>
{skipEffect ? (
<span className={styleClassName + styleAllText}>{e}</span>
) : (
<span className={styles.zhanwei + styleAllText}>
{e}
<span className={applyStyle('outerName', styles.outerName) + styleClassName + styleAllText}>{e}</span>
{isUseStroke && <span className={applyStyle('innerName', styles.innerName) + styleAllText}>{e}</span>}
</span>
</span>
);
}
return (
<span key={index} style={{ position: 'relative' }}>
<span className={styles.zhanwei + styleAllText}>
{e}
<span className={applyStyle('outerName', styles.outerName) + styleClassName + styleAllText}>{e}</span>
{isUseStroke && <span className={applyStyle('innerName', styles.innerName) + styleAllText}>{e}</span>}
</span>
)}
</span>
);
});
Expand Down Expand Up @@ -140,36 +139,44 @@ export default function IMSSTextbox(props: ITextboxProps) {
}
const styleClassName = ' ' + css(style);
const styleAllText = ' ' + css(style_alltext);
const skipEffect = hasEmoji(e);

if (allTextIndex < prevLength) {
return (
<span
// data-text={e}
id={`${delay}`}
className={applyStyle('TextBox_textElement_Settled', styles.TextBox_textElement_Settled)}
key={currentDialogKey + index}
style={{ animationDelay: `${delay}ms`, animationDuration: `${textDuration}ms` }}
>
<span className={styles.zhanwei + styleAllText}>
{e}
<span className={applyStyle('outer', styles.outer) + styleClassName + styleAllText}>{e}</span>
{isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
</span>
{skipEffect ? (
<span className={styleClassName + styleAllText}>{e}</span>
) : (
<span className={styles.zhanwei + styleAllText}>
{e}
<span className={applyStyle('outer', styles.outer) + styleClassName + styleAllText}>{e}</span>
{isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
</span>
)}
</span>
);
}
return (
<span
// data-text={e}
id={`${delay}`}
className={`${applyStyle('TextBox_textElement_start', styles.TextBox_textElement_start)} Textelement_start`}
key={currentDialogKey + index}
style={{ animationDelay: `${delay}ms`, position: 'relative' }}
>
<span className={styles.zhanwei + styleAllText}>
{e}
<span className={applyStyle('outer', styles.outer) + styleClassName + styleAllText}>{e}</span>
{isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
</span>
{skipEffect ? (
<span className={styleClassName + styleAllText}>{e}</span>
) : (
<span className={styles.zhanwei + styleAllText}>
{e}
<span className={applyStyle('outer', styles.outer) + styleClassName + styleAllText}>{e}</span>
{isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
</span>
)}
</span>
);
Comment on lines 144 to 181
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

textElementListmap 方法中,根据 skipEffect 变量来决定是否渲染特效的 JSX 逻辑在 if (allTextIndex < prevLength)else 两个分支中被重复了。可以将这部分重复的 JSX 提取到一个变量中,以减少代码重复,提高可读性和可维护性。

      const textSpan = skipEffect ? (
        <span className={styleClassName + styleAllText}>{e}</span>
      ) : (
        <span className={styles.zhanwei + styleAllText}>
          {e}
          <span className={applyStyle('outer', styles.outer) + styleClassName + styleAllText}>{e}</span>
          {isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
        </span>
      );

      if (allTextIndex < prevLength) {
        return (
          <span
            id={`${delay}`}
            className={applyStyle('TextBox_textElement_Settled', styles.TextBox_textElement_Settled)}
            key={currentDialogKey + index}
            style={{ animationDelay: `${delay}ms`, animationDuration: `${textDuration}ms` }}
          >
            {textSpan}
          </span>
        );
      }
      return (
        <span
          id={`${delay}`}
          className={`${applyStyle('TextBox_textElement_start', styles.TextBox_textElement_start)} Textelement_start`}
          key={currentDialogKey + index}
          style={{ animationDelay: `${delay}ms`, position: 'relative' }}
        >
          {textSpan}
        </span>
      );

});
Expand Down