create-pixi-vn 1.3.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/index.mjs +52 -59
  2. package/package.json +3 -3
  3. package/template-game-engine/.vscode/settings.json +9 -5
  4. package/template-react-vite-muijoy/.vscode/settings.json +14 -11
  5. package/template-react-vite-muijoy/src/components/AnimatedDots.tsx +45 -0
  6. package/template-react-vite-muijoy/src/hooks/useDebouncedEffect.ts +2 -2
  7. package/template-react-vite-muijoy/src/hooks/useInterval.ts +4 -2
  8. package/template-react-vite-muijoy/src/hooks/useSkipAutoDetector.ts +9 -21
  9. package/template-react-vite-muijoy/src/screens/NarrationScreen.tsx +7 -2
  10. package/template-react-vite-muijoy/src/screens/QuickTools.tsx +7 -1
  11. package/template-react-vite-muijoy-ink/.vscode/settings.json +4 -1
  12. package/template-react-vite-muijoy-ink/src/components/AnimatedDots.tsx +45 -0
  13. package/template-react-vite-muijoy-ink/src/hooks/useDebouncedEffect.ts +2 -2
  14. package/template-react-vite-muijoy-ink/src/hooks/useInterval.ts +4 -2
  15. package/template-react-vite-muijoy-ink/src/hooks/useSkipAutoDetector.ts +9 -21
  16. package/template-react-vite-muijoy-ink/src/screens/NarrationScreen.tsx +7 -2
  17. package/template-react-vite-muijoy-ink/src/screens/QuickTools.tsx +7 -1
  18. package/template-react-vite-muijoy-ink-tauri/.vscode/settings.json +4 -1
  19. package/template-react-vite-muijoy-ink-tauri/src/components/AnimatedDots.tsx +45 -0
  20. package/template-react-vite-muijoy-ink-tauri/src/hooks/useDebouncedEffect.ts +2 -2
  21. package/template-react-vite-muijoy-ink-tauri/src/hooks/useInterval.ts +4 -2
  22. package/template-react-vite-muijoy-ink-tauri/src/hooks/useSkipAutoDetector.ts +9 -21
  23. package/template-react-vite-muijoy-ink-tauri/src/screens/NarrationScreen.tsx +7 -2
  24. package/template-react-vite-muijoy-ink-tauri/src/screens/QuickTools.tsx +7 -1
  25. package/template-react-vite-muijoy-ink-tauri/src/screens/settings/FullScreenSettings.tsx +6 -1
  26. package/template-react-vite-muijoy-ink-tauri/src/use_query/useQueryIsFullModeScreen.ts +4 -0
  27. package/template-react-vite-muijoy-ink-tauri/src-tauri/capabilities/default.json +1 -0
  28. package/template-react-vite-muijoy-ink-tauri/src-tauri/tauri.conf.json +2 -0
  29. package/template-react-vite-muijoy-tauri/.vscode/settings.json +4 -1
  30. package/template-react-vite-muijoy-tauri/src/components/AnimatedDots.tsx +45 -0
  31. package/template-react-vite-muijoy-tauri/src/hooks/useDebouncedEffect.ts +2 -2
  32. package/template-react-vite-muijoy-tauri/src/hooks/useInterval.ts +4 -2
  33. package/template-react-vite-muijoy-tauri/src/hooks/useSkipAutoDetector.ts +9 -21
  34. package/template-react-vite-muijoy-tauri/src/screens/NarrationScreen.tsx +7 -2
  35. package/template-react-vite-muijoy-tauri/src/screens/QuickTools.tsx +7 -1
  36. package/template-react-vite-muijoy-tauri/src/screens/settings/FullScreenSettings.tsx +6 -1
  37. package/template-react-vite-muijoy-tauri/src/use_query/useQueryIsFullModeScreen.ts +4 -0
  38. package/template-react-vite-muijoy-tauri/src-tauri/capabilities/default.json +1 -0
  39. package/template-react-vite-muijoy-tauri/src-tauri/tauri.conf.json +2 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-pixi-vn",
3
3
  "description": "Create a new Pixi’VN project",
4
- "version": "1.3.1",
4
+ "version": "1.4.1",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0",
7
7
  "author": "DRincs-Productions",
@@ -40,16 +40,16 @@
40
40
  "homepage": "https://pixi-vn.web.app/",
41
41
  "funding": "https://github.com/DRincs-Productions/pixi-vn?sponsor=1",
42
42
  "devDependencies": {
43
- "@types/cross-spawn": "^6.0.6",
43
+ "@clack/prompts": "^0.10.1",
44
44
  "@types/minimist": "^1.2.5",
45
45
  "@types/which": "^3.0.4",
46
- "cross-spawn": "^7.0.6",
47
46
  "inquirer": "^12.6.0",
48
47
  "kolorist": "^1.8.0",
49
48
  "minimist": "^1.2.8",
50
49
  "unbuild": "^3.5.0"
51
50
  },
52
51
  "dependencies": {
52
+ "execa": "^9.5.3",
53
53
  "which": "^5.0.0"
54
54
  }
55
55
  }
@@ -25,11 +25,15 @@
25
25
  // move file
26
26
  "javascript.updateImportsOnFileMove.enabled": "always",
27
27
  "typescript.updateImportsOnFileMove.enabled": "always",
28
- // debug
29
- "terminal.integrated.defaultProfile.linux": "JavaScript Debug Terminal",
30
- "terminal.integrated.defaultProfile.windows": "JavaScript Debug Terminal",
31
- "terminal.integrated.defaultProfile.osx": "JavaScript Debug Terminal",
28
+ // debug
29
+ "terminal.integrated.defaultProfile.linux": "JavaScript Debug Terminal",
30
+ "terminal.integrated.defaultProfile.windows": "JavaScript Debug Terminal",
31
+ "terminal.integrated.defaultProfile.osx": "JavaScript Debug Terminal",
32
32
  // olther
33
33
  "extensions.ignoreRecommendations": false,
34
- "git.fetchOnPull": true
34
+ "git.fetchOnPull": true,
35
+ "workbench.editor.enablePreview": true,
36
+ "workbench.editorAssociations": {
37
+ "*.md": "vscode.markdown.preview.editor"
38
+ },
35
39
  }
@@ -1,28 +1,28 @@
1
1
  {
2
2
  // Formatter
3
3
  "[javascript]": {
4
- "editor.defaultFormatter": "esbenp.prettier-vscode",
5
- "editor.formatOnSave": true
4
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
5
+ "editor.formatOnSave": true
6
6
  },
7
7
  "[javascriptreact]": {
8
- "editor.defaultFormatter": "esbenp.prettier-vscode",
9
- "editor.formatOnSave": true
8
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
9
+ "editor.formatOnSave": true
10
10
  },
11
11
  "[typescript]": {
12
- "editor.defaultFormatter": "esbenp.prettier-vscode",
13
- "editor.formatOnSave": true
12
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
13
+ "editor.formatOnSave": true
14
14
  },
15
15
  "[typescriptreact]": {
16
- "editor.defaultFormatter": "esbenp.prettier-vscode",
17
- "editor.formatOnSave": true
16
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
17
+ "editor.formatOnSave": true
18
18
  },
19
19
  "[css]": {
20
20
  "editor.defaultFormatter": "vscode.css-language-features",
21
21
  "editor.formatOnSave": true
22
22
  },
23
23
  "[html]": {
24
- "editor.defaultFormatter": "esbenp.prettier-vscode",
25
- "editor.formatOnSave": true,
24
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
25
+ "editor.formatOnSave": true,
26
26
  "prettier.tabWidth": 2,
27
27
  },
28
28
  "prettier.jsxSingleQuote": true,
@@ -53,5 +53,8 @@
53
53
  ],
54
54
  // olther
55
55
  "extensions.ignoreRecommendations": false,
56
- "prettier.useEditorConfig": false,
56
+ "workbench.editor.enablePreview": true,
57
+ "workbench.editorAssociations": {
58
+ "*.md": "vscode.markdown.preview.editor"
59
+ },
57
60
  }
@@ -0,0 +1,45 @@
1
+ import { motion } from "framer-motion";
2
+
3
+ export default function AnimatedDots() {
4
+ const dots = [".", ".", "."]; // I caratteri da animare
5
+
6
+ return (
7
+ <motion.span
8
+ style={{ display: "flex", pointerEvents: "none", userSelect: "none" }}
9
+ transition={{
10
+ staggerChildren: 0.2,
11
+ }}
12
+ initial='closed'
13
+ animate='open'
14
+ >
15
+ {dots.map((dot, index) => (
16
+ <motion.span
17
+ key={index}
18
+ initial={{ y: 0 }}
19
+ variants={{
20
+ open: {
21
+ y: 5,
22
+ transition: {
23
+ repeat: Infinity,
24
+ duration: 0.5,
25
+ ease: "easeInOut",
26
+ repeatType: "reverse",
27
+ },
28
+ },
29
+ closed: {
30
+ y: 0,
31
+ transition: {
32
+ repeat: Infinity,
33
+ duration: 0.5,
34
+ ease: "easeInOut",
35
+ repeatType: "reverse",
36
+ },
37
+ },
38
+ }}
39
+ >
40
+ {dot}
41
+ </motion.span>
42
+ ))}
43
+ </motion.span>
44
+ );
45
+ }
@@ -25,9 +25,9 @@ export default function useDebouncedEffect(
25
25
  const { delay = 1000, enabled = true } = options;
26
26
 
27
27
  useEffect(() => {
28
- if (enabled) {
28
+ if (enabled && delay > 0) {
29
29
  const timeout = setTimeout(callback, delay);
30
30
  return () => clearTimeout(timeout);
31
31
  }
32
- }, dependencies);
32
+ }, [delay, enabled, ...dependencies]);
33
33
  }
@@ -4,6 +4,7 @@ import { useEffect, useRef } from "react";
4
4
  * A custom hook that sets up an interval to call a callback function.
5
5
  * @param callback The callback function to call on each interval.
6
6
  * @param options An object containing the delay and enabled state for the interval.
7
+ * @param dependencies The dependencies array that determines when to re-run the effect.
7
8
  */
8
9
  export default function useInterval(
9
10
  callback: () => any,
@@ -18,7 +19,8 @@ export default function useInterval(
18
19
  * @default true
19
20
  */
20
21
  enabled?: boolean;
21
- }
22
+ },
23
+ dependencies: any[] = []
22
24
  ) {
23
25
  const savedCallback = useRef<() => any | null>(null);
24
26
  const { delay = 1000, enabled = true } = options;
@@ -38,5 +40,5 @@ export default function useInterval(
38
40
  const id = setInterval(tick, delay);
39
41
  return () => clearInterval(id);
40
42
  }
41
- }, [delay, enabled]);
43
+ }, [delay, enabled, ...dependencies]);
42
44
  }
@@ -1,9 +1,9 @@
1
- import { useEffect } from "react";
2
1
  import { useShallow } from "zustand/react/shallow";
3
2
  import { SKIP_DELAY } from "../constans";
4
3
  import useAutoInfoStore from "../stores/useAutoInfoStore";
5
4
  import useSkipStore from "../stores/useSkipStore";
6
5
  import useTypewriterStore from "../stores/useTypewriterStore";
6
+ import useDebouncedEffect from "./useDebouncedEffect";
7
7
  import useInterval from "./useInterval";
8
8
  import useEventListener from "./useKeyDetector";
9
9
  import useNarrationFunctions from "./useNarrationFunctions";
@@ -21,26 +21,14 @@ export default function useSkipAutoDetector() {
21
21
  enabled: skipEnabled,
22
22
  });
23
23
 
24
- useEffect(() => {
25
- if (skipEnabled) {
26
- return;
27
- }
28
- if (autoEnabled && !typewriterInProgress) {
29
- if (autoTime) {
30
- let millisecond = autoTime * 1000;
31
- // Debouncing
32
- let timeout = setTimeout(() => {
33
- if (autoEnabled && !skipEnabled) {
34
- goNext();
35
- }
36
- }, millisecond);
37
-
38
- return () => {
39
- clearTimeout(timeout);
40
- };
41
- }
42
- }
43
- }, [autoTime, autoEnabled, typewriterInProgress, skipEnabled, goNext]);
24
+ useDebouncedEffect(
25
+ () => autoEnabled && !skipEnabled && goNext(),
26
+ {
27
+ delay: autoTime * 1000,
28
+ enabled: autoEnabled && !skipEnabled && !typewriterInProgress,
29
+ },
30
+ [autoEnabled, skipEnabled, goNext]
31
+ );
44
32
 
45
33
  useEventListener({
46
34
  type: "keypress",
@@ -11,6 +11,7 @@ import { MarkdownTypewriterHooks } from "react-markdown-typewriter";
11
11
  import rehypeRaw from "rehype-raw";
12
12
  import remarkGfm from "remark-gfm";
13
13
  import { useShallow } from "zustand/react/shallow";
14
+ import AnimatedDots from "../components/AnimatedDots";
14
15
  import SliderResizer from "../components/SliderResizer";
15
16
  import useDialogueCardStore from "../stores/useDialogueCardStore";
16
17
  import useInterfaceStore from "../stores/useInterfaceStore";
@@ -248,10 +249,14 @@ function NarrationScreenText(props: { paragraphRef: RefObject<HTMLDivElement | n
248
249
  delay={typewriterDelay}
249
250
  motionProps={{
250
251
  onAnimationStart: startTypewriter,
251
- onAnimationComplete: endTypewriter,
252
+ onAnimationComplete: (definition: "visible" | "hidden") => {
253
+ if (definition == "visible") {
254
+ endTypewriter();
255
+ }
256
+ },
252
257
  onCharacterAnimationComplete: handleCharacterAnimationComplete,
253
258
  }}
254
- fallback={<>...</>}
259
+ fallback={<AnimatedDots />}
255
260
  >
256
261
  {text}
257
262
  </MarkdownTypewriterHooks>
@@ -28,6 +28,7 @@ export default function QuickTools() {
28
28
  const setHideInterface = useInterfaceStore((state) => state.editHidden);
29
29
  const skipEnabled = useSkipStore((state) => state.enabled);
30
30
  const editSkipEnabled = useSkipStore((state) => state.editEnabled);
31
+ const setSkipEnabled = useSkipStore((state) => state.setEnabled);
31
32
  const autoEnabled = useAutoInfoStore((state) => state.enabled);
32
33
  const editAutoEnabled = useAutoInfoStore((state) => state.editEnabled);
33
34
  const { enqueueSnackbar } = useSnackbar();
@@ -69,7 +70,12 @@ export default function QuickTools() {
69
70
  transition={{ type: "tween" }}
70
71
  >
71
72
  <TextMenuButton
72
- onClick={goBack}
73
+ onClick={() => {
74
+ if (skipEnabled) {
75
+ setSkipEnabled(false);
76
+ }
77
+ goBack();
78
+ }}
73
79
  disabled={!canGoBack || nextStepLoading}
74
80
  sx={{ pointerEvents: !hideInterface ? "auto" : "none" }}
75
81
  >
@@ -53,5 +53,8 @@
53
53
  ],
54
54
  // olther
55
55
  "extensions.ignoreRecommendations": false,
56
- "prettier.useEditorConfig": false,
56
+ "workbench.editor.enablePreview": true,
57
+ "workbench.editorAssociations": {
58
+ "*.md": "vscode.markdown.preview.editor"
59
+ },
57
60
  }
@@ -0,0 +1,45 @@
1
+ import { motion } from "framer-motion";
2
+
3
+ export default function AnimatedDots() {
4
+ const dots = [".", ".", "."]; // I caratteri da animare
5
+
6
+ return (
7
+ <motion.span
8
+ style={{ display: "flex", pointerEvents: "none", userSelect: "none" }}
9
+ transition={{
10
+ staggerChildren: 0.2,
11
+ }}
12
+ initial='closed'
13
+ animate='open'
14
+ >
15
+ {dots.map((dot, index) => (
16
+ <motion.span
17
+ key={index}
18
+ initial={{ y: 0 }}
19
+ variants={{
20
+ open: {
21
+ y: 5,
22
+ transition: {
23
+ repeat: Infinity,
24
+ duration: 0.5,
25
+ ease: "easeInOut",
26
+ repeatType: "reverse",
27
+ },
28
+ },
29
+ closed: {
30
+ y: 0,
31
+ transition: {
32
+ repeat: Infinity,
33
+ duration: 0.5,
34
+ ease: "easeInOut",
35
+ repeatType: "reverse",
36
+ },
37
+ },
38
+ }}
39
+ >
40
+ {dot}
41
+ </motion.span>
42
+ ))}
43
+ </motion.span>
44
+ );
45
+ }
@@ -25,9 +25,9 @@ export default function useDebouncedEffect(
25
25
  const { delay = 1000, enabled = true } = options;
26
26
 
27
27
  useEffect(() => {
28
- if (enabled) {
28
+ if (enabled && delay > 0) {
29
29
  const timeout = setTimeout(callback, delay);
30
30
  return () => clearTimeout(timeout);
31
31
  }
32
- }, dependencies);
32
+ }, [delay, enabled, ...dependencies]);
33
33
  }
@@ -4,6 +4,7 @@ import { useEffect, useRef } from "react";
4
4
  * A custom hook that sets up an interval to call a callback function.
5
5
  * @param callback The callback function to call on each interval.
6
6
  * @param options An object containing the delay and enabled state for the interval.
7
+ * @param dependencies The dependencies array that determines when to re-run the effect.
7
8
  */
8
9
  export default function useInterval(
9
10
  callback: () => any,
@@ -18,7 +19,8 @@ export default function useInterval(
18
19
  * @default true
19
20
  */
20
21
  enabled?: boolean;
21
- }
22
+ },
23
+ dependencies: any[] = []
22
24
  ) {
23
25
  const savedCallback = useRef<() => any | null>(null);
24
26
  const { delay = 1000, enabled = true } = options;
@@ -38,5 +40,5 @@ export default function useInterval(
38
40
  const id = setInterval(tick, delay);
39
41
  return () => clearInterval(id);
40
42
  }
41
- }, [delay, enabled]);
43
+ }, [delay, enabled, ...dependencies]);
42
44
  }
@@ -1,9 +1,9 @@
1
- import { useEffect } from "react";
2
1
  import { useShallow } from "zustand/react/shallow";
3
2
  import { SKIP_DELAY } from "../constans";
4
3
  import useAutoInfoStore from "../stores/useAutoInfoStore";
5
4
  import useSkipStore from "../stores/useSkipStore";
6
5
  import useTypewriterStore from "../stores/useTypewriterStore";
6
+ import useDebouncedEffect from "./useDebouncedEffect";
7
7
  import useInterval from "./useInterval";
8
8
  import useEventListener from "./useKeyDetector";
9
9
  import useNarrationFunctions from "./useNarrationFunctions";
@@ -21,26 +21,14 @@ export default function useSkipAutoDetector() {
21
21
  enabled: skipEnabled,
22
22
  });
23
23
 
24
- useEffect(() => {
25
- if (skipEnabled) {
26
- return;
27
- }
28
- if (autoEnabled && !typewriterInProgress) {
29
- if (autoTime) {
30
- let millisecond = autoTime * 1000;
31
- // Debouncing
32
- let timeout = setTimeout(() => {
33
- if (autoEnabled && !skipEnabled) {
34
- goNext();
35
- }
36
- }, millisecond);
37
-
38
- return () => {
39
- clearTimeout(timeout);
40
- };
41
- }
42
- }
43
- }, [autoTime, autoEnabled, typewriterInProgress, skipEnabled, goNext]);
24
+ useDebouncedEffect(
25
+ () => autoEnabled && !skipEnabled && goNext(),
26
+ {
27
+ delay: autoTime * 1000,
28
+ enabled: autoEnabled && !skipEnabled && !typewriterInProgress,
29
+ },
30
+ [autoEnabled, skipEnabled, goNext]
31
+ );
44
32
 
45
33
  useEventListener({
46
34
  type: "keypress",
@@ -11,6 +11,7 @@ import { MarkdownTypewriterHooks } from "react-markdown-typewriter";
11
11
  import rehypeRaw from "rehype-raw";
12
12
  import remarkGfm from "remark-gfm";
13
13
  import { useShallow } from "zustand/react/shallow";
14
+ import AnimatedDots from "../components/AnimatedDots";
14
15
  import SliderResizer from "../components/SliderResizer";
15
16
  import useDialogueCardStore from "../stores/useDialogueCardStore";
16
17
  import useInterfaceStore from "../stores/useInterfaceStore";
@@ -248,10 +249,14 @@ function NarrationScreenText(props: { paragraphRef: RefObject<HTMLDivElement | n
248
249
  delay={typewriterDelay}
249
250
  motionProps={{
250
251
  onAnimationStart: startTypewriter,
251
- onAnimationComplete: endTypewriter,
252
+ onAnimationComplete: (definition: "visible" | "hidden") => {
253
+ if (definition == "visible") {
254
+ endTypewriter();
255
+ }
256
+ },
252
257
  onCharacterAnimationComplete: handleCharacterAnimationComplete,
253
258
  }}
254
- fallback={<>...</>}
259
+ fallback={<AnimatedDots />}
255
260
  >
256
261
  {text}
257
262
  </MarkdownTypewriterHooks>
@@ -28,6 +28,7 @@ export default function QuickTools() {
28
28
  const setHideInterface = useInterfaceStore((state) => state.editHidden);
29
29
  const skipEnabled = useSkipStore((state) => state.enabled);
30
30
  const editSkipEnabled = useSkipStore((state) => state.editEnabled);
31
+ const setSkipEnabled = useSkipStore((state) => state.setEnabled);
31
32
  const autoEnabled = useAutoInfoStore((state) => state.enabled);
32
33
  const editAutoEnabled = useAutoInfoStore((state) => state.editEnabled);
33
34
  const { enqueueSnackbar } = useSnackbar();
@@ -69,7 +70,12 @@ export default function QuickTools() {
69
70
  transition={{ type: "tween" }}
70
71
  >
71
72
  <TextMenuButton
72
- onClick={goBack}
73
+ onClick={() => {
74
+ if (skipEnabled) {
75
+ setSkipEnabled(false);
76
+ }
77
+ goBack();
78
+ }}
73
79
  disabled={!canGoBack || nextStepLoading}
74
80
  sx={{ pointerEvents: !hideInterface ? "auto" : "none" }}
75
81
  >
@@ -53,5 +53,8 @@
53
53
  ],
54
54
  // olther
55
55
  "extensions.ignoreRecommendations": false,
56
- "prettier.useEditorConfig": false,
56
+ "workbench.editor.enablePreview": true,
57
+ "workbench.editorAssociations": {
58
+ "*.md": "vscode.markdown.preview.editor"
59
+ },
57
60
  }
@@ -0,0 +1,45 @@
1
+ import { motion } from "framer-motion";
2
+
3
+ export default function AnimatedDots() {
4
+ const dots = [".", ".", "."]; // I caratteri da animare
5
+
6
+ return (
7
+ <motion.span
8
+ style={{ display: "flex", pointerEvents: "none", userSelect: "none" }}
9
+ transition={{
10
+ staggerChildren: 0.2,
11
+ }}
12
+ initial='closed'
13
+ animate='open'
14
+ >
15
+ {dots.map((dot, index) => (
16
+ <motion.span
17
+ key={index}
18
+ initial={{ y: 0 }}
19
+ variants={{
20
+ open: {
21
+ y: 5,
22
+ transition: {
23
+ repeat: Infinity,
24
+ duration: 0.5,
25
+ ease: "easeInOut",
26
+ repeatType: "reverse",
27
+ },
28
+ },
29
+ closed: {
30
+ y: 0,
31
+ transition: {
32
+ repeat: Infinity,
33
+ duration: 0.5,
34
+ ease: "easeInOut",
35
+ repeatType: "reverse",
36
+ },
37
+ },
38
+ }}
39
+ >
40
+ {dot}
41
+ </motion.span>
42
+ ))}
43
+ </motion.span>
44
+ );
45
+ }
@@ -25,9 +25,9 @@ export default function useDebouncedEffect(
25
25
  const { delay = 1000, enabled = true } = options;
26
26
 
27
27
  useEffect(() => {
28
- if (enabled) {
28
+ if (enabled && delay > 0) {
29
29
  const timeout = setTimeout(callback, delay);
30
30
  return () => clearTimeout(timeout);
31
31
  }
32
- }, dependencies);
32
+ }, [delay, enabled, ...dependencies]);
33
33
  }
@@ -4,6 +4,7 @@ import { useEffect, useRef } from "react";
4
4
  * A custom hook that sets up an interval to call a callback function.
5
5
  * @param callback The callback function to call on each interval.
6
6
  * @param options An object containing the delay and enabled state for the interval.
7
+ * @param dependencies The dependencies array that determines when to re-run the effect.
7
8
  */
8
9
  export default function useInterval(
9
10
  callback: () => any,
@@ -18,7 +19,8 @@ export default function useInterval(
18
19
  * @default true
19
20
  */
20
21
  enabled?: boolean;
21
- }
22
+ },
23
+ dependencies: any[] = []
22
24
  ) {
23
25
  const savedCallback = useRef<() => any | null>(null);
24
26
  const { delay = 1000, enabled = true } = options;
@@ -38,5 +40,5 @@ export default function useInterval(
38
40
  const id = setInterval(tick, delay);
39
41
  return () => clearInterval(id);
40
42
  }
41
- }, [delay, enabled]);
43
+ }, [delay, enabled, ...dependencies]);
42
44
  }
@@ -1,9 +1,9 @@
1
- import { useEffect } from "react";
2
1
  import { useShallow } from "zustand/react/shallow";
3
2
  import { SKIP_DELAY } from "../constans";
4
3
  import useAutoInfoStore from "../stores/useAutoInfoStore";
5
4
  import useSkipStore from "../stores/useSkipStore";
6
5
  import useTypewriterStore from "../stores/useTypewriterStore";
6
+ import useDebouncedEffect from "./useDebouncedEffect";
7
7
  import useInterval from "./useInterval";
8
8
  import useEventListener from "./useKeyDetector";
9
9
  import useNarrationFunctions from "./useNarrationFunctions";
@@ -21,26 +21,14 @@ export default function useSkipAutoDetector() {
21
21
  enabled: skipEnabled,
22
22
  });
23
23
 
24
- useEffect(() => {
25
- if (skipEnabled) {
26
- return;
27
- }
28
- if (autoEnabled && !typewriterInProgress) {
29
- if (autoTime) {
30
- let millisecond = autoTime * 1000;
31
- // Debouncing
32
- let timeout = setTimeout(() => {
33
- if (autoEnabled && !skipEnabled) {
34
- goNext();
35
- }
36
- }, millisecond);
37
-
38
- return () => {
39
- clearTimeout(timeout);
40
- };
41
- }
42
- }
43
- }, [autoTime, autoEnabled, typewriterInProgress, skipEnabled, goNext]);
24
+ useDebouncedEffect(
25
+ () => autoEnabled && !skipEnabled && goNext(),
26
+ {
27
+ delay: autoTime * 1000,
28
+ enabled: autoEnabled && !skipEnabled && !typewriterInProgress,
29
+ },
30
+ [autoEnabled, skipEnabled, goNext]
31
+ );
44
32
 
45
33
  useEventListener({
46
34
  type: "keypress",
@@ -11,6 +11,7 @@ import { MarkdownTypewriterHooks } from "react-markdown-typewriter";
11
11
  import rehypeRaw from "rehype-raw";
12
12
  import remarkGfm from "remark-gfm";
13
13
  import { useShallow } from "zustand/react/shallow";
14
+ import AnimatedDots from "../components/AnimatedDots";
14
15
  import SliderResizer from "../components/SliderResizer";
15
16
  import useDialogueCardStore from "../stores/useDialogueCardStore";
16
17
  import useInterfaceStore from "../stores/useInterfaceStore";
@@ -248,10 +249,14 @@ function NarrationScreenText(props: { paragraphRef: RefObject<HTMLDivElement | n
248
249
  delay={typewriterDelay}
249
250
  motionProps={{
250
251
  onAnimationStart: startTypewriter,
251
- onAnimationComplete: endTypewriter,
252
+ onAnimationComplete: (definition: "visible" | "hidden") => {
253
+ if (definition == "visible") {
254
+ endTypewriter();
255
+ }
256
+ },
252
257
  onCharacterAnimationComplete: handleCharacterAnimationComplete,
253
258
  }}
254
- fallback={<>...</>}
259
+ fallback={<AnimatedDots />}
255
260
  >
256
261
  {text}
257
262
  </MarkdownTypewriterHooks>
@@ -28,6 +28,7 @@ export default function QuickTools() {
28
28
  const setHideInterface = useInterfaceStore((state) => state.editHidden);
29
29
  const skipEnabled = useSkipStore((state) => state.enabled);
30
30
  const editSkipEnabled = useSkipStore((state) => state.editEnabled);
31
+ const setSkipEnabled = useSkipStore((state) => state.setEnabled);
31
32
  const autoEnabled = useAutoInfoStore((state) => state.enabled);
32
33
  const editAutoEnabled = useAutoInfoStore((state) => state.editEnabled);
33
34
  const { enqueueSnackbar } = useSnackbar();
@@ -69,7 +70,12 @@ export default function QuickTools() {
69
70
  transition={{ type: "tween" }}
70
71
  >
71
72
  <TextMenuButton
72
- onClick={goBack}
73
+ onClick={() => {
74
+ if (skipEnabled) {
75
+ setSkipEnabled(false);
76
+ }
77
+ goBack();
78
+ }}
73
79
  disabled={!canGoBack || nextStepLoading}
74
80
  sx={{ pointerEvents: !hideInterface ? "auto" : "none" }}
75
81
  >