summaryrefslogtreecommitdiff
path: root/makima/frontend/src/hooks/useTextScramble.ts
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2025-12-22 04:50:25 +0000
committersoryu <soryu@soryu.co>2025-12-23 14:47:18 +0000
commit0741a8b8e9a2099c82bff6d6b9ebbce9c07cad53 (patch)
tree88cbd5fecb9ca72a04aa07f1a6db4e1a751b1fd7 /makima/frontend/src/hooks/useTextScramble.ts
parentaee2e4e784afd6d115fb5f7b40284c4efd2da966 (diff)
downloadsoryu-0741a8b8e9a2099c82bff6d6b9ebbce9c07cad53.tar.gz
soryu-0741a8b8e9a2099c82bff6d6b9ebbce9c07cad53.zip
Update makima FE to add initial listening system
Diffstat (limited to 'makima/frontend/src/hooks/useTextScramble.ts')
-rw-r--r--makima/frontend/src/hooks/useTextScramble.ts52
1 files changed, 52 insertions, 0 deletions
diff --git a/makima/frontend/src/hooks/useTextScramble.ts b/makima/frontend/src/hooks/useTextScramble.ts
new file mode 100644
index 0000000..bb3f365
--- /dev/null
+++ b/makima/frontend/src/hooks/useTextScramble.ts
@@ -0,0 +1,52 @@
+import { useState, useCallback, useRef } from "react";
+
+const GLYPHS = "▒▓░█#@*+:-/[]{}<>_";
+
+export function useTextScramble(originalText: string) {
+ const [displayText, setDisplayText] = useState(originalText);
+ const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
+ const iterationRef = useRef(0);
+
+ const scramble = useCallback(() => {
+ // Clear any existing animation
+ if (timerRef.current) {
+ clearInterval(timerRef.current);
+ }
+
+ iterationRef.current = 0;
+
+ timerRef.current = setInterval(() => {
+ const text = originalText;
+ const iteration = iterationRef.current;
+
+ const display = text
+ .split("")
+ .map((char, index) => {
+ if (index < iteration) return char;
+ return GLYPHS.charAt(Math.floor(Math.random() * GLYPHS.length));
+ })
+ .join("");
+
+ setDisplayText(display);
+ iterationRef.current += 1;
+
+ if (iteration > text.length + 2) {
+ if (timerRef.current) {
+ clearInterval(timerRef.current);
+ timerRef.current = null;
+ }
+ setDisplayText(originalText);
+ }
+ }, 26);
+ }, [originalText]);
+
+ const reset = useCallback(() => {
+ if (timerRef.current) {
+ clearInterval(timerRef.current);
+ timerRef.current = null;
+ }
+ setDisplayText(originalText);
+ }, [originalText]);
+
+ return { displayText, scramble, reset };
+}