create-pixi-vn 2.1.5 → 2.1.7
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/package.json +1 -1
- package/template-nqtr-react-vite-muijoy/src/components/menus/main-menu.tsx +3 -3
- package/template-nqtr-react-vite-muijoy-ink/src/components/menus/main-menu.tsx +3 -3
- package/template-nqtr-react-vite-muijoy-ink-tauri/_github/workflows/mobile.yml +76 -13
- package/template-nqtr-react-vite-muijoy-ink-tauri/src/components/menus/main-menu.tsx +3 -3
- package/template-nqtr-react-vite-muijoy-tauri/_github/workflows/mobile.yml +76 -13
- package/template-nqtr-react-vite-muijoy-tauri/src/components/menus/main-menu.tsx +3 -3
- package/template-react-vite-muijoy/src/components/menus/main-menu.tsx +3 -3
- package/template-react-vite-muijoy-ink/src/components/menus/main-menu.tsx +3 -3
- package/template-react-vite-muijoy-ink-tauri/_github/workflows/mobile.yml +76 -13
- package/template-react-vite-muijoy-ink-tauri/package-lock.json +12 -12
- package/template-react-vite-muijoy-ink-tauri/src/components/menus/main-menu.tsx +3 -3
- package/template-react-vite-muijoy-tauri/_github/workflows/mobile.yml +76 -13
- package/template-react-vite-muijoy-tauri/src/components/menus/main-menu.tsx +3 -3
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@ import { useGameProps } from "@/lib/hooks/props-hooks";
|
|
|
13
13
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
14
14
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
15
15
|
import { cn } from "@/lib/utils";
|
|
16
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
16
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
17
17
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
18
18
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
19
19
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -224,7 +224,7 @@ export function ContinueMenuButton({
|
|
|
224
224
|
if (!lastSave) return;
|
|
225
225
|
setLoading(true);
|
|
226
226
|
onLoadingChange?.(true);
|
|
227
|
-
loadSave(lastSave)
|
|
227
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
228
228
|
.then(() =>
|
|
229
229
|
queryClient.invalidateQueries({
|
|
230
230
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -238,7 +238,7 @@ export function ContinueMenuButton({
|
|
|
238
238
|
setLoading(false);
|
|
239
239
|
onLoadingChange?.(false);
|
|
240
240
|
});
|
|
241
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
241
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
242
242
|
|
|
243
243
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
244
244
|
|
|
@@ -13,7 +13,7 @@ import { useGameProps } from "@/lib/hooks/props-hooks";
|
|
|
13
13
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
14
14
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
15
15
|
import { cn } from "@/lib/utils";
|
|
16
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
16
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
17
17
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
18
18
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
19
19
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -224,7 +224,7 @@ export function ContinueMenuButton({
|
|
|
224
224
|
if (!lastSave) return;
|
|
225
225
|
setLoading(true);
|
|
226
226
|
onLoadingChange?.(true);
|
|
227
|
-
loadSave(lastSave)
|
|
227
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
228
228
|
.then(() =>
|
|
229
229
|
queryClient.invalidateQueries({
|
|
230
230
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -238,7 +238,7 @@ export function ContinueMenuButton({
|
|
|
238
238
|
setLoading(false);
|
|
239
239
|
onLoadingChange?.(false);
|
|
240
240
|
});
|
|
241
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
241
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
242
242
|
|
|
243
243
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
244
244
|
|
|
@@ -100,26 +100,89 @@ jobs:
|
|
|
100
100
|
with open(manifest, 'w') as f:
|
|
101
101
|
f.write(content)
|
|
102
102
|
|
|
103
|
-
# Tauri may generate styles.xml or themes.xml
|
|
103
|
+
# Tauri may generate styles.xml or themes.xml, and both a light (values/)
|
|
104
|
+
# and dark (values-night/) variant — patch every variant we find so the
|
|
105
|
+
# fullscreen flag doesn't silently no-op when the device is in dark mode.
|
|
104
106
|
styles_candidates = (
|
|
105
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
106
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
107
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/styles.xml') +
|
|
108
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/themes.xml')
|
|
107
109
|
)
|
|
108
110
|
if not styles_candidates:
|
|
109
111
|
print('Warning: no styles.xml/themes.xml found, skipping fullscreen patch')
|
|
110
112
|
else:
|
|
111
|
-
styles
|
|
112
|
-
|
|
113
|
+
for styles in styles_candidates:
|
|
114
|
+
with open(styles) as f:
|
|
115
|
+
content = f.read()
|
|
116
|
+
# Hide status bar (fullscreen) — kept as a best-effort theme hint,
|
|
117
|
+
# but on targetSdk 35+ (edge-to-edge is enforced by the OS) this
|
|
118
|
+
# alone has no effect; the real fix is the MainActivity.kt patch below.
|
|
119
|
+
content = content.replace(
|
|
120
|
+
'</style>',
|
|
121
|
+
' <item name="android:windowFullscreen">true</item>\n </style>',
|
|
122
|
+
1
|
|
123
|
+
)
|
|
124
|
+
with open(styles, 'w') as f:
|
|
125
|
+
f.write(content)
|
|
126
|
+
print(f'Patched {styles}')
|
|
127
|
+
|
|
128
|
+
# Since this project's Android template targets SDK 35+, edge-to-edge display
|
|
129
|
+
# is enforced by the OS and the theme-based windowFullscreen flag above no
|
|
130
|
+
# longer hides the status bar (it's always drawn, transparent, over the
|
|
131
|
+
# content). The only reliable way to hide it is to hide the system bars at
|
|
132
|
+
# runtime via WindowInsetsControllerCompat in MainActivity.kt.
|
|
133
|
+
activity_candidates = glob.glob(
|
|
134
|
+
'src-tauri/gen/android/app/src/main/**/MainActivity.kt', recursive=True
|
|
135
|
+
)
|
|
136
|
+
if not activity_candidates:
|
|
137
|
+
print('WARNING: MainActivity.kt not found — status bar hiding NOT patched')
|
|
138
|
+
else:
|
|
139
|
+
activity = activity_candidates[0]
|
|
140
|
+
with open(activity) as f:
|
|
113
141
|
content = f.read()
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
142
|
+
|
|
143
|
+
new_imports = [
|
|
144
|
+
'androidx.core.view.WindowCompat',
|
|
145
|
+
'androidx.core.view.WindowInsetsCompat',
|
|
146
|
+
'androidx.core.view.WindowInsetsControllerCompat',
|
|
147
|
+
]
|
|
148
|
+
import_lines = list(re.finditer(r'^import .+$', content, re.MULTILINE))
|
|
149
|
+
if import_lines:
|
|
150
|
+
insert_at = import_lines[-1].end()
|
|
151
|
+
addition = ''.join(
|
|
152
|
+
f'\nimport {imp}' for imp in new_imports if imp not in content
|
|
153
|
+
)
|
|
154
|
+
content = content[:insert_at] + addition + content[insert_at:]
|
|
155
|
+
|
|
156
|
+
if 'hideSystemBars' not in content:
|
|
157
|
+
content = content.replace(
|
|
158
|
+
'super.onCreate(savedInstanceState)',
|
|
159
|
+
'super.onCreate(savedInstanceState)\n hideSystemBars()',
|
|
160
|
+
1
|
|
161
|
+
)
|
|
162
|
+
content = re.sub(
|
|
163
|
+
r'\n}\s*$',
|
|
164
|
+
'\n\n'
|
|
165
|
+
' override fun onWindowFocusChanged(hasFocus: Boolean) {\n'
|
|
166
|
+
' super.onWindowFocusChanged(hasFocus)\n'
|
|
167
|
+
' if (hasFocus) {\n'
|
|
168
|
+
' hideSystemBars()\n'
|
|
169
|
+
' }\n'
|
|
170
|
+
' }\n'
|
|
171
|
+
'\n'
|
|
172
|
+
' private fun hideSystemBars() {\n'
|
|
173
|
+
' WindowCompat.setDecorFitsSystemWindows(window, false)\n'
|
|
174
|
+
' val controller = WindowInsetsControllerCompat(window, window.decorView)\n'
|
|
175
|
+
' controller.hide(WindowInsetsCompat.Type.systemBars())\n'
|
|
176
|
+
' controller.systemBarsBehavior =\n'
|
|
177
|
+
' WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE\n'
|
|
178
|
+
' }\n'
|
|
179
|
+
'}\n',
|
|
180
|
+
content,
|
|
181
|
+
count=1
|
|
182
|
+
)
|
|
183
|
+
with open(activity, 'w') as f:
|
|
121
184
|
f.write(content)
|
|
122
|
-
print(f'Patched {
|
|
185
|
+
print(f'Patched {activity} (hide system bars at runtime)')
|
|
123
186
|
PYEOF
|
|
124
187
|
|
|
125
188
|
- name: build Android app
|
|
@@ -14,7 +14,7 @@ import { useQuit } from "@/lib/hooks/quit-hooks";
|
|
|
14
14
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
15
15
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
16
16
|
import { cn } from "@/lib/utils";
|
|
17
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
17
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
18
18
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
19
19
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
20
20
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -239,7 +239,7 @@ export function ContinueMenuButton({
|
|
|
239
239
|
if (!lastSave) return;
|
|
240
240
|
setLoading(true);
|
|
241
241
|
onLoadingChange?.(true);
|
|
242
|
-
loadSave(lastSave)
|
|
242
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
243
243
|
.then(() =>
|
|
244
244
|
queryClient.invalidateQueries({
|
|
245
245
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -253,7 +253,7 @@ export function ContinueMenuButton({
|
|
|
253
253
|
setLoading(false);
|
|
254
254
|
onLoadingChange?.(false);
|
|
255
255
|
});
|
|
256
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
256
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
257
257
|
|
|
258
258
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
259
259
|
|
|
@@ -100,26 +100,89 @@ jobs:
|
|
|
100
100
|
with open(manifest, 'w') as f:
|
|
101
101
|
f.write(content)
|
|
102
102
|
|
|
103
|
-
# Tauri may generate styles.xml or themes.xml
|
|
103
|
+
# Tauri may generate styles.xml or themes.xml, and both a light (values/)
|
|
104
|
+
# and dark (values-night/) variant — patch every variant we find so the
|
|
105
|
+
# fullscreen flag doesn't silently no-op when the device is in dark mode.
|
|
104
106
|
styles_candidates = (
|
|
105
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
106
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
107
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/styles.xml') +
|
|
108
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/themes.xml')
|
|
107
109
|
)
|
|
108
110
|
if not styles_candidates:
|
|
109
111
|
print('Warning: no styles.xml/themes.xml found, skipping fullscreen patch')
|
|
110
112
|
else:
|
|
111
|
-
styles
|
|
112
|
-
|
|
113
|
+
for styles in styles_candidates:
|
|
114
|
+
with open(styles) as f:
|
|
115
|
+
content = f.read()
|
|
116
|
+
# Hide status bar (fullscreen) — kept as a best-effort theme hint,
|
|
117
|
+
# but on targetSdk 35+ (edge-to-edge is enforced by the OS) this
|
|
118
|
+
# alone has no effect; the real fix is the MainActivity.kt patch below.
|
|
119
|
+
content = content.replace(
|
|
120
|
+
'</style>',
|
|
121
|
+
' <item name="android:windowFullscreen">true</item>\n </style>',
|
|
122
|
+
1
|
|
123
|
+
)
|
|
124
|
+
with open(styles, 'w') as f:
|
|
125
|
+
f.write(content)
|
|
126
|
+
print(f'Patched {styles}')
|
|
127
|
+
|
|
128
|
+
# Since this project's Android template targets SDK 35+, edge-to-edge display
|
|
129
|
+
# is enforced by the OS and the theme-based windowFullscreen flag above no
|
|
130
|
+
# longer hides the status bar (it's always drawn, transparent, over the
|
|
131
|
+
# content). The only reliable way to hide it is to hide the system bars at
|
|
132
|
+
# runtime via WindowInsetsControllerCompat in MainActivity.kt.
|
|
133
|
+
activity_candidates = glob.glob(
|
|
134
|
+
'src-tauri/gen/android/app/src/main/**/MainActivity.kt', recursive=True
|
|
135
|
+
)
|
|
136
|
+
if not activity_candidates:
|
|
137
|
+
print('WARNING: MainActivity.kt not found — status bar hiding NOT patched')
|
|
138
|
+
else:
|
|
139
|
+
activity = activity_candidates[0]
|
|
140
|
+
with open(activity) as f:
|
|
113
141
|
content = f.read()
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
142
|
+
|
|
143
|
+
new_imports = [
|
|
144
|
+
'androidx.core.view.WindowCompat',
|
|
145
|
+
'androidx.core.view.WindowInsetsCompat',
|
|
146
|
+
'androidx.core.view.WindowInsetsControllerCompat',
|
|
147
|
+
]
|
|
148
|
+
import_lines = list(re.finditer(r'^import .+$', content, re.MULTILINE))
|
|
149
|
+
if import_lines:
|
|
150
|
+
insert_at = import_lines[-1].end()
|
|
151
|
+
addition = ''.join(
|
|
152
|
+
f'\nimport {imp}' for imp in new_imports if imp not in content
|
|
153
|
+
)
|
|
154
|
+
content = content[:insert_at] + addition + content[insert_at:]
|
|
155
|
+
|
|
156
|
+
if 'hideSystemBars' not in content:
|
|
157
|
+
content = content.replace(
|
|
158
|
+
'super.onCreate(savedInstanceState)',
|
|
159
|
+
'super.onCreate(savedInstanceState)\n hideSystemBars()',
|
|
160
|
+
1
|
|
161
|
+
)
|
|
162
|
+
content = re.sub(
|
|
163
|
+
r'\n}\s*$',
|
|
164
|
+
'\n\n'
|
|
165
|
+
' override fun onWindowFocusChanged(hasFocus: Boolean) {\n'
|
|
166
|
+
' super.onWindowFocusChanged(hasFocus)\n'
|
|
167
|
+
' if (hasFocus) {\n'
|
|
168
|
+
' hideSystemBars()\n'
|
|
169
|
+
' }\n'
|
|
170
|
+
' }\n'
|
|
171
|
+
'\n'
|
|
172
|
+
' private fun hideSystemBars() {\n'
|
|
173
|
+
' WindowCompat.setDecorFitsSystemWindows(window, false)\n'
|
|
174
|
+
' val controller = WindowInsetsControllerCompat(window, window.decorView)\n'
|
|
175
|
+
' controller.hide(WindowInsetsCompat.Type.systemBars())\n'
|
|
176
|
+
' controller.systemBarsBehavior =\n'
|
|
177
|
+
' WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE\n'
|
|
178
|
+
' }\n'
|
|
179
|
+
'}\n',
|
|
180
|
+
content,
|
|
181
|
+
count=1
|
|
182
|
+
)
|
|
183
|
+
with open(activity, 'w') as f:
|
|
121
184
|
f.write(content)
|
|
122
|
-
print(f'Patched {
|
|
185
|
+
print(f'Patched {activity} (hide system bars at runtime)')
|
|
123
186
|
PYEOF
|
|
124
187
|
|
|
125
188
|
- name: build Android app
|
|
@@ -14,7 +14,7 @@ import { useQuit } from "@/lib/hooks/quit-hooks";
|
|
|
14
14
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
15
15
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
16
16
|
import { cn } from "@/lib/utils";
|
|
17
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
17
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
18
18
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
19
19
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
20
20
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -239,7 +239,7 @@ export function ContinueMenuButton({
|
|
|
239
239
|
if (!lastSave) return;
|
|
240
240
|
setLoading(true);
|
|
241
241
|
onLoadingChange?.(true);
|
|
242
|
-
loadSave(lastSave)
|
|
242
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
243
243
|
.then(() =>
|
|
244
244
|
queryClient.invalidateQueries({
|
|
245
245
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -253,7 +253,7 @@ export function ContinueMenuButton({
|
|
|
253
253
|
setLoading(false);
|
|
254
254
|
onLoadingChange?.(false);
|
|
255
255
|
});
|
|
256
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
256
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
257
257
|
|
|
258
258
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
259
259
|
|
|
@@ -13,7 +13,7 @@ import { useGameProps } from "@/lib/hooks/props-hooks";
|
|
|
13
13
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
14
14
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
15
15
|
import { cn } from "@/lib/utils";
|
|
16
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
16
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
17
17
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
18
18
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
19
19
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -225,7 +225,7 @@ export function ContinueMenuButton({
|
|
|
225
225
|
if (!lastSave) return;
|
|
226
226
|
setLoading(true);
|
|
227
227
|
onLoadingChange?.(true);
|
|
228
|
-
loadSave(lastSave)
|
|
228
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
229
229
|
.then(() =>
|
|
230
230
|
queryClient.invalidateQueries({
|
|
231
231
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -239,7 +239,7 @@ export function ContinueMenuButton({
|
|
|
239
239
|
setLoading(false);
|
|
240
240
|
onLoadingChange?.(false);
|
|
241
241
|
});
|
|
242
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
242
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
243
243
|
|
|
244
244
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
245
245
|
|
|
@@ -13,7 +13,7 @@ import { useGameProps } from "@/lib/hooks/props-hooks";
|
|
|
13
13
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
14
14
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
15
15
|
import { cn } from "@/lib/utils";
|
|
16
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
16
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
17
17
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
18
18
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
19
19
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -225,7 +225,7 @@ export function ContinueMenuButton({
|
|
|
225
225
|
if (!lastSave) return;
|
|
226
226
|
setLoading(true);
|
|
227
227
|
onLoadingChange?.(true);
|
|
228
|
-
loadSave(lastSave)
|
|
228
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
229
229
|
.then(() =>
|
|
230
230
|
queryClient.invalidateQueries({
|
|
231
231
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -239,7 +239,7 @@ export function ContinueMenuButton({
|
|
|
239
239
|
setLoading(false);
|
|
240
240
|
onLoadingChange?.(false);
|
|
241
241
|
});
|
|
242
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
242
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
243
243
|
|
|
244
244
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
245
245
|
|
|
@@ -100,26 +100,89 @@ jobs:
|
|
|
100
100
|
with open(manifest, 'w') as f:
|
|
101
101
|
f.write(content)
|
|
102
102
|
|
|
103
|
-
# Tauri may generate styles.xml or themes.xml
|
|
103
|
+
# Tauri may generate styles.xml or themes.xml, and both a light (values/)
|
|
104
|
+
# and dark (values-night/) variant — patch every variant we find so the
|
|
105
|
+
# fullscreen flag doesn't silently no-op when the device is in dark mode.
|
|
104
106
|
styles_candidates = (
|
|
105
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
106
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
107
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/styles.xml') +
|
|
108
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/themes.xml')
|
|
107
109
|
)
|
|
108
110
|
if not styles_candidates:
|
|
109
111
|
print('Warning: no styles.xml/themes.xml found, skipping fullscreen patch')
|
|
110
112
|
else:
|
|
111
|
-
styles
|
|
112
|
-
|
|
113
|
+
for styles in styles_candidates:
|
|
114
|
+
with open(styles) as f:
|
|
115
|
+
content = f.read()
|
|
116
|
+
# Hide status bar (fullscreen) — kept as a best-effort theme hint,
|
|
117
|
+
# but on targetSdk 35+ (edge-to-edge is enforced by the OS) this
|
|
118
|
+
# alone has no effect; the real fix is the MainActivity.kt patch below.
|
|
119
|
+
content = content.replace(
|
|
120
|
+
'</style>',
|
|
121
|
+
' <item name="android:windowFullscreen">true</item>\n </style>',
|
|
122
|
+
1
|
|
123
|
+
)
|
|
124
|
+
with open(styles, 'w') as f:
|
|
125
|
+
f.write(content)
|
|
126
|
+
print(f'Patched {styles}')
|
|
127
|
+
|
|
128
|
+
# Since this project's Android template targets SDK 35+, edge-to-edge display
|
|
129
|
+
# is enforced by the OS and the theme-based windowFullscreen flag above no
|
|
130
|
+
# longer hides the status bar (it's always drawn, transparent, over the
|
|
131
|
+
# content). The only reliable way to hide it is to hide the system bars at
|
|
132
|
+
# runtime via WindowInsetsControllerCompat in MainActivity.kt.
|
|
133
|
+
activity_candidates = glob.glob(
|
|
134
|
+
'src-tauri/gen/android/app/src/main/**/MainActivity.kt', recursive=True
|
|
135
|
+
)
|
|
136
|
+
if not activity_candidates:
|
|
137
|
+
print('WARNING: MainActivity.kt not found — status bar hiding NOT patched')
|
|
138
|
+
else:
|
|
139
|
+
activity = activity_candidates[0]
|
|
140
|
+
with open(activity) as f:
|
|
113
141
|
content = f.read()
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
142
|
+
|
|
143
|
+
new_imports = [
|
|
144
|
+
'androidx.core.view.WindowCompat',
|
|
145
|
+
'androidx.core.view.WindowInsetsCompat',
|
|
146
|
+
'androidx.core.view.WindowInsetsControllerCompat',
|
|
147
|
+
]
|
|
148
|
+
import_lines = list(re.finditer(r'^import .+$', content, re.MULTILINE))
|
|
149
|
+
if import_lines:
|
|
150
|
+
insert_at = import_lines[-1].end()
|
|
151
|
+
addition = ''.join(
|
|
152
|
+
f'\nimport {imp}' for imp in new_imports if imp not in content
|
|
153
|
+
)
|
|
154
|
+
content = content[:insert_at] + addition + content[insert_at:]
|
|
155
|
+
|
|
156
|
+
if 'hideSystemBars' not in content:
|
|
157
|
+
content = content.replace(
|
|
158
|
+
'super.onCreate(savedInstanceState)',
|
|
159
|
+
'super.onCreate(savedInstanceState)\n hideSystemBars()',
|
|
160
|
+
1
|
|
161
|
+
)
|
|
162
|
+
content = re.sub(
|
|
163
|
+
r'\n}\s*$',
|
|
164
|
+
'\n\n'
|
|
165
|
+
' override fun onWindowFocusChanged(hasFocus: Boolean) {\n'
|
|
166
|
+
' super.onWindowFocusChanged(hasFocus)\n'
|
|
167
|
+
' if (hasFocus) {\n'
|
|
168
|
+
' hideSystemBars()\n'
|
|
169
|
+
' }\n'
|
|
170
|
+
' }\n'
|
|
171
|
+
'\n'
|
|
172
|
+
' private fun hideSystemBars() {\n'
|
|
173
|
+
' WindowCompat.setDecorFitsSystemWindows(window, false)\n'
|
|
174
|
+
' val controller = WindowInsetsControllerCompat(window, window.decorView)\n'
|
|
175
|
+
' controller.hide(WindowInsetsCompat.Type.systemBars())\n'
|
|
176
|
+
' controller.systemBarsBehavior =\n'
|
|
177
|
+
' WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE\n'
|
|
178
|
+
' }\n'
|
|
179
|
+
'}\n',
|
|
180
|
+
content,
|
|
181
|
+
count=1
|
|
182
|
+
)
|
|
183
|
+
with open(activity, 'w') as f:
|
|
121
184
|
f.write(content)
|
|
122
|
-
print(f'Patched {
|
|
185
|
+
print(f'Patched {activity} (hide system bars at runtime)')
|
|
123
186
|
PYEOF
|
|
124
187
|
|
|
125
188
|
- name: build Android app
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"license": "GPL-3.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@base-ui/react": "^1.6.0",
|
|
13
|
-
"@drincs/pixi-vn": "^1.8.
|
|
14
|
-
"@drincs/pixi-vn-ink": "^1.1.
|
|
13
|
+
"@drincs/pixi-vn": "^1.8.25",
|
|
14
|
+
"@drincs/pixi-vn-ink": "^1.1.9",
|
|
15
15
|
"@tailwindcss/vite": "^4.3.0",
|
|
16
16
|
"@tanstack/hotkeys": "^0.8.0",
|
|
17
17
|
"@tanstack/react-hotkeys": "^0.10.0",
|
|
@@ -2119,9 +2119,9 @@
|
|
|
2119
2119
|
}
|
|
2120
2120
|
},
|
|
2121
2121
|
"node_modules/@drincs/pixi-vn": {
|
|
2122
|
-
"version": "1.8.
|
|
2123
|
-
"resolved": "https://registry.npmjs.org/@drincs/pixi-vn/-/pixi-vn-1.8.
|
|
2124
|
-
"integrity": "sha512-
|
|
2122
|
+
"version": "1.8.25",
|
|
2123
|
+
"resolved": "https://registry.npmjs.org/@drincs/pixi-vn/-/pixi-vn-1.8.25.tgz",
|
|
2124
|
+
"integrity": "sha512-S+SwiYcKdx9hnK78vnj/TZhNrtnNxArPyBp+h82jPIrUMwytkPpSHFCvXltC6NyWEsIFqlpyXzPPw8rJDApR+Q==",
|
|
2125
2125
|
"license": "LGPL-2.1",
|
|
2126
2126
|
"workspaces": [
|
|
2127
2127
|
"sandbox"
|
|
@@ -2146,15 +2146,15 @@
|
|
|
2146
2146
|
}
|
|
2147
2147
|
},
|
|
2148
2148
|
"node_modules/@drincs/pixi-vn-ink": {
|
|
2149
|
-
"version": "1.1.
|
|
2150
|
-
"resolved": "https://registry.npmjs.org/@drincs/pixi-vn-ink/-/pixi-vn-ink-1.1.
|
|
2151
|
-
"integrity": "sha512-
|
|
2149
|
+
"version": "1.1.9",
|
|
2150
|
+
"resolved": "https://registry.npmjs.org/@drincs/pixi-vn-ink/-/pixi-vn-ink-1.1.9.tgz",
|
|
2151
|
+
"integrity": "sha512-GJdOg+W0gP7PRo1BmtJQns3Sw6FBQupRffi8tb9zozVtlYaQ9OnZAARI4qkGVvhfMNNR8g4C9rellq7FonNiRA==",
|
|
2152
2152
|
"license": "LGPL-2.1",
|
|
2153
2153
|
"workspaces": [
|
|
2154
2154
|
"playground"
|
|
2155
2155
|
],
|
|
2156
2156
|
"dependencies": {
|
|
2157
|
-
"@drincs/pixi-vn-json": "^1.13.
|
|
2157
|
+
"@drincs/pixi-vn-json": "^1.13.15"
|
|
2158
2158
|
},
|
|
2159
2159
|
"funding": {
|
|
2160
2160
|
"url": "https://github.com/DRincs-Productions/pixi-vn?sponsor=1"
|
|
@@ -2170,9 +2170,9 @@
|
|
|
2170
2170
|
}
|
|
2171
2171
|
},
|
|
2172
2172
|
"node_modules/@drincs/pixi-vn-json": {
|
|
2173
|
-
"version": "1.13.
|
|
2174
|
-
"resolved": "https://registry.npmjs.org/@drincs/pixi-vn-json/-/pixi-vn-json-1.13.
|
|
2175
|
-
"integrity": "sha512-
|
|
2173
|
+
"version": "1.13.17",
|
|
2174
|
+
"resolved": "https://registry.npmjs.org/@drincs/pixi-vn-json/-/pixi-vn-json-1.13.17.tgz",
|
|
2175
|
+
"integrity": "sha512-SIIdrMEUqOgIWRMk9Bx8XCg6Jngr5PMjkyYpQ6CM9S5GPk0Nl6RI1zctGuz6BOEssDuOmke5Q93UGb78EHYKoQ==",
|
|
2176
2176
|
"license": "LGPL-2.1",
|
|
2177
2177
|
"funding": {
|
|
2178
2178
|
"url": "https://github.com/DRincs-Productions/pixi-vn?sponsor=1"
|
|
@@ -14,7 +14,7 @@ import { useQuit } from "@/lib/hooks/quit-hooks";
|
|
|
14
14
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
15
15
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
16
16
|
import { cn } from "@/lib/utils";
|
|
17
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
17
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
18
18
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
19
19
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
20
20
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -240,7 +240,7 @@ export function ContinueMenuButton({
|
|
|
240
240
|
if (!lastSave) return;
|
|
241
241
|
setLoading(true);
|
|
242
242
|
onLoadingChange?.(true);
|
|
243
|
-
loadSave(lastSave)
|
|
243
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
244
244
|
.then(() =>
|
|
245
245
|
queryClient.invalidateQueries({
|
|
246
246
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -254,7 +254,7 @@ export function ContinueMenuButton({
|
|
|
254
254
|
setLoading(false);
|
|
255
255
|
onLoadingChange?.(false);
|
|
256
256
|
});
|
|
257
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
257
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
258
258
|
|
|
259
259
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
260
260
|
|
|
@@ -100,26 +100,89 @@ jobs:
|
|
|
100
100
|
with open(manifest, 'w') as f:
|
|
101
101
|
f.write(content)
|
|
102
102
|
|
|
103
|
-
# Tauri may generate styles.xml or themes.xml
|
|
103
|
+
# Tauri may generate styles.xml or themes.xml, and both a light (values/)
|
|
104
|
+
# and dark (values-night/) variant — patch every variant we find so the
|
|
105
|
+
# fullscreen flag doesn't silently no-op when the device is in dark mode.
|
|
104
106
|
styles_candidates = (
|
|
105
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
106
|
-
glob.glob('src-tauri/gen/android/app/src/main/res/values
|
|
107
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/styles.xml') +
|
|
108
|
+
glob.glob('src-tauri/gen/android/app/src/main/res/values*/themes.xml')
|
|
107
109
|
)
|
|
108
110
|
if not styles_candidates:
|
|
109
111
|
print('Warning: no styles.xml/themes.xml found, skipping fullscreen patch')
|
|
110
112
|
else:
|
|
111
|
-
styles
|
|
112
|
-
|
|
113
|
+
for styles in styles_candidates:
|
|
114
|
+
with open(styles) as f:
|
|
115
|
+
content = f.read()
|
|
116
|
+
# Hide status bar (fullscreen) — kept as a best-effort theme hint,
|
|
117
|
+
# but on targetSdk 35+ (edge-to-edge is enforced by the OS) this
|
|
118
|
+
# alone has no effect; the real fix is the MainActivity.kt patch below.
|
|
119
|
+
content = content.replace(
|
|
120
|
+
'</style>',
|
|
121
|
+
' <item name="android:windowFullscreen">true</item>\n </style>',
|
|
122
|
+
1
|
|
123
|
+
)
|
|
124
|
+
with open(styles, 'w') as f:
|
|
125
|
+
f.write(content)
|
|
126
|
+
print(f'Patched {styles}')
|
|
127
|
+
|
|
128
|
+
# Since this project's Android template targets SDK 35+, edge-to-edge display
|
|
129
|
+
# is enforced by the OS and the theme-based windowFullscreen flag above no
|
|
130
|
+
# longer hides the status bar (it's always drawn, transparent, over the
|
|
131
|
+
# content). The only reliable way to hide it is to hide the system bars at
|
|
132
|
+
# runtime via WindowInsetsControllerCompat in MainActivity.kt.
|
|
133
|
+
activity_candidates = glob.glob(
|
|
134
|
+
'src-tauri/gen/android/app/src/main/**/MainActivity.kt', recursive=True
|
|
135
|
+
)
|
|
136
|
+
if not activity_candidates:
|
|
137
|
+
print('WARNING: MainActivity.kt not found — status bar hiding NOT patched')
|
|
138
|
+
else:
|
|
139
|
+
activity = activity_candidates[0]
|
|
140
|
+
with open(activity) as f:
|
|
113
141
|
content = f.read()
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
142
|
+
|
|
143
|
+
new_imports = [
|
|
144
|
+
'androidx.core.view.WindowCompat',
|
|
145
|
+
'androidx.core.view.WindowInsetsCompat',
|
|
146
|
+
'androidx.core.view.WindowInsetsControllerCompat',
|
|
147
|
+
]
|
|
148
|
+
import_lines = list(re.finditer(r'^import .+$', content, re.MULTILINE))
|
|
149
|
+
if import_lines:
|
|
150
|
+
insert_at = import_lines[-1].end()
|
|
151
|
+
addition = ''.join(
|
|
152
|
+
f'\nimport {imp}' for imp in new_imports if imp not in content
|
|
153
|
+
)
|
|
154
|
+
content = content[:insert_at] + addition + content[insert_at:]
|
|
155
|
+
|
|
156
|
+
if 'hideSystemBars' not in content:
|
|
157
|
+
content = content.replace(
|
|
158
|
+
'super.onCreate(savedInstanceState)',
|
|
159
|
+
'super.onCreate(savedInstanceState)\n hideSystemBars()',
|
|
160
|
+
1
|
|
161
|
+
)
|
|
162
|
+
content = re.sub(
|
|
163
|
+
r'\n}\s*$',
|
|
164
|
+
'\n\n'
|
|
165
|
+
' override fun onWindowFocusChanged(hasFocus: Boolean) {\n'
|
|
166
|
+
' super.onWindowFocusChanged(hasFocus)\n'
|
|
167
|
+
' if (hasFocus) {\n'
|
|
168
|
+
' hideSystemBars()\n'
|
|
169
|
+
' }\n'
|
|
170
|
+
' }\n'
|
|
171
|
+
'\n'
|
|
172
|
+
' private fun hideSystemBars() {\n'
|
|
173
|
+
' WindowCompat.setDecorFitsSystemWindows(window, false)\n'
|
|
174
|
+
' val controller = WindowInsetsControllerCompat(window, window.decorView)\n'
|
|
175
|
+
' controller.hide(WindowInsetsCompat.Type.systemBars())\n'
|
|
176
|
+
' controller.systemBarsBehavior =\n'
|
|
177
|
+
' WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE\n'
|
|
178
|
+
' }\n'
|
|
179
|
+
'}\n',
|
|
180
|
+
content,
|
|
181
|
+
count=1
|
|
182
|
+
)
|
|
183
|
+
with open(activity, 'w') as f:
|
|
121
184
|
f.write(content)
|
|
122
|
-
print(f'Patched {
|
|
185
|
+
print(f'Patched {activity} (hide system bars at runtime)')
|
|
123
186
|
PYEOF
|
|
124
187
|
|
|
125
188
|
- name: build Android app
|
|
@@ -14,7 +14,7 @@ import { useQuit } from "@/lib/hooks/quit-hooks";
|
|
|
14
14
|
import { useQueryLastSave } from "@/lib/query/save-query";
|
|
15
15
|
import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
|
|
16
16
|
import { cn } from "@/lib/utils";
|
|
17
|
-
import { loadSave } from "@/lib/utils/save-utility";
|
|
17
|
+
import { loadRefreshSave, loadSave } from "@/lib/utils/save-utility";
|
|
18
18
|
import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
|
|
19
19
|
import { useHotkeys } from "@tanstack/react-hotkeys";
|
|
20
20
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -240,7 +240,7 @@ export function ContinueMenuButton({
|
|
|
240
240
|
if (!lastSave) return;
|
|
241
241
|
setLoading(true);
|
|
242
242
|
onLoadingChange?.(true);
|
|
243
|
-
loadSave(lastSave)
|
|
243
|
+
(hasRefreshSave ? loadRefreshSave() : loadSave(lastSave))
|
|
244
244
|
.then(() =>
|
|
245
245
|
queryClient.invalidateQueries({
|
|
246
246
|
queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
|
|
@@ -254,7 +254,7 @@ export function ContinueMenuButton({
|
|
|
254
254
|
setLoading(false);
|
|
255
255
|
onLoadingChange?.(false);
|
|
256
256
|
});
|
|
257
|
-
}, [lastSave, queryClient, t, onLoadingChange]);
|
|
257
|
+
}, [lastSave, hasRefreshSave, queryClient, t, onLoadingChange]);
|
|
258
258
|
|
|
259
259
|
const isDisabled = (!isLoading && !lastSave) || loading || disabled;
|
|
260
260
|
|