create-pixi-vn 2.0.12 → 2.0.13

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 (114) hide show
  1. package/package.json +1 -1
  2. package/template-react-vite-muijoy-ink/.vscode/extensions.json +2 -1
  3. package/template-react-vite-muijoy-ink/.vscode/settings.json +6 -1
  4. package/template-react-vite-muijoy-ink/_gitignore +1 -0
  5. package/template-react-vite-muijoy-ink/ink/second_part.ink +571 -0
  6. package/template-react-vite-muijoy-ink/ink/start.ink +214 -0
  7. package/template-react-vite-muijoy-ink/package-lock.json +230 -4
  8. package/template-react-vite-muijoy-ink/package.json +3 -1
  9. package/template-react-vite-muijoy-ink/src/App.tsx +25 -25
  10. package/template-react-vite-muijoy-ink/src/assets/index.ts +2 -4
  11. package/template-react-vite-muijoy-ink/src/assets/ink-manifest.gen.json +4 -1
  12. package/template-react-vite-muijoy-ink/src/content/ink/hashtag-commands.ts +38 -0
  13. package/template-react-vite-muijoy-ink/src/content/ink/text-replaces.ts +19 -0
  14. package/template-react-vite-muijoy-ink/src/lib/hooks/ink-hooks.tsx +12 -0
  15. package/template-react-vite-muijoy-ink/src/lib/i18n.ts +22 -1
  16. package/template-react-vite-muijoy-ink/src/pixi-vn-keys.gen.d.ts +2 -0
  17. package/template-react-vite-muijoy-ink/src/routes/__root.tsx +4 -0
  18. package/template-react-vite-muijoy-ink/vite.config.ts +6 -0
  19. package/template-react-vite-muijoy-ink-tauri/.assetpack.ts +9 -0
  20. package/template-react-vite-muijoy-ink-tauri/.vscode/extensions.json +5 -1
  21. package/template-react-vite-muijoy-ink-tauri/.vscode/launch.json +11 -0
  22. package/template-react-vite-muijoy-ink-tauri/.vscode/settings.json +6 -1
  23. package/template-react-vite-muijoy-ink-tauri/.vscode/tasks.json +47 -0
  24. package/template-react-vite-muijoy-ink-tauri/README.md +3 -3
  25. package/template-react-vite-muijoy-ink-tauri/_github/workflows/desktop.yml +188 -0
  26. package/template-react-vite-muijoy-ink-tauri/_github/workflows/mobile.yml +270 -0
  27. package/template-react-vite-muijoy-ink-tauri/_gitignore +11 -0
  28. package/template-react-vite-muijoy-ink-tauri/ink/second_part.ink +571 -0
  29. package/template-react-vite-muijoy-ink-tauri/ink/start.ink +214 -0
  30. package/template-react-vite-muijoy-ink-tauri/package-lock.json +480 -4
  31. package/template-react-vite-muijoy-ink-tauri/package.json +13 -2
  32. package/template-react-vite-muijoy-ink-tauri/src/App.tsx +25 -25
  33. package/template-react-vite-muijoy-ink-tauri/src/assets/index.ts +2 -4
  34. package/template-react-vite-muijoy-ink-tauri/src/assets/ink-manifest.gen.json +4 -1
  35. package/template-react-vite-muijoy-ink-tauri/src/components/menus/main-menu.tsx +16 -1
  36. package/template-react-vite-muijoy-ink-tauri/src/components/menus/settings/quick-menus.tsx +17 -1
  37. package/template-react-vite-muijoy-ink-tauri/src/components/menus/settings/system-controls.tsx +11 -1
  38. package/template-react-vite-muijoy-ink-tauri/src/content/ink/hashtag-commands.ts +55 -0
  39. package/template-react-vite-muijoy-ink-tauri/src/content/ink/text-replaces.ts +19 -0
  40. package/template-react-vite-muijoy-ink-tauri/src/lib/hooks/ink-hooks.tsx +12 -0
  41. package/template-react-vite-muijoy-ink-tauri/src/lib/hooks/quit-hooks.ts +24 -0
  42. package/template-react-vite-muijoy-ink-tauri/src/lib/i18n.ts +22 -1
  43. package/template-react-vite-muijoy-ink-tauri/src/lib/query/settings-query.ts +7 -1
  44. package/template-react-vite-muijoy-ink-tauri/src/lib/steam.ts +143 -0
  45. package/template-react-vite-muijoy-ink-tauri/src/pixi-vn-keys.gen.d.ts +2 -0
  46. package/template-react-vite-muijoy-ink-tauri/src/routes/__root.tsx +4 -0
  47. package/template-react-vite-muijoy-ink-tauri/src-tauri/Cargo.toml +50 -0
  48. package/template-react-vite-muijoy-ink-tauri/src-tauri/build.rs +46 -0
  49. package/template-react-vite-muijoy-ink-tauri/src-tauri/capabilities/default.json +21 -0
  50. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/128x128.png +0 -0
  51. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/128x128@2x.png +0 -0
  52. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/32x32.png +0 -0
  53. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square107x107Logo.png +0 -0
  54. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square142x142Logo.png +0 -0
  55. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square150x150Logo.png +0 -0
  56. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square284x284Logo.png +0 -0
  57. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square30x30Logo.png +0 -0
  58. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square310x310Logo.png +0 -0
  59. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square44x44Logo.png +0 -0
  60. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square71x71Logo.png +0 -0
  61. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/Square89x89Logo.png +0 -0
  62. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/StoreLogo.png +0 -0
  63. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/icon.icns +0 -0
  64. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/icon.ico +0 -0
  65. package/template-react-vite-muijoy-ink-tauri/src-tauri/icons/icon.png +0 -0
  66. package/template-react-vite-muijoy-ink-tauri/src-tauri/src/lib.rs +64 -0
  67. package/template-react-vite-muijoy-ink-tauri/src-tauri/src/main.rs +6 -0
  68. package/template-react-vite-muijoy-ink-tauri/src-tauri/src/steam.rs +238 -0
  69. package/template-react-vite-muijoy-ink-tauri/src-tauri/tauri.conf.json +50 -0
  70. package/template-react-vite-muijoy-ink-tauri/vite.config.ts +30 -0
  71. package/template-react-vite-muijoy-tauri/.assetpack.ts +9 -0
  72. package/template-react-vite-muijoy-tauri/.vscode/extensions.json +4 -1
  73. package/template-react-vite-muijoy-tauri/.vscode/launch.json +11 -0
  74. package/template-react-vite-muijoy-tauri/.vscode/tasks.json +47 -0
  75. package/template-react-vite-muijoy-tauri/README.md +3 -3
  76. package/template-react-vite-muijoy-tauri/_github/workflows/desktop.yml +188 -0
  77. package/template-react-vite-muijoy-tauri/_github/workflows/mobile.yml +270 -0
  78. package/template-react-vite-muijoy-tauri/_gitignore +10 -0
  79. package/template-react-vite-muijoy-tauri/package-lock.json +250 -0
  80. package/template-react-vite-muijoy-tauri/package.json +10 -1
  81. package/template-react-vite-muijoy-tauri/src/components/menus/main-menu.tsx +16 -1
  82. package/template-react-vite-muijoy-tauri/src/components/menus/settings/quick-menus.tsx +17 -1
  83. package/template-react-vite-muijoy-tauri/src/components/menus/settings/system-controls.tsx +11 -1
  84. package/template-react-vite-muijoy-tauri/src/lib/hooks/quit-hooks.ts +24 -0
  85. package/template-react-vite-muijoy-tauri/src/lib/query/settings-query.ts +7 -1
  86. package/template-react-vite-muijoy-tauri/src/lib/steam.ts +143 -0
  87. package/template-react-vite-muijoy-tauri/src-tauri/Cargo.toml +50 -0
  88. package/template-react-vite-muijoy-tauri/src-tauri/build.rs +46 -0
  89. package/template-react-vite-muijoy-tauri/src-tauri/capabilities/default.json +21 -0
  90. package/template-react-vite-muijoy-tauri/src-tauri/icons/128x128.png +0 -0
  91. package/template-react-vite-muijoy-tauri/src-tauri/icons/128x128@2x.png +0 -0
  92. package/template-react-vite-muijoy-tauri/src-tauri/icons/32x32.png +0 -0
  93. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square107x107Logo.png +0 -0
  94. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square142x142Logo.png +0 -0
  95. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square150x150Logo.png +0 -0
  96. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square284x284Logo.png +0 -0
  97. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square30x30Logo.png +0 -0
  98. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square310x310Logo.png +0 -0
  99. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square44x44Logo.png +0 -0
  100. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square71x71Logo.png +0 -0
  101. package/template-react-vite-muijoy-tauri/src-tauri/icons/Square89x89Logo.png +0 -0
  102. package/template-react-vite-muijoy-tauri/src-tauri/icons/StoreLogo.png +0 -0
  103. package/template-react-vite-muijoy-tauri/src-tauri/icons/icon.icns +0 -0
  104. package/template-react-vite-muijoy-tauri/src-tauri/icons/icon.ico +0 -0
  105. package/template-react-vite-muijoy-tauri/src-tauri/icons/icon.png +0 -0
  106. package/template-react-vite-muijoy-tauri/src-tauri/src/lib.rs +64 -0
  107. package/template-react-vite-muijoy-tauri/src-tauri/src/main.rs +6 -0
  108. package/template-react-vite-muijoy-tauri/src-tauri/src/steam.rs +238 -0
  109. package/template-react-vite-muijoy-tauri/src-tauri/tauri.conf.json +50 -0
  110. package/template-react-vite-muijoy-tauri/vite.config.ts +24 -0
  111. package/template-react-vite-muijoy-ink/src/content/labels/second.label.ts +0 -1207
  112. package/template-react-vite-muijoy-ink/src/content/labels/start.label.ts +0 -566
  113. package/template-react-vite-muijoy-ink-tauri/src/content/labels/second.label.ts +0 -1207
  114. package/template-react-vite-muijoy-ink-tauri/src/content/labels/start.label.ts +0 -566
@@ -26,6 +26,8 @@
26
26
  "@tanstack/react-store": "latest",
27
27
  "@tanstack/router-plugin": "latest",
28
28
  "@tanstack/store": "latest",
29
+ "@tauri-apps/api": "^2",
30
+ "@tauri-apps/plugin-opener": "^2",
29
31
  "@unpic/react": "^1.0.2",
30
32
  "class-variance-authority": "^0.7.1",
31
33
  "clsx": "^2.1.1",
@@ -59,6 +61,8 @@
59
61
  "@biomejs/biome": "latest",
60
62
  "@tailwindcss/typography": "^0.5.19",
61
63
  "@tanstack/devtools-vite": "latest",
64
+ "@tauri-apps/cli": "^2",
65
+ "@tauri-apps/plugin-process": "^2.3.1",
62
66
  "@types/node": "^25.9.1",
63
67
  "@types/react": "^19.2.15",
64
68
  "@types/react-dom": "^19.2.3",
@@ -6660,6 +6664,252 @@
6660
6664
  "url": "https://github.com/sponsors/tannerlinsley"
6661
6665
  }
6662
6666
  },
6667
+ "node_modules/@tauri-apps/api": {
6668
+ "version": "2.11.0",
6669
+ "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.0.tgz",
6670
+ "integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==",
6671
+ "license": "Apache-2.0 OR MIT",
6672
+ "funding": {
6673
+ "type": "opencollective",
6674
+ "url": "https://opencollective.com/tauri"
6675
+ }
6676
+ },
6677
+ "node_modules/@tauri-apps/cli": {
6678
+ "version": "2.11.2",
6679
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.2.tgz",
6680
+ "integrity": "sha512-bk3HemqvGRoy+5D/dVMUQHKMYLglD0jVnMm/0iGMH6ufZ+p8r14m6BpIixwij3PBvZdvORUp1YifTD8QxVZ1Nw==",
6681
+ "dev": true,
6682
+ "license": "Apache-2.0 OR MIT",
6683
+ "bin": {
6684
+ "tauri": "tauri.js"
6685
+ },
6686
+ "engines": {
6687
+ "node": ">= 10"
6688
+ },
6689
+ "funding": {
6690
+ "type": "opencollective",
6691
+ "url": "https://opencollective.com/tauri"
6692
+ },
6693
+ "optionalDependencies": {
6694
+ "@tauri-apps/cli-darwin-arm64": "2.11.2",
6695
+ "@tauri-apps/cli-darwin-x64": "2.11.2",
6696
+ "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.2",
6697
+ "@tauri-apps/cli-linux-arm64-gnu": "2.11.2",
6698
+ "@tauri-apps/cli-linux-arm64-musl": "2.11.2",
6699
+ "@tauri-apps/cli-linux-riscv64-gnu": "2.11.2",
6700
+ "@tauri-apps/cli-linux-x64-gnu": "2.11.2",
6701
+ "@tauri-apps/cli-linux-x64-musl": "2.11.2",
6702
+ "@tauri-apps/cli-win32-arm64-msvc": "2.11.2",
6703
+ "@tauri-apps/cli-win32-ia32-msvc": "2.11.2",
6704
+ "@tauri-apps/cli-win32-x64-msvc": "2.11.2"
6705
+ }
6706
+ },
6707
+ "node_modules/@tauri-apps/cli-darwin-arm64": {
6708
+ "version": "2.11.2",
6709
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.2.tgz",
6710
+ "integrity": "sha512-+4UZzLt+eOAEQCwgd+TqKgyUJMrvx+BgdXLLaqJYmPqzP+nE6YZr/hY6CWLYGQb8jFn99jEkmC6uA3tNvamA1w==",
6711
+ "cpu": [
6712
+ "arm64"
6713
+ ],
6714
+ "dev": true,
6715
+ "license": "Apache-2.0 OR MIT",
6716
+ "optional": true,
6717
+ "os": [
6718
+ "darwin"
6719
+ ],
6720
+ "engines": {
6721
+ "node": ">= 10"
6722
+ }
6723
+ },
6724
+ "node_modules/@tauri-apps/cli-darwin-x64": {
6725
+ "version": "2.11.2",
6726
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.2.tgz",
6727
+ "integrity": "sha512-VjYYtZUPqDMLutSfJEyxFE3Bz+DPi7c8wC3imckgvciLDZLq4qwKJxBicg0BXGhXjJsl8vKWgWRFNMPELQ+Xyg==",
6728
+ "cpu": [
6729
+ "x64"
6730
+ ],
6731
+ "dev": true,
6732
+ "license": "Apache-2.0 OR MIT",
6733
+ "optional": true,
6734
+ "os": [
6735
+ "darwin"
6736
+ ],
6737
+ "engines": {
6738
+ "node": ">= 10"
6739
+ }
6740
+ },
6741
+ "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
6742
+ "version": "2.11.2",
6743
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.2.tgz",
6744
+ "integrity": "sha512-yMemD6f4i95AQriS8EazyOFzbE34yjnP16i3IOzpHGQvBoy2DjypFMFBq0NtPuITURv/cOGguRtHR5d79/9CSA==",
6745
+ "cpu": [
6746
+ "arm"
6747
+ ],
6748
+ "dev": true,
6749
+ "license": "Apache-2.0 OR MIT",
6750
+ "optional": true,
6751
+ "os": [
6752
+ "linux"
6753
+ ],
6754
+ "engines": {
6755
+ "node": ">= 10"
6756
+ }
6757
+ },
6758
+ "node_modules/@tauri-apps/cli-linux-arm64-gnu": {
6759
+ "version": "2.11.2",
6760
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.2.tgz",
6761
+ "integrity": "sha512-cgI91D2wL8GSgoWwZXDqt+DwnuZCP2/bz03QAE4TrhgAKIsrB4hX26W/H1EONPUUNkqrsgeCD0wU6pcNjV/5kw==",
6762
+ "cpu": [
6763
+ "arm64"
6764
+ ],
6765
+ "dev": true,
6766
+ "license": "Apache-2.0 OR MIT",
6767
+ "optional": true,
6768
+ "os": [
6769
+ "linux"
6770
+ ],
6771
+ "engines": {
6772
+ "node": ">= 10"
6773
+ }
6774
+ },
6775
+ "node_modules/@tauri-apps/cli-linux-arm64-musl": {
6776
+ "version": "2.11.2",
6777
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.2.tgz",
6778
+ "integrity": "sha512-X1rm0BERqAAggtYTESSgXrS3sz4Sb/OiPiz54UqISlXW+GkR3vNIGnsy/lejNmoXGVqri3Q53BCfQiclOIyRPw==",
6779
+ "cpu": [
6780
+ "arm64"
6781
+ ],
6782
+ "dev": true,
6783
+ "license": "Apache-2.0 OR MIT",
6784
+ "optional": true,
6785
+ "os": [
6786
+ "linux"
6787
+ ],
6788
+ "engines": {
6789
+ "node": ">= 10"
6790
+ }
6791
+ },
6792
+ "node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
6793
+ "version": "2.11.2",
6794
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.2.tgz",
6795
+ "integrity": "sha512-usbMLJbT3KtkOrBMDVeGYNM35aTHXx38SJSzTMSqqjeUIOQ+iVPjb2yAGNAE+KqmBbAx4FOFIyMeKXx2M/JKGQ==",
6796
+ "cpu": [
6797
+ "riscv64"
6798
+ ],
6799
+ "dev": true,
6800
+ "license": "Apache-2.0 OR MIT",
6801
+ "optional": true,
6802
+ "os": [
6803
+ "linux"
6804
+ ],
6805
+ "engines": {
6806
+ "node": ">= 10"
6807
+ }
6808
+ },
6809
+ "node_modules/@tauri-apps/cli-linux-x64-gnu": {
6810
+ "version": "2.11.2",
6811
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.2.tgz",
6812
+ "integrity": "sha512-Ru4gwJKPG0ctVGchRGpRup4Y4lW2SSfFnrbQcyHhCliKy4g8Qz97TrUgCur4CbWyAgKxvGh3SjrkA0LDYzDGiw==",
6813
+ "cpu": [
6814
+ "x64"
6815
+ ],
6816
+ "dev": true,
6817
+ "license": "Apache-2.0 OR MIT",
6818
+ "optional": true,
6819
+ "os": [
6820
+ "linux"
6821
+ ],
6822
+ "engines": {
6823
+ "node": ">= 10"
6824
+ }
6825
+ },
6826
+ "node_modules/@tauri-apps/cli-linux-x64-musl": {
6827
+ "version": "2.11.2",
6828
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.2.tgz",
6829
+ "integrity": "sha512-eUm7T6clN1MMmNSRQ9gaWsQdyehQx2Gmn5hht/QUlqZQI/qcP2OJK5dnaxqwFzCr2HdsEo9ydxaqcS1oJzMvUw==",
6830
+ "cpu": [
6831
+ "x64"
6832
+ ],
6833
+ "dev": true,
6834
+ "license": "Apache-2.0 OR MIT",
6835
+ "optional": true,
6836
+ "os": [
6837
+ "linux"
6838
+ ],
6839
+ "engines": {
6840
+ "node": ">= 10"
6841
+ }
6842
+ },
6843
+ "node_modules/@tauri-apps/cli-win32-arm64-msvc": {
6844
+ "version": "2.11.2",
6845
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.2.tgz",
6846
+ "integrity": "sha512-HeeZW80jU+gVTOEX4X/hC6NVSAdDVXajwP5fxIZ/3z9WvUC7qrudX2GMTilYq6Dg0e0sk0XgsAJD1hZ5wPBXUA==",
6847
+ "cpu": [
6848
+ "arm64"
6849
+ ],
6850
+ "dev": true,
6851
+ "license": "Apache-2.0 OR MIT",
6852
+ "optional": true,
6853
+ "os": [
6854
+ "win32"
6855
+ ],
6856
+ "engines": {
6857
+ "node": ">= 10"
6858
+ }
6859
+ },
6860
+ "node_modules/@tauri-apps/cli-win32-ia32-msvc": {
6861
+ "version": "2.11.2",
6862
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.2.tgz",
6863
+ "integrity": "sha512-YhjQNZcXfbkCLyazSv1nPnJ9iRFE1wm6kc51FDbU10/Dk09io+6PAGMLjkxnX2GdM0qMnDmTjstY8mTDVvtKeA==",
6864
+ "cpu": [
6865
+ "ia32"
6866
+ ],
6867
+ "dev": true,
6868
+ "license": "Apache-2.0 OR MIT",
6869
+ "optional": true,
6870
+ "os": [
6871
+ "win32"
6872
+ ],
6873
+ "engines": {
6874
+ "node": ">= 10"
6875
+ }
6876
+ },
6877
+ "node_modules/@tauri-apps/cli-win32-x64-msvc": {
6878
+ "version": "2.11.2",
6879
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.2.tgz",
6880
+ "integrity": "sha512-d2JchlFIpZevZVReyqhQOekJmb1UH3rhZ5VX6sH3ty9ETE0TKQavpihvoScUXfKKpW6HZC0MrFGRU0ZtD+w3gA==",
6881
+ "cpu": [
6882
+ "x64"
6883
+ ],
6884
+ "dev": true,
6885
+ "license": "Apache-2.0 OR MIT",
6886
+ "optional": true,
6887
+ "os": [
6888
+ "win32"
6889
+ ],
6890
+ "engines": {
6891
+ "node": ">= 10"
6892
+ }
6893
+ },
6894
+ "node_modules/@tauri-apps/plugin-opener": {
6895
+ "version": "2.5.4",
6896
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz",
6897
+ "integrity": "sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==",
6898
+ "license": "MIT OR Apache-2.0",
6899
+ "dependencies": {
6900
+ "@tauri-apps/api": "^2.11.0"
6901
+ }
6902
+ },
6903
+ "node_modules/@tauri-apps/plugin-process": {
6904
+ "version": "2.3.1",
6905
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.3.1.tgz",
6906
+ "integrity": "sha512-nCa4fGVaDL/B9ai03VyPOjfAHRHSBz5v6F/ObsB73r/dA3MHHhZtldaDMIc0V/pnUw9ehzr2iEG+XkSEyC0JJA==",
6907
+ "dev": true,
6908
+ "license": "MIT OR Apache-2.0",
6909
+ "dependencies": {
6910
+ "@tauri-apps/api": "^2.8.0"
6911
+ }
6912
+ },
6663
6913
  "node_modules/@tokenizer/inflate": {
6664
6914
  "version": "0.4.1",
6665
6915
  "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
@@ -11,7 +11,12 @@
11
11
  "build": "tsc -b && vite build",
12
12
  "build:fast": "vite build",
13
13
  "prebuild": "npm run icon",
14
- "icon": "pwa-assets-generator",
14
+ "icon": "pwa-assets-generator && tauri icon public/icon.png",
15
+ "tauri": "tauri",
16
+ "tauri:dev": "tauri dev",
17
+ "tauri:build": "tauri build",
18
+ "tauri:android:dev": "tauri android dev",
19
+ "tauri:ios:dev": "tauri ios dev",
15
20
  "lint": "biome lint",
16
21
  "check": "biome check",
17
22
  "format": "biome format --write",
@@ -35,6 +40,8 @@
35
40
  "@tanstack/react-store": "latest",
36
41
  "@tanstack/router-plugin": "latest",
37
42
  "@tanstack/store": "latest",
43
+ "@tauri-apps/api": "^2",
44
+ "@tauri-apps/plugin-opener": "^2",
38
45
  "@unpic/react": "^1.0.2",
39
46
  "class-variance-authority": "^0.7.1",
40
47
  "clsx": "^2.1.1",
@@ -68,6 +75,8 @@
68
75
  "@biomejs/biome": "latest",
69
76
  "@tailwindcss/typography": "^0.5.19",
70
77
  "@tanstack/devtools-vite": "latest",
78
+ "@tauri-apps/cli": "^2",
79
+ "@tauri-apps/plugin-process": "^2.3.1",
71
80
  "@types/node": "^25.9.1",
72
81
  "@types/react": "^19.2.15",
73
82
  "@types/react-dom": "^19.2.3",
@@ -10,6 +10,7 @@ import {
10
10
  } from "@/constants";
11
11
  import { useSetSearchParamState } from "@/lib/hooks/navigation-hooks";
12
12
  import { useGameProps } from "@/lib/hooks/props-hooks";
13
+ import { useQuit } from "@/lib/hooks/quit-hooks";
13
14
  import { useQueryLastSave } from "@/lib/query/save-query";
14
15
  import { InterfaceSettings } from "@/lib/stores/interface-settings-store";
15
16
  import { cn } from "@/lib/utils";
@@ -17,7 +18,7 @@ import { loadSave } from "@/lib/utils/save-utility";
17
18
  import { canvas, Game, ImageSprite } from "@drincs/pixi-vn";
18
19
  import { useHotkeys } from "@tanstack/react-hotkeys";
19
20
  import { useQueryClient } from "@tanstack/react-query";
20
- import { AlertCircle, CirclePlay, Play, Save, Settings } from "lucide-react";
21
+ import { AlertCircle, CirclePlay, LogOut, Play, Save, Settings } from "lucide-react";
21
22
  import { useCallback, useEffect, useRef, useState } from "react";
22
23
  import { useTranslation } from "react-i18next";
23
24
  import { toast } from "sonner";
@@ -33,6 +34,7 @@ export function MainMenu() {
33
34
  const setSettingsTab = useSetSearchParamState<string>("settings_tab");
34
35
  const [loading, setLoading] = useState(false);
35
36
  const menuRef = useRef<HTMLDivElement>(null);
37
+ const { quit, canQuit } = useQuit();
36
38
 
37
39
  /** Returns all enabled menuitem buttons inside the menu container. */
38
40
  function getMenuItems(): HTMLButtonElement[] {
@@ -186,6 +188,19 @@ export function MainMenu() {
186
188
  {t("settings")}
187
189
  </Button>
188
190
 
191
+ {canQuit && (
192
+ <Button
193
+ role="menuitem"
194
+ onClick={quit}
195
+ disabled={loading}
196
+ variant="outline"
197
+ className={menuButtonClass}
198
+ >
199
+ <LogOut className="size-4" />
200
+ {t("quit")}
201
+ </Button>
202
+ )}
203
+
189
204
  {loading ? (
190
205
  <div
191
206
  className="flex items-center justify-end pt-1 text-muted-foreground"
@@ -3,9 +3,10 @@ import { Button } from "@/components/ui/button";
3
3
  import { Kbd, KbdGroup } from "@/components/ui/kbd";
4
4
  import { Separator } from "@/components/ui/separator";
5
5
  import { useSetSearchParamState } from "@/lib/hooks/navigation-hooks";
6
+ import { useQuit } from "@/lib/hooks/quit-hooks";
6
7
  import { Game } from "@drincs/pixi-vn";
7
8
  import { useLocation, useNavigate } from "@tanstack/react-router";
8
- import { Gamepad2Icon, HistoryIcon, LogOutIcon, SaveIcon } from "lucide-react";
9
+ import { Gamepad2Icon, HistoryIcon, LogOutIcon, PowerIcon, SaveIcon } from "lucide-react";
9
10
  import { useTranslation } from "react-i18next";
10
11
 
11
12
  export function QuickMenus() {
@@ -21,6 +22,7 @@ export function QuickMenus() {
21
22
  </div>
22
23
  {isInGame && <Separator />}
23
24
  {isInGame && <ReturnMainMenuButton />}
25
+ <QuitButton />
24
26
  </div>
25
27
  );
26
28
  }
@@ -101,6 +103,20 @@ export function OpenHistorySettingButton() {
101
103
  );
102
104
  }
103
105
 
106
+ export function QuitButton() {
107
+ const { t } = useTranslation(["ui"]);
108
+ const { quit, canQuit } = useQuit();
109
+
110
+ if (!canQuit) return null;
111
+
112
+ return (
113
+ <Button variant="destructive" onClick={quit}>
114
+ <PowerIcon />
115
+ {t("quit")}
116
+ </Button>
117
+ );
118
+ }
119
+
104
120
  export function SaveLoadMenuButton() {
105
121
  const { t } = useTranslation(["ui"]);
106
122
  const setSettingsOpen = useSetSearchParamState<boolean>("settings");
@@ -20,6 +20,8 @@ import {
20
20
  import { TextDisplaySettings } from "@/lib/stores/text-display-settings-store";
21
21
  import { useQueryClient } from "@tanstack/react-query";
22
22
  import { useSelector } from "@tanstack/react-store";
23
+ import type * as app from "@tauri-apps/api";
24
+ import { getCurrentWindow } from "@tauri-apps/api/window";
23
25
  import {
24
26
  DownloadIcon,
25
27
  FullscreenIcon,
@@ -31,6 +33,12 @@ import {
31
33
  import { useState } from "react";
32
34
  import { useTranslation } from "react-i18next";
33
35
 
36
+ declare global {
37
+ interface Window {
38
+ __TAURI__: typeof app;
39
+ }
40
+ }
41
+
34
42
  export function SystemControls() {
35
43
  return (
36
44
  <div className="flex flex-col gap-4">
@@ -154,7 +162,9 @@ export function FullScreenSettings() {
154
162
  onClick={() => {
155
163
  setLoading(true);
156
164
  let promise: Promise<void>;
157
- if (isFullScreenMode) {
165
+ if (window.__TAURI__) {
166
+ promise = getCurrentWindow().setFullscreen(!isFullScreenMode);
167
+ } else if (isFullScreenMode) {
158
168
  promise = document.exitFullscreen();
159
169
  } else {
160
170
  promise = document.documentElement.requestFullscreen();
@@ -0,0 +1,24 @@
1
+ import { useAlertDialog } from "@/components/providers/alert-dialog-provider";
2
+ import { exit } from "@tauri-apps/plugin-process";
3
+ import { useCallback } from "react";
4
+ import { useTranslation } from "react-i18next";
5
+
6
+ export function useQuit() {
7
+ const { openAlertDialog } = useAlertDialog();
8
+ const { t } = useTranslation(["ui"]);
9
+
10
+ const canQuit = typeof window !== "undefined" && !!window.__TAURI__;
11
+
12
+ const quit = useCallback(() => {
13
+ openAlertDialog({
14
+ head: t("quit"),
15
+ content: t("quit_confirm"),
16
+ onConfirm: async () => {
17
+ await exit();
18
+ return true;
19
+ },
20
+ });
21
+ }, [openAlertDialog, t]);
22
+
23
+ return { quit, canQuit };
24
+ }
@@ -1,10 +1,16 @@
1
1
  import { useQuery } from "@tanstack/react-query";
2
+ import { getCurrentWindow } from "@tauri-apps/api/window";
2
3
 
3
4
  export const IS_FULL_SCREEN_MODE_USE_QUERY_KEY = "is_full_screen_mode_use_query_key";
4
5
 
5
6
  export function useQueryIsFullModeScreen() {
6
7
  return useQuery({
7
8
  queryKey: [IS_FULL_SCREEN_MODE_USE_QUERY_KEY],
8
- queryFn: async () => document.fullscreenElement !== null,
9
+ queryFn: async () => {
10
+ if (window.__TAURI__) {
11
+ return getCurrentWindow().isFullscreen();
12
+ }
13
+ return document.fullscreenElement !== null;
14
+ },
9
15
  });
10
16
  }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Steam utility — thin wrappers around Tauri commands exposed by the
3
+ * `steam` Cargo feature. All functions are safe to call even when:
4
+ * - the app is running outside Tauri (web mode)
5
+ * - Steam is not running
6
+ * - the `steam` feature was not compiled in
7
+ * In all those cases the functions return sensible defaults (null / false / 0)
8
+ * without throwing.
9
+ *
10
+ * Enable Steam in Rust:
11
+ * src-tauri/Cargo.toml → default = ["steam"] (or pass --features steam)
12
+ *
13
+ * Typical usage:
14
+ * import { steam } from "@/lib/steam";
15
+ *
16
+ * const name = await steam.getPlayerName(); // "Alice" | null
17
+ * await steam.unlockAchievement("ACH_COMPLETE_CH1"); // fire & forget
18
+ * await steam.openOverlay("achievements");
19
+ */
20
+
21
+ import { invoke } from "@tauri-apps/api/core";
22
+
23
+ const isTauri = typeof window !== "undefined" && "__TAURI__" in window;
24
+
25
+ /** Dialogs supported by the Steam overlay. */
26
+ export type SteamOverlayDialog =
27
+ | "achievements"
28
+ | "community"
29
+ | "friends"
30
+ | "players"
31
+ | "settings"
32
+ | "officialgamegroup"
33
+ | "stats";
34
+
35
+ async function call<T>(cmd: string, args?: Record<string, unknown>): Promise<T | null> {
36
+ if (!isTauri) return null;
37
+ try {
38
+ return await invoke<T>(cmd, args);
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+
44
+ // ── API ───────────────────────────────────────────────────────────────────────
45
+
46
+ export namespace steam {
47
+ /** `true` when Steam was initialised successfully (Steam client running). */
48
+ export async function isAvailable(): Promise<boolean> {
49
+ return (await call<boolean>("steam_is_available")) ?? false;
50
+ }
51
+
52
+ /** Steam display name of the logged-in user. */
53
+ export async function getPlayerName(): Promise<string | null> {
54
+ return call<string>("steam_get_player_name");
55
+ }
56
+
57
+ /** Numeric App ID of the running application. */
58
+ export async function getAppId(): Promise<number | null> {
59
+ return call<number>("steam_get_app_id");
60
+ }
61
+
62
+ // ── Achievements ──────────────────────────────────────────────────────────
63
+
64
+ /**
65
+ * Unlock an achievement and immediately persist it.
66
+ * `id` must match the API Name in Steamworks Partner.
67
+ */
68
+ export async function unlockAchievement(id: string): Promise<void> {
69
+ await call("steam_unlock_achievement", { achievementId: id });
70
+ }
71
+
72
+ /**
73
+ * Returns `true` if the user has already unlocked the achievement.
74
+ * Reliable only after the first few seconds of launch (stats are fetched
75
+ * automatically at startup).
76
+ */
77
+ export async function isAchievementUnlocked(id: string): Promise<boolean> {
78
+ return (await call<boolean>("steam_is_achievement_unlocked", { achievementId: id })) ?? false;
79
+ }
80
+
81
+ /** Reset an achievement — intended for development / testing only. */
82
+ export async function clearAchievement(id: string): Promise<void> {
83
+ await call("steam_clear_achievement", { achievementId: id });
84
+ }
85
+
86
+ // ── Stats ─────────────────────────────────────────────────────────────────
87
+
88
+ /** Set an integer stat. Remember to call `storeStats()` afterwards. */
89
+ export async function setStatInt(name: string, value: number): Promise<void> {
90
+ await call("steam_set_stat_int", { name, value: Math.trunc(value) });
91
+ }
92
+
93
+ /** Read an integer stat (returns `0` on error). */
94
+ export async function getStatInt(name: string): Promise<number> {
95
+ return (await call<number>("steam_get_stat_int", { name })) ?? 0;
96
+ }
97
+
98
+ /** Set a float stat. Remember to call `storeStats()` afterwards. */
99
+ export async function setStatFloat(name: string, value: number): Promise<void> {
100
+ await call("steam_set_stat_float", { name, value });
101
+ }
102
+
103
+ /** Read a float stat (returns `0` on error). */
104
+ export async function getStatFloat(name: string): Promise<number> {
105
+ return (await call<number>("steam_get_stat_float", { name })) ?? 0;
106
+ }
107
+
108
+ /**
109
+ * Commit pending stat changes to Steam servers.
110
+ * `unlockAchievement` / `clearAchievement` already call this automatically;
111
+ * you only need this when using `setStatInt` / `setStatFloat` directly.
112
+ */
113
+ export async function storeStats(): Promise<void> {
114
+ await call("steam_store_stats");
115
+ }
116
+
117
+ // ── DLC ───────────────────────────────────────────────────────────────────
118
+
119
+ /** `true` if the user owns and has installed the DLC with the given App ID. */
120
+ export async function isDlcInstalled(appId: number): Promise<boolean> {
121
+ return (await call<boolean>("steam_is_dlc_installed", { appId })) ?? false;
122
+ }
123
+
124
+ // ── Overlay ───────────────────────────────────────────────────────────────
125
+
126
+ /**
127
+ * Open the Steam overlay to a specific dialog.
128
+ *
129
+ * Common values: "achievements", "friends", "community", "stats",
130
+ * "settings", "officialgamegroup", "players"
131
+ */
132
+ export async function openOverlay(dialog: SteamOverlayDialog): Promise<void> {
133
+ await call("steam_open_overlay", { dialog });
134
+ }
135
+
136
+ /**
137
+ * Open the Steam store page for this game.
138
+ * Pass a different `appId` to open another game's page.
139
+ */
140
+ export async function openStore(appId?: number): Promise<void> {
141
+ await call("steam_open_store", { appId: appId ?? null });
142
+ }
143
+ }
@@ -0,0 +1,50 @@
1
+ [package]
2
+ name = "my-app-package-name"
3
+ version = "0.1.0"
4
+ description = "my-app-description"
5
+ authors = ["you"]
6
+ edition = "2021"
7
+
8
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9
+
10
+ # ── Steam (optional) ─────────────────────────────────────────────────────────
11
+ # To enable Steam support:
12
+ # 1. Set your App ID in steam_appid.txt (root of the repo, use 480 for testing)
13
+ # 2. Change `default = []` to `default = ["steam"]` below, or pass
14
+ # `--features steam` to cargo / tauri build.
15
+ # 3. On Windows, ship steam_api64.dll next to the executable.
16
+ # 4. On Linux, ship libsteam_api.so next to the executable.
17
+ # 5. On macOS, ship libsteam_api.dylib next to the executable.
18
+ # (The steamworks-sys crate copies the library to the build output
19
+ # automatically; you only need to include it in the Tauri bundle.)
20
+ # ─────────────────────────────────────────────────────────────────────────────
21
+ [features]
22
+ default = []
23
+ steam = ["dep:steamworks"]
24
+
25
+ [lib]
26
+ # The `_lib` suffix may seem redundant but it is necessary
27
+ # to make the lib name unique and wouldn't conflict with the bin name.
28
+ # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
29
+ name = "my_app_lib"
30
+ crate-type = ["staticlib", "cdylib", "rlib"]
31
+
32
+ [build-dependencies]
33
+ tauri-build = { version = "2", features = [] }
34
+
35
+ [dependencies]
36
+ tauri = { version = "2", features = [] }
37
+ tauri-plugin-opener = "2"
38
+ tauri-plugin-process = "2"
39
+ tauri-plugin-window-state = "2"
40
+ serde = { version = "1", features = ["derive"] }
41
+ serde_json = "1"
42
+ steamworks = { version = "0.13", optional = true }
43
+
44
+ [profile.release]
45
+ opt-level = "z" # max runtime performance
46
+ lto = true # link-time optimization — removes dead code across crates
47
+ codegen-units = 1 # slower compile, smaller output
48
+ panic = "abort" # no stack unwinding machinery
49
+ strip = true # strip symbols from the binary
50
+