create-pixi-vn 1.1.0 → 1.1.2
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.
- package/README.md +18 -6
- package/package.json +1 -1
- package/template-react-vite-muijoy/src/AppRoutes.tsx +15 -11
- package/template-react-vite-muijoy/src/Home.tsx +24 -9
- package/template-react-vite-muijoy/src/components/GameSaveSlot.tsx +2 -2
- package/template-react-vite-muijoy/src/components/NextButton.tsx +17 -21
- package/template-react-vite-muijoy/src/components/ReturnMainMenuButton.tsx +3 -2
- package/{template-react-vite-muijoy-ink-tauri/src/interceptors/RefreshEventInterceptor.tsx → template-react-vite-muijoy/src/hooks/useClosePageDetector.tsx} +11 -15
- package/template-react-vite-muijoy/src/hooks/useKeyDetector.tsx +16 -0
- package/template-react-vite-muijoy/src/{interceptors/OnKeyEventInterceptor.tsx → hooks/useKeyboardDetector.tsx} +4 -9
- package/template-react-vite-muijoy/src/hooks/useNetworkDetector.tsx +18 -0
- package/{template-react-vite-muijoy-ink/src/interceptors/SkipAutoInterceptor.tsx → template-react-vite-muijoy/src/hooks/useSkipAutoDetector.tsx} +2 -2
- package/template-react-vite-muijoy/src/labels/startLabel.ts +11 -2
- package/template-react-vite-muijoy/src/main.tsx +3 -3
- package/template-react-vite-muijoy/src/screens/HistoryScreen.tsx +9 -12
- package/template-react-vite-muijoy/src/screens/OfflineScreen.tsx +54 -0
- package/template-react-vite-muijoy/src/screens/QuickTools.tsx +2 -2
- package/template-react-vite-muijoy/src/screens/Settings.tsx +8 -12
- package/template-react-vite-muijoy/src/stores/useNetworkStore.ts +20 -0
- package/template-react-vite-muijoy-ink/src/AppRoutes.tsx +15 -11
- package/template-react-vite-muijoy-ink/src/Home.tsx +26 -11
- package/template-react-vite-muijoy-ink/src/components/GameSaveSlot.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/components/NextButton.tsx +17 -21
- package/template-react-vite-muijoy-ink/src/components/ReturnMainMenuButton.tsx +3 -2
- package/{template-react-vite-muijoy-tauri/src/interceptors/RefreshEventInterceptor.tsx → template-react-vite-muijoy-ink/src/hooks/useClosePageDetector.tsx} +11 -15
- package/template-react-vite-muijoy-ink/src/{interceptors/InkInitialization.tsx → hooks/useInkInitialization.tsx} +1 -1
- package/template-react-vite-muijoy-ink/src/hooks/useKeyDetector.tsx +16 -0
- package/template-react-vite-muijoy-ink/src/{interceptors/OnKeyEventInterceptor.tsx → hooks/useKeyboardDetector.tsx} +4 -9
- package/template-react-vite-muijoy-ink/src/hooks/useNetworkDetector.tsx +18 -0
- package/{template-react-vite-muijoy-tauri/src/interceptors/SkipAutoInterceptor.tsx → template-react-vite-muijoy-ink/src/hooks/useSkipAutoDetector.tsx} +2 -2
- package/template-react-vite-muijoy-ink/src/ink/start.ink +5 -0
- package/template-react-vite-muijoy-ink/src/main.tsx +3 -3
- package/template-react-vite-muijoy-ink/src/screens/HistoryScreen.tsx +9 -12
- package/template-react-vite-muijoy-ink/src/screens/OfflineScreen.tsx +54 -0
- package/template-react-vite-muijoy-ink/src/screens/QuickTools.tsx +2 -2
- package/template-react-vite-muijoy-ink/src/screens/Settings.tsx +8 -12
- package/template-react-vite-muijoy-ink/src/stores/useNetworkStore.ts +20 -0
- package/template-react-vite-muijoy-ink-tauri/src/AppRoutes.tsx +15 -11
- package/template-react-vite-muijoy-ink-tauri/src/Home.tsx +26 -11
- package/template-react-vite-muijoy-ink-tauri/src/components/GameSaveSlot.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/components/NextButton.tsx +17 -21
- package/template-react-vite-muijoy-ink-tauri/src/components/ReturnMainMenuButton.tsx +3 -2
- package/{template-react-vite-muijoy-ink/src/interceptors/RefreshEventInterceptor.tsx → template-react-vite-muijoy-ink-tauri/src/hooks/useClosePageDetector.tsx} +11 -15
- package/template-react-vite-muijoy-ink-tauri/src/{interceptors/InkInitialization.tsx → hooks/useInkInitialization.tsx} +1 -1
- package/template-react-vite-muijoy-ink-tauri/src/hooks/useKeyDetector.tsx +16 -0
- package/{template-react-vite-muijoy-tauri/src/interceptors/OnKeyEventInterceptor.tsx → template-react-vite-muijoy-ink-tauri/src/hooks/useKeyboardDetector.tsx} +4 -9
- package/template-react-vite-muijoy-ink-tauri/src/hooks/useNetworkDetector.tsx +18 -0
- package/template-react-vite-muijoy-ink-tauri/src/{interceptors/SkipAutoInterceptor.tsx → hooks/useSkipAutoDetector.tsx} +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/ink/start.ink +5 -0
- package/template-react-vite-muijoy-ink-tauri/src/main.tsx +3 -3
- package/template-react-vite-muijoy-ink-tauri/src/screens/HistoryScreen.tsx +9 -12
- package/template-react-vite-muijoy-ink-tauri/src/screens/OfflineScreen.tsx +54 -0
- package/template-react-vite-muijoy-ink-tauri/src/screens/QuickTools.tsx +2 -2
- package/template-react-vite-muijoy-ink-tauri/src/screens/Settings.tsx +8 -12
- package/template-react-vite-muijoy-ink-tauri/src/stores/useNetworkStore.ts +20 -0
- package/template-react-vite-muijoy-tauri/src/AppRoutes.tsx +15 -11
- package/template-react-vite-muijoy-tauri/src/Home.tsx +24 -9
- package/template-react-vite-muijoy-tauri/src/components/GameSaveSlot.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/components/NextButton.tsx +17 -21
- package/template-react-vite-muijoy-tauri/src/components/ReturnMainMenuButton.tsx +3 -2
- package/{template-react-vite-muijoy/src/interceptors/RefreshEventInterceptor.tsx → template-react-vite-muijoy-tauri/src/hooks/useClosePageDetector.tsx} +11 -15
- package/template-react-vite-muijoy-tauri/src/hooks/useKeyDetector.tsx +16 -0
- package/{template-react-vite-muijoy-ink-tauri/src/interceptors/OnKeyEventInterceptor.tsx → template-react-vite-muijoy-tauri/src/hooks/useKeyboardDetector.tsx} +4 -9
- package/template-react-vite-muijoy-tauri/src/hooks/useNetworkDetector.tsx +18 -0
- package/{template-react-vite-muijoy/src/interceptors/SkipAutoInterceptor.tsx → template-react-vite-muijoy-tauri/src/hooks/useSkipAutoDetector.tsx} +2 -2
- package/template-react-vite-muijoy-tauri/src/labels/startLabel.ts +11 -2
- package/template-react-vite-muijoy-tauri/src/main.tsx +3 -3
- package/template-react-vite-muijoy-tauri/src/screens/HistoryScreen.tsx +9 -12
- package/template-react-vite-muijoy-tauri/src/screens/OfflineScreen.tsx +54 -0
- package/template-react-vite-muijoy-tauri/src/screens/QuickTools.tsx +2 -2
- package/template-react-vite-muijoy-tauri/src/screens/Settings.tsx +8 -12
- package/template-react-vite-muijoy-tauri/src/stores/useNetworkStore.ts +20 -0
- package/template-react-vite-muijoy/src/interceptors/GoBackEventInterceptor.tsx +0 -17
- package/template-react-vite-muijoy/src/utils/actions-utility.ts +0 -10
- package/template-react-vite-muijoy-ink/src/interceptors/GoBackEventInterceptor.tsx +0 -17
- package/template-react-vite-muijoy-ink/src/utils/actions-utility.ts +0 -10
- package/template-react-vite-muijoy-ink-tauri/src/interceptors/GoBackEventInterceptor.tsx +0 -17
- package/template-react-vite-muijoy-ink-tauri/src/utils/actions-utility.ts +0 -10
- package/template-react-vite-muijoy-tauri/src/interceptors/GoBackEventInterceptor.tsx +0 -17
- package/template-react-vite-muijoy-tauri/src/utils/actions-utility.ts +0 -10
package/README.md
CHANGED
|
@@ -4,9 +4,14 @@ You can start using Pixi’VN by initializing a new project.
|
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
7
|
+
Before starting, you must have the following tools installed:
|
|
8
|
+
|
|
7
9
|
* [Node.js](https://nodejs.org/) version 18 or higher.
|
|
8
10
|
* Text Editor with TypeScript support.
|
|
9
|
-
* [Visual Studio Code](https://code.visualstudio.com/)
|
|
11
|
+
* [Visual Studio Code](https://code.visualstudio.com/)
|
|
12
|
+
* [Cursor](https://www.cursor.com/)
|
|
13
|
+
* (Recommended) [Git](https://git-scm.com/)
|
|
14
|
+
* Have a [GitHub account](https://github.com/)
|
|
10
15
|
|
|
11
16
|
## Project Initialization
|
|
12
17
|
|
|
@@ -17,19 +22,26 @@ To initialize a new project, you can use the following command:
|
|
|
17
22
|
npm create pixi-vn@latest
|
|
18
23
|
|
|
19
24
|
# yarn
|
|
20
|
-
yarn create pixi-vn
|
|
25
|
+
yarn create pixi-vn
|
|
21
26
|
|
|
22
27
|
# pnpm
|
|
23
|
-
pnpm create pixi-vn
|
|
28
|
+
pnpm create pixi-vn
|
|
29
|
+
|
|
30
|
+
# bun
|
|
31
|
+
bun create pixi-vn
|
|
24
32
|
|
|
25
33
|
# bun
|
|
26
|
-
|
|
34
|
+
deno init --npm pixi-vn
|
|
27
35
|
```
|
|
28
36
|
|
|
29
37
|
The supported template presets are:
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
**Visual Novel - React**:
|
|
40
|
+
|
|
41
|
+
* **[Visual Novel - React - Typescript - Web page](https://github.com/DRincs-Productions/pixi-vn-react-template)**
|
|
42
|
+
* **[Visual Novel - React - Typescript - Web page + Desktop + Mobile](https://github.com/DRincs-Productions/pixi-vn-react-template/tree/tauri)**
|
|
43
|
+
* **[Visual Novel - React - Ink + Typescript - Web page](https://github.com/DRincs-Productions/pixi-vn-react-template/tree/ink)**
|
|
44
|
+
* **[Visual Novel - React - Ink + Typescript - Web page + Desktop + Mobile](https://github.com/DRincs-Productions/pixi-vn-react-template/tree/ink-tauri)**
|
|
33
45
|
|
|
34
46
|
( More templates will be added in the future, see this [issue](https://github.com/DRincs-Productions/pixi-vn/issues/162) for more information )
|
|
35
47
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Route, Routes } from 'react-router-dom';
|
|
2
2
|
import NextButton from './components/NextButton';
|
|
3
3
|
import { LOADING_ROUTE, MAIN_MENU_ROUTE, NARRATION_ROUTE } from './constans';
|
|
4
|
-
import
|
|
4
|
+
import useSkipAutoDetector from './hooks/useSkipAutoDetector';
|
|
5
5
|
import HistoryScreen from './screens/HistoryScreen';
|
|
6
6
|
import LoadingScreen from './screens/LoadingScreen';
|
|
7
7
|
import MainMenu from './screens/MainMenu';
|
|
@@ -14,17 +14,21 @@ export default function AppRoutes() {
|
|
|
14
14
|
<Routes>
|
|
15
15
|
<Route key={"main_menu"} path={MAIN_MENU_ROUTE} element={<MainMenu />} />
|
|
16
16
|
<Route key={"loading"} path={LOADING_ROUTE} element={<LoadingScreen />} />
|
|
17
|
-
<Route key={"narration"} path={NARRATION_ROUTE}
|
|
18
|
-
element={<>
|
|
19
|
-
<HistoryScreen />
|
|
20
|
-
<QuickTools />
|
|
21
|
-
<NarrationScreen />
|
|
22
|
-
<SkipAutoInterceptor />
|
|
23
|
-
<TextInput />
|
|
24
|
-
<NextButton />
|
|
25
|
-
</>}
|
|
26
|
-
/>
|
|
17
|
+
<Route key={"narration"} path={NARRATION_ROUTE} element={<NarrationElement />} />
|
|
27
18
|
<Route path="*" element={<MainMenu />} />
|
|
28
19
|
</Routes>
|
|
29
20
|
)
|
|
30
21
|
}
|
|
22
|
+
|
|
23
|
+
function NarrationElement() {
|
|
24
|
+
useSkipAutoDetector()
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<HistoryScreen />
|
|
28
|
+
<QuickTools />
|
|
29
|
+
<NarrationScreen />
|
|
30
|
+
<TextInput />
|
|
31
|
+
<NextButton />
|
|
32
|
+
</>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
import { Box } from '@mui/joy';
|
|
2
2
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
3
3
|
import Routes from './AppRoutes';
|
|
4
|
+
import useClosePageDetector from './hooks/useClosePageDetector';
|
|
5
|
+
import useKeyboardDetector from './hooks/useKeyboardDetector';
|
|
6
|
+
import useEventListener from './hooks/useKeyDetector';
|
|
7
|
+
import useNetworkDetector from './hooks/useNetworkDetector';
|
|
4
8
|
import Imports from './Imports';
|
|
5
|
-
import GoBackEventInterceptor from './interceptors/GoBackEventInterceptor';
|
|
6
|
-
import OnKeyEventInterceptor from './interceptors/OnKeyEventInterceptor';
|
|
7
|
-
import RefreshSaveEventInterceptor from './interceptors/RefreshEventInterceptor';
|
|
8
9
|
import GameSaveScreen from './screens/GameSaveScreen';
|
|
9
10
|
import SaveLoadAlert from './screens/modals/SaveLoadAlert';
|
|
11
|
+
import OfflineScreen from './screens/OfflineScreen';
|
|
10
12
|
import Settings from './screens/Settings';
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
function HomeChild() {
|
|
15
|
+
useKeyboardDetector()
|
|
16
|
+
useClosePageDetector()
|
|
17
|
+
useNetworkDetector()
|
|
18
|
+
// Prevent the user from going back to the previous page
|
|
19
|
+
useEventListener({
|
|
20
|
+
type: 'popstate',
|
|
21
|
+
listener: () => {
|
|
22
|
+
window.history.forward();
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
13
26
|
return (
|
|
14
|
-
|
|
27
|
+
<>
|
|
15
28
|
<Routes />
|
|
16
29
|
<Settings />
|
|
17
30
|
<GameSaveScreen />
|
|
18
31
|
<SaveLoadAlert />
|
|
19
|
-
<
|
|
20
|
-
<GoBackEventInterceptor />
|
|
21
|
-
<RefreshSaveEventInterceptor />
|
|
32
|
+
<OfflineScreen />
|
|
22
33
|
<Box
|
|
23
34
|
sx={{
|
|
24
35
|
pointerEvents: "auto",
|
|
@@ -26,6 +37,10 @@ export default function Home() {
|
|
|
26
37
|
>
|
|
27
38
|
<ReactQueryDevtools initialIsOpen={false} />
|
|
28
39
|
</Box>
|
|
29
|
-
|
|
40
|
+
</>
|
|
30
41
|
)
|
|
31
42
|
}
|
|
43
|
+
|
|
44
|
+
export default function Home() {
|
|
45
|
+
return (<Imports><HomeChild /></Imports>)
|
|
46
|
+
}
|
|
@@ -120,7 +120,7 @@ export default function GameSaveSlot({ saveId, onDelete, onLoad, onOverwriteSave
|
|
|
120
120
|
}}
|
|
121
121
|
/>
|
|
122
122
|
</IconButton>
|
|
123
|
-
<IconButton
|
|
123
|
+
{location.pathname !== MAIN_MENU_ROUTE && <IconButton
|
|
124
124
|
onClick={() => onOverwriteSave(saveData)}
|
|
125
125
|
>
|
|
126
126
|
<SaveAsIcon
|
|
@@ -129,7 +129,7 @@ export default function GameSaveSlot({ saveId, onDelete, onLoad, onOverwriteSave
|
|
|
129
129
|
color: useTheme().palette.neutral[300],
|
|
130
130
|
}}
|
|
131
131
|
/>
|
|
132
|
-
</IconButton>
|
|
132
|
+
</IconButton>}
|
|
133
133
|
<IconButton
|
|
134
134
|
onClick={() => {
|
|
135
135
|
onLoad(saveData)
|
|
@@ -3,8 +3,9 @@ import { Button } from '@mui/joy';
|
|
|
3
3
|
import { useQueryClient } from '@tanstack/react-query';
|
|
4
4
|
import { motion } from "motion/react";
|
|
5
5
|
import { useSnackbar } from 'notistack';
|
|
6
|
-
import { useCallback
|
|
6
|
+
import { useCallback } from 'react';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
|
+
import useEventListener from '../hooks/useKeyDetector';
|
|
8
9
|
import useInterfaceStore from '../stores/useInterfaceStore';
|
|
9
10
|
import useSkipStore from '../stores/useSkipStore';
|
|
10
11
|
import useStepStore from '../stores/useStepStore';
|
|
@@ -52,28 +53,23 @@ export default function NextButton() {
|
|
|
52
53
|
}
|
|
53
54
|
}, [tNarration, queryClient])
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
useEventListener({
|
|
57
|
+
type: 'keypress',
|
|
58
|
+
listener: (event) => {
|
|
59
|
+
if ((event.code == 'Enter' || event.code == 'Space')) {
|
|
60
|
+
setSkipEnabled(true)
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
})
|
|
64
|
+
useEventListener({
|
|
65
|
+
type: 'keyup',
|
|
66
|
+
listener: (event) => {
|
|
67
|
+
if ((event.code == 'Enter' || event.code == 'Space')) {
|
|
68
|
+
setSkipEnabled(false)
|
|
69
|
+
nextOnClick()
|
|
70
|
+
}
|
|
65
71
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
window.addEventListener("keypress", onkeypress);
|
|
70
|
-
window.addEventListener("keyup", onkeyup);
|
|
71
|
-
|
|
72
|
-
return () => {
|
|
73
|
-
window.removeEventListener("keypress", onkeypress);
|
|
74
|
-
window.removeEventListener("keyup", onkeyup);
|
|
75
|
-
};
|
|
76
|
-
}, [onkeypress, onkeyup]);
|
|
72
|
+
})
|
|
77
73
|
|
|
78
74
|
return (
|
|
79
75
|
<Button
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clearAllGameDatas } from '@drincs/pixi-vn';
|
|
1
2
|
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
|
|
2
3
|
import { Button, Stack, Typography } from "@mui/joy";
|
|
3
4
|
import { useState } from 'react';
|
|
@@ -5,7 +6,6 @@ import { useTranslation } from 'react-i18next';
|
|
|
5
6
|
import { useLocation } from 'react-router-dom';
|
|
6
7
|
import ModalDialogCustom from '../components/ModalDialog';
|
|
7
8
|
import useSettingsScreenStore from '../stores/useSettingsScreenStore';
|
|
8
|
-
import { gameEnd } from '../utils/actions-utility';
|
|
9
9
|
import { useMyNavigate } from '../utils/navigate-utility';
|
|
10
10
|
|
|
11
11
|
export default function ReturnMainMenuButton() {
|
|
@@ -51,7 +51,8 @@ export default function ReturnMainMenuButton() {
|
|
|
51
51
|
color='danger'
|
|
52
52
|
variant="outlined"
|
|
53
53
|
onClick={() => {
|
|
54
|
-
|
|
54
|
+
clearAllGameDatas()
|
|
55
|
+
navigate('/')
|
|
55
56
|
setOpenSettings(false)
|
|
56
57
|
setOpenDialog(false)
|
|
57
58
|
}}
|
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
4
|
import { LOADING_ROUTE, MAIN_MENU_ROUTE } from '../constans';
|
|
5
5
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
6
6
|
import { useMyNavigate } from '../utils/navigate-utility';
|
|
7
7
|
import { addRefreshSave, loadRefreshSave } from '../utils/save-utility';
|
|
8
|
+
import useEventListener from './useKeyDetector';
|
|
8
9
|
|
|
9
|
-
export default function
|
|
10
|
+
export default function useClosePageDetector() {
|
|
10
11
|
const navigate = useMyNavigate();
|
|
11
12
|
const queryClient = useQueryClient()
|
|
12
13
|
const location = useLocation();
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
useEventListener({
|
|
16
|
+
type: 'beforeunload',
|
|
17
|
+
listener: async () => {
|
|
18
|
+
if (location.pathname === MAIN_MENU_ROUTE || location.pathname === LOADING_ROUTE) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
await addRefreshSave()
|
|
17
22
|
}
|
|
18
|
-
|
|
19
|
-
}, [location])
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
window.addEventListener("beforeunload", beforeunload);
|
|
23
|
-
|
|
24
|
-
return () => {
|
|
25
|
-
window.removeEventListener("beforeunload", beforeunload);
|
|
26
|
-
};
|
|
27
|
-
}, [beforeunload]);
|
|
23
|
+
})
|
|
28
24
|
|
|
29
25
|
useEffect(() => {
|
|
30
26
|
loadRefreshSave(navigate).then(() => queryClient.invalidateQueries({ queryKey: [INTERFACE_DATA_USE_QUEY_KEY] }))
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export default function useEventListener<K extends keyof WindowEventMap>({ type, listener }: {
|
|
4
|
+
type: K
|
|
5
|
+
listener: (this: Window, ev: WindowEventMap[K]) => any
|
|
6
|
+
}) {
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
window.addEventListener(type, listener);
|
|
9
|
+
|
|
10
|
+
return () => {
|
|
11
|
+
window.removeEventListener(type, listener);
|
|
12
|
+
};
|
|
13
|
+
}, [onkeydown]);
|
|
14
|
+
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useQueryClient } from '@tanstack/react-query';
|
|
2
2
|
import { useSnackbar } from 'notistack';
|
|
3
|
-
import { useCallback
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { useLocation } from 'react-router-dom';
|
|
6
6
|
import useGameSaveScreenStore from '../stores/useGameSaveScreenStore';
|
|
@@ -8,8 +8,9 @@ import useInterfaceStore from '../stores/useInterfaceStore';
|
|
|
8
8
|
import useQueryLastSave, { LAST_SAVE_USE_QUEY_KEY } from '../use_query/useQueryLastSave';
|
|
9
9
|
import { SAVES_USE_QUEY_KEY } from '../use_query/useQuerySaves';
|
|
10
10
|
import { putSaveIntoIndexDB } from '../utils/save-utility';
|
|
11
|
+
import useEventListener from './useKeyDetector';
|
|
11
12
|
|
|
12
|
-
export default function
|
|
13
|
+
export default function useKeyboardDetector() {
|
|
13
14
|
const hideInterface = useInterfaceStore((state) => state.hidden);
|
|
14
15
|
const setHideInterface = useInterfaceStore((state) => state.setHidden);
|
|
15
16
|
const setOpenLoadAlert = useGameSaveScreenStore((state) => (state.editLoadAlert))
|
|
@@ -61,13 +62,7 @@ export default function EventInterceptor() {
|
|
|
61
62
|
}
|
|
62
63
|
}, [location, hideInterface, lastSave, queryClient, t])
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
window.addEventListener('keydown', onkeydown);
|
|
66
|
-
|
|
67
|
-
return () => {
|
|
68
|
-
window.removeEventListener('keydown', onkeydown);
|
|
69
|
-
};
|
|
70
|
-
}, [onkeydown]);
|
|
65
|
+
useEventListener({ type: 'keydown', listener: onkeydown })
|
|
71
66
|
|
|
72
67
|
return null
|
|
73
68
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import useNetworkStore from "../stores/useNetworkStore";
|
|
3
|
+
|
|
4
|
+
export default function useNetworkDetector() {
|
|
5
|
+
const update = useNetworkStore((state) => (state.updateOnlineStatus))
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
window.addEventListener("online", update);
|
|
9
|
+
window.addEventListener("offline", update);
|
|
10
|
+
|
|
11
|
+
return () => {
|
|
12
|
+
window.removeEventListener("online", update);
|
|
13
|
+
window.removeEventListener("offline", update);
|
|
14
|
+
};
|
|
15
|
+
}, []);
|
|
16
|
+
|
|
17
|
+
return null;
|
|
18
|
+
};
|
|
@@ -10,13 +10,13 @@ import useTypewriterStore from '../stores/useTypewriterStore';
|
|
|
10
10
|
import { INTERFACE_DATA_USE_QUEY_KEY } from '../use_query/useQueryInterface';
|
|
11
11
|
import { useMyNavigate } from '../utils/navigate-utility';
|
|
12
12
|
|
|
13
|
-
export default function
|
|
13
|
+
export default function useSkipAutoDetector() {
|
|
14
14
|
const navigate = useMyNavigate();
|
|
15
15
|
const { t: tNarration } = useTranslation(["narration"]);
|
|
16
16
|
const skipEnabled = useSkipStore((state) => state.enabled)
|
|
17
17
|
const autoEnabled = useAutoInfoStore((state) => state.enabled)
|
|
18
18
|
const autoTime = useAutoInfoStore((state) => state.time)
|
|
19
|
-
const typewriterInProgress = useTypewriterStore((state) =>
|
|
19
|
+
const typewriterInProgress = useTypewriterStore((state) => state.inProgress)
|
|
20
20
|
const [recheckSkip, setRecheckSkip] = useState<number>(0)
|
|
21
21
|
const { enqueueSnackbar } = useSnackbar();
|
|
22
22
|
const setNextStepLoading = useStepStore((state) => state.setLoading);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChoiceMenuOption, ChoiceMenuOptionClose, moveIn, narration, newLabel, showImage, showImageContainer } from "@drincs/pixi-vn";
|
|
1
|
+
import { Assets, ChoiceMenuOption, ChoiceMenuOptionClose, moveIn, narration, newLabel, showImage, showImageContainer } from "@drincs/pixi-vn";
|
|
2
2
|
import { james, mc, sly, steph } from "../values/characters";
|
|
3
3
|
|
|
4
4
|
const steph_fullname = "Stephanie";
|
|
@@ -329,7 +329,16 @@ const startLabel = newLabel("start", [
|
|
|
329
329
|
new ChoiceMenuOptionClose("No, I want to stop here"),
|
|
330
330
|
]
|
|
331
331
|
},
|
|
332
|
-
]
|
|
332
|
+
], {
|
|
333
|
+
onLoadingLabel: () => {
|
|
334
|
+
Assets.load([
|
|
335
|
+
"bg01-hallway",
|
|
336
|
+
"m01-body", "m01-eyes-grin", "m01-eyes-smile", "m01-eyes-wow", "m01-mouth-grin00", "m01-mouth-smile00", "m01-mouth-smile01",
|
|
337
|
+
"fm01-body", "fm01-eyes-smile", "fm01-eyes-upset", "fm01-mouth-serious00", "fm01-mouth-serious01", "fm01-mouth-smile00",
|
|
338
|
+
"fm02-body", "fm02-eyes-joy", "fm02-eyes-nervous", "fm02-eyes-wow", "fm02-mouth-nervous00", "fm02-mouth-smile00",
|
|
339
|
+
])
|
|
340
|
+
}
|
|
341
|
+
});
|
|
333
342
|
export default startLabel;
|
|
334
343
|
|
|
335
344
|
const secondPart = newLabel("second_part", [
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { canvas, narration } from '@drincs/pixi-vn'
|
|
1
|
+
import { canvas, clearAllGameDatas, narration } from '@drincs/pixi-vn'
|
|
2
2
|
import { createRoot } from 'react-dom/client'
|
|
3
3
|
import App from './App'
|
|
4
4
|
import './index.css'
|
|
5
|
-
import { gameEnd } from './utils/actions-utility'
|
|
6
5
|
import './values/characters'
|
|
7
6
|
|
|
8
7
|
// Canvas setup with PIXI
|
|
@@ -32,7 +31,8 @@ canvas.initialize(body, 1920, 1080, {
|
|
|
32
31
|
})
|
|
33
32
|
|
|
34
33
|
narration.onGameEnd = async ({ navigate }) => {
|
|
35
|
-
|
|
34
|
+
clearAllGameDatas()
|
|
35
|
+
navigate('/')
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
narration.onStepError = async (_error, { notify, t }) => {
|
|
@@ -3,12 +3,13 @@ import SearchRoundedIcon from "@mui/icons-material/SearchRounded";
|
|
|
3
3
|
import { Box, Chip, Input, Stack, Theme, Typography } from "@mui/joy";
|
|
4
4
|
import Avatar from '@mui/joy/Avatar';
|
|
5
5
|
import { useMediaQuery } from '@mui/material';
|
|
6
|
-
import React, {
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import Markdown from 'react-markdown';
|
|
9
9
|
import rehypeRaw from "rehype-raw";
|
|
10
10
|
import remarkGfm from "remark-gfm";
|
|
11
11
|
import ModalDialogCustom from '../components/ModalDialog';
|
|
12
|
+
import useEventListener from '../hooks/useKeyDetector';
|
|
12
13
|
import useHistoryScreenStore from '../stores/useHistoryScreenStore';
|
|
13
14
|
import { useQueryNarrativeHistory } from '../use_query/useQueryInterface';
|
|
14
15
|
|
|
@@ -90,18 +91,14 @@ export default function HistoryScreen() {
|
|
|
90
91
|
const { t } = useTranslation(["ui"]);
|
|
91
92
|
const smScreen = useMediaQuery((theme: Theme) => theme.breakpoints.down("md"));
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
useEventListener({
|
|
95
|
+
type: 'keydown',
|
|
96
|
+
listener: (event) => {
|
|
97
|
+
if (event.code == 'KeyH' && event.altKey) {
|
|
98
|
+
editOpen()
|
|
99
|
+
}
|
|
96
100
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
window.addEventListener('keydown', onkeydown);
|
|
101
|
-
return () => {
|
|
102
|
-
window.removeEventListener('keydown', onkeydown);
|
|
103
|
-
};
|
|
104
|
-
}, [onkeydown]);
|
|
101
|
+
})
|
|
105
102
|
|
|
106
103
|
return (
|
|
107
104
|
<ModalDialogCustom
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import SignalWifiBadIcon from '@mui/icons-material/SignalWifiBad';
|
|
2
|
+
import { Box } from '@mui/joy';
|
|
3
|
+
import Modal from '@mui/joy/Modal';
|
|
4
|
+
import { AnimatePresence, motion } from "motion/react";
|
|
5
|
+
import useNetworkStore from '../stores/useNetworkStore';
|
|
6
|
+
|
|
7
|
+
export default function OfflineScreen() {
|
|
8
|
+
const open = useNetworkStore((state) => !state.isOnline)
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<AnimatePresence>
|
|
12
|
+
<Modal
|
|
13
|
+
keepMounted
|
|
14
|
+
open={open}
|
|
15
|
+
component={motion.div}
|
|
16
|
+
variants={{
|
|
17
|
+
open: {
|
|
18
|
+
opacity: 1,
|
|
19
|
+
pointerEvents: "auto",
|
|
20
|
+
backdropFilter: "blur(8px)",
|
|
21
|
+
},
|
|
22
|
+
closed: {
|
|
23
|
+
opacity: 0,
|
|
24
|
+
pointerEvents: "none",
|
|
25
|
+
backdropFilter: "blur(0px)",
|
|
26
|
+
}
|
|
27
|
+
}}
|
|
28
|
+
initial={"closed"}
|
|
29
|
+
animate={open ? "open" : "closed"}
|
|
30
|
+
exit={"closed"}
|
|
31
|
+
transition={{
|
|
32
|
+
duration: 0.4,
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
<Box
|
|
36
|
+
sx={{
|
|
37
|
+
position: "absolute",
|
|
38
|
+
left: "50%",
|
|
39
|
+
top: "50%",
|
|
40
|
+
transform: "translate(-50%, -50%)",
|
|
41
|
+
borderRadius: "20%",
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
<SignalWifiBadIcon
|
|
45
|
+
color="error"
|
|
46
|
+
sx={{
|
|
47
|
+
fontSize: "1000%",
|
|
48
|
+
}}
|
|
49
|
+
/>
|
|
50
|
+
</Box>
|
|
51
|
+
</Modal>
|
|
52
|
+
</AnimatePresence>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { narration } from '@drincs/pixi-vn';
|
|
1
2
|
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
|
2
3
|
import { IconButton, Stack, useTheme } from '@mui/joy';
|
|
3
4
|
import { useQueryClient } from '@tanstack/react-query';
|
|
@@ -14,7 +15,6 @@ import useSkipStore from '../stores/useSkipStore';
|
|
|
14
15
|
import { INTERFACE_DATA_USE_QUEY_KEY, useQueryCanGoBack } from '../use_query/useQueryInterface';
|
|
15
16
|
import useQueryLastSave, { LAST_SAVE_USE_QUEY_KEY } from '../use_query/useQueryLastSave';
|
|
16
17
|
import { SAVES_USE_QUEY_KEY } from '../use_query/useQuerySaves';
|
|
17
|
-
import { goBack } from '../utils/actions-utility';
|
|
18
18
|
import { useMyNavigate } from '../utils/navigate-utility';
|
|
19
19
|
import { putSaveIntoIndexDB } from '../utils/save-utility';
|
|
20
20
|
|
|
@@ -68,7 +68,7 @@ export default function QuickTools() {
|
|
|
68
68
|
transition={{ type: "tween" }}
|
|
69
69
|
>
|
|
70
70
|
<TextMenuButton
|
|
71
|
-
onClick={() => goBack(navigate).then(() => queryClient.invalidateQueries({ queryKey: [INTERFACE_DATA_USE_QUEY_KEY] }))}
|
|
71
|
+
onClick={() => narration.goBack(navigate).then(() => queryClient.invalidateQueries({ queryKey: [INTERFACE_DATA_USE_QUEY_KEY] }))}
|
|
72
72
|
disabled={!canGoBack}
|
|
73
73
|
sx={{ pointerEvents: !hideInterface ? "auto" : "none" }}
|
|
74
74
|
>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Box, DialogContent, DialogTitle, Divider, Drawer, FormControl, ModalClose, RadioGroup, Sheet, Typography } from "@mui/joy";
|
|
2
2
|
import { Theme, useMediaQuery } from '@mui/material';
|
|
3
|
-
import { useCallback, useEffect } from 'react';
|
|
4
3
|
import { useTranslation } from 'react-i18next';
|
|
5
4
|
import ReturnMainMenuButton from '../components/ReturnMainMenuButton';
|
|
5
|
+
import useEventListener from "../hooks/useKeyDetector";
|
|
6
6
|
import useSettingsScreenStore from '../stores/useSettingsScreenStore';
|
|
7
7
|
import AutoSettingToggle from './settings/AutoSettingToggle';
|
|
8
8
|
import DialoguesSettings from './settings/DialoguesSettings';
|
|
@@ -19,18 +19,14 @@ export default function Settings() {
|
|
|
19
19
|
const { t } = useTranslation(["ui"]);
|
|
20
20
|
const smScreen = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm'));
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
useEventListener({
|
|
23
|
+
type: 'keydown',
|
|
24
|
+
listener: (event) => {
|
|
25
|
+
if (event.code == 'Escape') {
|
|
26
|
+
editOpen()
|
|
27
|
+
}
|
|
25
28
|
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
window.addEventListener('keydown', onkeydown);
|
|
30
|
-
return () => {
|
|
31
|
-
window.removeEventListener('keydown', onkeydown);
|
|
32
|
-
};
|
|
33
|
-
}, [onkeydown]);
|
|
29
|
+
})
|
|
34
30
|
|
|
35
31
|
return (
|
|
36
32
|
<Drawer
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
|
|
3
|
+
type NetworkStoreType = {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the user is online or not
|
|
6
|
+
*/
|
|
7
|
+
isOnline: boolean,
|
|
8
|
+
/**
|
|
9
|
+
* Update the online status
|
|
10
|
+
*/
|
|
11
|
+
updateOnlineStatus: () => void,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const useNetworkStore = create<NetworkStoreType>((set) => ({
|
|
15
|
+
isOnline: navigator.onLine,
|
|
16
|
+
updateOnlineStatus: () => {
|
|
17
|
+
set({ isOnline: navigator.onLine })
|
|
18
|
+
}
|
|
19
|
+
}))
|
|
20
|
+
export default useNetworkStore;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Route, Routes } from 'react-router-dom';
|
|
2
2
|
import NextButton from './components/NextButton';
|
|
3
3
|
import { LOADING_ROUTE, MAIN_MENU_ROUTE, NARRATION_ROUTE } from './constans';
|
|
4
|
-
import
|
|
4
|
+
import useSkipAutoDetector from './hooks/useSkipAutoDetector';
|
|
5
5
|
import HistoryScreen from './screens/HistoryScreen';
|
|
6
6
|
import LoadingScreen from './screens/LoadingScreen';
|
|
7
7
|
import MainMenu from './screens/MainMenu';
|
|
@@ -14,17 +14,21 @@ export default function AppRoutes() {
|
|
|
14
14
|
<Routes>
|
|
15
15
|
<Route key={"main_menu"} path={MAIN_MENU_ROUTE} element={<MainMenu />} />
|
|
16
16
|
<Route key={"loading"} path={LOADING_ROUTE} element={<LoadingScreen />} />
|
|
17
|
-
<Route key={"narration"} path={NARRATION_ROUTE}
|
|
18
|
-
element={<>
|
|
19
|
-
<HistoryScreen />
|
|
20
|
-
<QuickTools />
|
|
21
|
-
<NarrationScreen />
|
|
22
|
-
<SkipAutoInterceptor />
|
|
23
|
-
<TextInput />
|
|
24
|
-
<NextButton />
|
|
25
|
-
</>}
|
|
26
|
-
/>
|
|
17
|
+
<Route key={"narration"} path={NARRATION_ROUTE} element={<NarrationElement />} />
|
|
27
18
|
<Route path="*" element={<MainMenu />} />
|
|
28
19
|
</Routes>
|
|
29
20
|
)
|
|
30
21
|
}
|
|
22
|
+
|
|
23
|
+
function NarrationElement() {
|
|
24
|
+
useSkipAutoDetector()
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<HistoryScreen />
|
|
28
|
+
<QuickTools />
|
|
29
|
+
<NarrationScreen />
|
|
30
|
+
<TextInput />
|
|
31
|
+
<NextButton />
|
|
32
|
+
</>
|
|
33
|
+
)
|
|
34
|
+
}
|