| 143 | |
| 144 | useEffect(() => { |
| 145 | const run = () => { |
| 146 | timeoutRef.current = null |
| 147 | const text = contentRef.current |
| 148 | const target = text.length |
| 149 | |
| 150 | if (revealedRef.current > target) { |
| 151 | revealedRef.current = target |
| 152 | setRevealed(target) |
| 153 | } |
| 154 | const current = revealedRef.current |
| 155 | if (current >= target) return |
| 156 | |
| 157 | const next = nextIndex(text, current) |
| 158 | revealedRef.current = next |
| 159 | setRevealed(next) |
| 160 | if (next < target) { |
| 161 | timeoutRef.current = setTimeout(run, PACE_MS) |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | if (hasBacklog && timeoutRef.current === null) { |
| 166 | timeoutRef.current = setTimeout(run, PACE_MS) |