BREAKING: Migrate to Tauri v2

This commit is contained in:
NotThorny
2025-11-27 19:43:08 -07:00
parent 0ef50b889b
commit c06f243a9b
77 changed files with 5199 additions and 13475 deletions

1
src/assets/react.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -16,6 +16,3 @@ let isDebug = false
}
root.render(<React.StrictMode>{isDebug ? <Debug /> : <App />}</React.StrictMode>)
import reportWebVitals from './utils/reportWebVitals'
isDebug && reportWebVitals(console.log)

View File

@@ -1 +0,0 @@
/// <reference types="react-scripts" />

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -4,7 +4,7 @@ import './App.css'
import DownloadHandler from '../utils/download'
import { getConfigOption } from '../utils/configuration'
import { getTheme, loadTheme } from '../utils/themes'
import { convertFileSrc, invoke } from '@tauri-apps/api/tauri'
import { convertFileSrc, invoke } from '@tauri-apps/api/core'
import { Main } from './Main'
import { Mods } from './Mods'

View File

@@ -3,7 +3,7 @@ import './App.css'
import TopBar from './components/TopBar'
import { invoke } from '@tauri-apps/api/tauri'
import { invoke } from '@tauri-apps/api/core'
import { dataDir } from '@tauri-apps/api/path'
import TextInput from './components/common/TextInput'
@@ -15,7 +15,7 @@ async function setProxyAddress(address: string) {
}
async function startProxy() {
await invoke('connect', { port: 2222, certificatePath: (await dataDir()) + '\\cultivation\\ca' })
await invoke('connect', { port: 2222, certificatePath: (await dataDir()) + '/cultivation/ca' })
await invoke('open_in_browser', { url: 'https://hoyoverse.com' })
}
@@ -24,12 +24,12 @@ async function stopProxy() {
}
async function generateCertificates() {
await invoke('generate_ca_files', { path: (await dataDir()) + '\\cultivation' })
await invoke('generate_ca_files', { path: (await dataDir()) + '/cultivation' })
}
async function generateInfo() {
console.log({
certificatePath: (await dataDir()) + '\\cultivation\\ca',
certificatePath: (await dataDir()) + '/cultivation/ca',
isAdmin: await invoke('is_elevated'),
connectingTo: proxyAddress,
})

View File

@@ -16,11 +16,11 @@ import Notification from './components/common/Notification'
import GamePathNotify from './components/menu/GamePathNotify'
import { getConfig, getConfigOption, setConfigOption } from '../utils/configuration'
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { getVersion } from '@tauri-apps/api/app'
import { listen } from '@tauri-apps/api/event'
import { dataDir } from '@tauri-apps/api/path'
import { appWindow } from '@tauri-apps/api/window'
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
import { unpatchGame } from '../utils/rsa'
import DownloadHandler from '../utils/download'
@@ -28,6 +28,7 @@ import DownloadHandler from '../utils/download'
import cogBtn from '../resources/icons/cog.svg'
import downBtn from '../resources/icons/download.svg'
import wrenchBtn from '../resources/icons/wrench.svg'
const appWindow = getCurrentWebviewWindow()
interface IProps {
downloadHandler: DownloadHandler
@@ -163,7 +164,7 @@ export class Main extends React.Component<IProps, IState> {
if (!cert_generated) {
// Generate the certificate
await invoke('generate_ca_files', {
path: (await dataDir()) + 'cultivation',
path: (await dataDir()) + '/cultivation',
})
await setConfigOption('cert_generated', true)
@@ -224,7 +225,7 @@ export class Main extends React.Component<IProps, IState> {
})
}
async componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>) {
async componentDidUpdate(_prevProps: Readonly<IProps>, prevState: Readonly<IState>) {
const game_path = await getConfigOption('game_install_path')
// Check if game exists at set location

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import React from 'react'
import DownloadHandler from '../utils/download'
import { getModDownload, ModData } from '../utils/gamebanana'

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import React from 'react'
import Discord from '../../resources/icons/discord.svg'

View File

@@ -5,7 +5,7 @@ import TextInput from './common/TextInput'
import HelpButton from './common/HelpButton'
import { getConfig, saveConfig, setConfigOption, setProfileOption } from '../../utils/configuration'
import { translate } from '../../utils/language'
import { invoke } from '@tauri-apps/api/tauri'
import { invoke } from '@tauri-apps/api/core'
import Server from '../../resources/icons/server.svg'
import Plus from '../../resources/icons/plus.svg'
@@ -16,7 +16,7 @@ import { GrasscutterElevation } from './menu/Options'
import { getGameExecutable, getGameVersion, getGrasscutterJar } from '../../utils/game'
import { patchGame, unpatchGame } from '../../utils/rsa'
import { listen } from '@tauri-apps/api/event'
import { confirm } from '@tauri-apps/api/dialog'
import { confirm } from '@tauri-apps/plugin-dialog'
import DownloadHandler from '../../utils/download'
interface IProps {
@@ -141,7 +141,7 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
if (
await confirm(
"Oops! HTTPS is enabled but you're connecting to localhost! \nHTTPS MUST be disabled for localhost. \n\nWould you like to disable HTTPS and continue?",
{ title: 'WARNING!!', type: 'warning' }
{ title: 'WARNING!!', kind: 'warning' }
)
) {
this.toggleHttps()
@@ -252,7 +252,7 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
addr: (this.state.httpsEnabled ? 'https' : 'http') + '://' + this.state.ip + ':' + this.state.port,
})
// Connect to proxy
await invoke('connect', { port: 8365, certificatePath: (await dataDir()) + '\\cultivation\\ca' })
await invoke('connect', { port: 8365, certificatePath: (await dataDir()) + '/cultivation/ca' })
}
// Open server as well if the options are set

View File

@@ -1,14 +1,16 @@
import React from 'react'
import { app, invoke } from '@tauri-apps/api'
import { appWindow } from '@tauri-apps/api/window'
import { app } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
import { getConfig, setConfigOption } from '../../utils/configuration'
import Tr from '../../utils/language'
import { confirm } from '@tauri-apps/api/dialog'
import { confirm } from '@tauri-apps/plugin-dialog'
import './TopBar.css'
import closeIcon from '../../resources/icons/close.svg'
import minIcon from '../../resources/icons/min.svg'
import { unpatchGame } from '../../utils/rsa'
const appWindow = getCurrentWebviewWindow()
interface IProps {
children?: React.ReactNode | React.ReactNode[]
@@ -17,7 +19,7 @@ interface IProps {
interface IState {
version: string
clicks: number
intv: NodeJS.Timeout | null
intv: number
}
export default class TopBar extends React.Component<IProps, IState> {
@@ -27,7 +29,7 @@ export default class TopBar extends React.Component<IProps, IState> {
this.state = {
version: '0.0.0',
clicks: 0,
intv: null,
intv: 0,
}
this.activateClick = this.activateClick.bind(this)

View File

@@ -1,5 +1,5 @@
import React from 'react'
import { open } from '@tauri-apps/api/dialog'
import { open } from '@tauri-apps/plugin-dialog'
import { translate } from '../../../utils/language'
import TextInput from './TextInput'
import File from '../../../resources/icons/folder.svg'

View File

@@ -9,10 +9,10 @@ import { dataDir } from '@tauri-apps/api/path'
import './Downloads.css'
import Divider from './Divider'
import { getConfigOption, setConfigOption } from '../../../utils/configuration'
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'
import HelpButton from '../common/HelpButton'
import { ask } from '@tauri-apps/api/dialog'
import { ask } from '@tauri-apps/plugin-dialog'
const FULL_BUILD_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterCulti.zip' // Change to link that can be updated without modifying here
const FULL_QUEST_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterQuests.zip'
@@ -104,15 +104,15 @@ export default class Downloads extends React.Component<IProps, IState> {
return
}
const path = gc_path.substring(0, gc_path.lastIndexOf('\\'))
const path = gc_path.substring(0, gc_path.lastIndexOf('/'))
if (gc_path) {
const resources_exist: boolean =
((await invoke('dir_exists', {
path: path + '\\resources',
path: path + '/resources',
})) as boolean) &&
(!(await invoke('dir_is_empty', {
path: path + '\\resources',
path: path + '/resources',
})) as boolean)
this.setState({
@@ -129,7 +129,7 @@ export default class Downloads extends React.Component<IProps, IState> {
// Set to default if not set
if (!path || path === '') {
const appdata = await dataDir()
folderPath = appdata + 'cultivation\\grasscutter'
folderPath = appdata + '/cultivation/grasscutter'
// Early return since its formatted properly
return folderPath
@@ -145,15 +145,15 @@ export default class Downloads extends React.Component<IProps, IState> {
}
async getCultivationFolder() {
const folderPath = (await dataDir()) + 'cultivation'
const folderPath = (await dataDir()) + '/cultivation'
return folderPath
}
async downloadGrasscutterFullBuild() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(FULL_BUILD_DOWNLOAD, folder + '\\GrasscutterCulti.zip', async () => {
await unzip(folder + '\\GrasscutterCulti.zip', folder + '\\', true)
this.props.downloadManager.addDownload(FULL_BUILD_DOWNLOAD, folder + '/GrasscutterCulti.zip', async () => {
await unzip(folder + '/GrasscutterCulti.zip', folder + '/', true)
this.toggleButtons()
})
@@ -162,8 +162,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGrasscutterFullQuest() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(FULL_QUEST_DOWNLOAD, folder + '\\GrasscutterQuests.zip', async () => {
await unzip(folder + '\\GrasscutterQuests.zip', folder + '\\', true)
this.props.downloadManager.addDownload(FULL_QUEST_DOWNLOAD, folder + '/GrasscutterQuests.zip', async () => {
await unzip(folder + '/GrasscutterQuests.zip', folder + '/', true)
this.toggleButtons()
})
@@ -172,8 +172,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGrasscutterFull50() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(FULL_50_DOWNLOAD, folder + '\\Grasscutter50.zip', async () => {
await unzip(folder + '\\Grasscutter50.zip', folder + '\\', true)
this.props.downloadManager.addDownload(FULL_50_DOWNLOAD, folder + '/Grasscutter50.zip', async () => {
await unzip(folder + '/Grasscutter50.zip', folder + '/', true)
this.toggleButtons()
})
@@ -182,8 +182,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGrasscutterStableRepo() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(STABLE_REPO_DOWNLOAD, folder + '\\grasscutter_repo.zip', async () => {
await unzip(folder + '\\grasscutter_repo.zip', folder + '\\', true)
this.props.downloadManager.addDownload(STABLE_REPO_DOWNLOAD, folder + '/grasscutter_repo.zip', async () => {
await unzip(folder + '/grasscutter_repo.zip', folder + '/', true)
this.toggleButtons()
})
@@ -192,8 +192,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGrasscutterDevRepo() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(DEV_REPO_DOWNLOAD, folder + '\\grasscutter_repo.zip', async () => {
await unzip(folder + '\\grasscutter_repo.zip', folder + '\\', true)
this.props.downloadManager.addDownload(DEV_REPO_DOWNLOAD, folder + '/grasscutter_repo.zip', async () => {
await unzip(folder + '/grasscutter_repo.zip', folder + '/', true)
this.toggleButtons()
})
@@ -202,8 +202,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGrasscutterUnstable() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(UNSTABLE_DOWNLOAD, folder + '\\grasscutter.zip', async () => {
await unzip(folder + '\\grasscutter.zip', folder + '\\', true)
this.props.downloadManager.addDownload(UNSTABLE_DOWNLOAD, folder + '/grasscutter.zip', async () => {
await unzip(folder + '/grasscutter.zip', folder + '/', true)
this.toggleButtons
})
@@ -212,8 +212,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGrasscutterLatest() {
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(DEV_DOWNLOAD, folder + '\\grasscutter.zip', async () => {
await unzip(folder + '\\grasscutter.zip', folder + '\\', true)
this.props.downloadManager.addDownload(DEV_DOWNLOAD, folder + '/grasscutter.zip', async () => {
await unzip(folder + '/grasscutter.zip', folder + '/', true)
this.toggleButtons()
})
@@ -240,22 +240,22 @@ export default class Downloads extends React.Component<IProps, IState> {
)
const folder = await this.getGrasscutterFolder()
this.props.downloadManager.addDownload(RESOURCES_DOWNLOAD, folder + '\\resources.zip', async () => {
this.props.downloadManager.addDownload(RESOURCES_DOWNLOAD, folder + '/resources.zip', async () => {
// Delete the existing folder if it exists
if (
await invoke('dir_exists', {
path: folder + '\\resources',
path: folder + '/resources',
})
) {
await invoke('dir_delete', {
path: folder + '\\resources',
path: folder + '/resources',
})
}
await unzip(folder + '\\resources.zip', folder + '\\', true)
await unzip(folder + '/resources.zip', folder + '/', true)
// Rename folder to resources
invoke('rename', {
path: folder + '\\Resources',
path: folder + '/Resources',
newName: 'resources',
})
@@ -274,8 +274,8 @@ export default class Downloads extends React.Component<IProps, IState> {
const folder = await this.getCultivationFolder()
this.props.downloadManager.addDownload(MIGOTO_DOWNLOAD, folder + '\\GIMI.zip', async () => {
await unzip(folder + '\\GIMI.zip', folder + '\\', true, true)
this.props.downloadManager.addDownload(MIGOTO_DOWNLOAD, folder + '/GIMI.zip', async () => {
await unzip(folder + '/GIMI.zip', folder + '/', true, true)
this.toggleButtons()
})
@@ -285,8 +285,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadMigotoFallback() {
const folder = await this.getCultivationFolder()
this.props.downloadManager.addDownload(MIGOTO_FALLBACK, folder + '\\GIMI7.zip', async () => {
await unzip(folder + '\\GIMI7.zip', folder + '\\', true, true)
this.props.downloadManager.addDownload(MIGOTO_FALLBACK, folder + '/GIMI7.zip', async () => {
await unzip(folder + '/GIMI7.zip', folder + '/', true, true)
this.toggleButtons()
})

View File

@@ -5,7 +5,7 @@ import Menu from './Menu'
import './ExtrasMenu.css'
import BigButton from '../common/BigButton'
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import Tr from '../../../utils/language'
import { getGameExecutable } from '../../../utils/game'

View File

@@ -45,8 +45,8 @@ export default class Downloads extends React.Component<IProps, IState> {
async downloadGame() {
const folder = this.state.gameDownloadFolder
this.props.downloadManager.addDownload(GAME_DOWNLOAD, folder + '\\game.zip', async () => {
await unzip(folder + '\\game.zip', folder + '\\', true)
this.props.downloadManager.addDownload(GAME_DOWNLOAD, folder + '/game.zip', async () => {
await unzip(folder + '/game.zip', folder + '/', true)
this.setState({
gameDownloading: false,
})

View File

@@ -1,5 +1,5 @@
import React from 'react'
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { dataDir } from '@tauri-apps/api/path'
import DirInput from '../common/DirInput'
import Menu from './Menu'
@@ -23,7 +23,7 @@ import DownloadHandler from '../../../utils/download'
import * as meta from '../../../utils/rsa'
import HelpButton from '../common/HelpButton'
import SmallButton from '../common/SmallButton'
import { ask, confirm } from '@tauri-apps/api/dialog'
import { ask, confirm } from '@tauri-apps/plugin-dialog'
import TextInput from '../common/TextInput'
import { unzip } from '../../../utils/zipUtils'
import { getGameExecutable } from '../../../utils/game'
@@ -392,7 +392,7 @@ export default class Options extends React.Component<IProps, IState> {
if (
!(await ask(
'Set delay for 3dmigoto loader? This is specifically made for GIMI v6 and earlier. Using it on latest GIMI or SRMI will cause issues!!! \n\nWould you like to continue?',
{ title: 'GIMI Delay', type: 'warning' }
{ title: 'GIMI Delay', kind: 'warning' }
))
) {
return
@@ -405,7 +405,7 @@ export default class Options extends React.Component<IProps, IState> {
async installCert() {
await invoke('generate_ca_files', {
path: (await dataDir()) + 'cultivation',
path: (await dataDir()) + '/cultivation',
})
}
@@ -445,7 +445,7 @@ export default class Options extends React.Component<IProps, IState> {
// Set to default if not set
if (!path || path === '') {
const appdata = await dataDir()
folderPath = appdata + 'cultivation\\grasscutter'
folderPath = appdata + '/cultivation/grasscutter'
}
if (path.includes('/')) {
@@ -463,7 +463,7 @@ export default class Options extends React.Component<IProps, IState> {
// Check if resources zip exists
if (
!(await invoke('dir_exists', {
path: folderPath + '\\GC-Resources-4.0.zip',
path: folderPath + '/GC-Resources-4.0.zip',
}))
) {
alert('Resources are already unzipped or do not exist! Ensure your resources zip is named "GC-Resources-4.0.zip"')
@@ -475,10 +475,10 @@ export default class Options extends React.Component<IProps, IState> {
)
// Unzip resources
await unzip(folderPath + '\\GC-Resources-4.0.zip', folderPath + '\\', true)
await unzip(folderPath + '/GC-Resources-4.0.zip', folderPath + '/', true)
// Rename folder to resources
invoke('rename', {
path: folderPath + '\\Resources',
path: folderPath + '/Resources',
newName: 'resources',
})

View File

@@ -7,9 +7,10 @@ import Like from '../../../resources/icons/like.svg'
import Eye from '../../../resources/icons/eye.svg'
import Download from '../../../resources/icons/download.svg'
import Folder from '../../../resources/icons/folder.svg'
import { shell } from '@tauri-apps/api'
import {} from '@tauri-apps/api'
import Checkbox from '../common/Checkbox'
import { disableMod, enableMod, modIsEnabled } from '../../../utils/mods'
import * as shell from '@tauri-apps/plugin-shell'
interface IProps {
mod: ModData | PartialModData

View File

@@ -1,6 +1,6 @@
/* eslint-disable indent */
import { invoke } from '@tauri-apps/api/tauri'
import React from 'react'
import { invoke } from '@tauri-apps/api/core'
import React, { JSX } from 'react'
import Tr from '../../../utils/language'
import { getConfig, getConfigOption } from '../../../utils/configuration'

View File

@@ -1,12 +1,13 @@
import { fs } from '@tauri-apps/api'
import {} from '@tauri-apps/api'
import { dataDir } from '@tauri-apps/api/path'
import * as fs from '@tauri-apps/plugin-fs'
let configFilePath: string
let defaultConfig: Configuration
;(async () => {
defaultConfig = {
toggle_grasscutter: true,
game_install_path: 'C:\\Program Files\\Genshin Impact\\Genshin Impact game\\GenshinImpact.exe',
game_install_path: 'C:/Program Files/Genshin Impact/Genshin Impact game/GenshinImpact.exe',
grasscutter_with_game: false,
grasscutter_path: '',
java_path: '',
@@ -150,7 +151,7 @@ export async function saveProfileConfig(obj: Configuration) {
const local = await dataDir()
const raw = JSON.stringify(obj)
const prevPath = configFilePath
configFilePath = local + 'cultivation/configuration.json'
configFilePath = local + '/cultivation/configuration.json'
await writeConfigFile(raw)
configFilePath = prevPath
@@ -160,34 +161,24 @@ export async function saveNewProfileConfig(obj: Configuration, prof: string) {
obj['profile'] = prof
const local = await dataDir()
const raw = JSON.stringify(obj)
configFilePath = local + 'cultivation/profiles/' + obj['profile'] + '.json'
configFilePath = local + '/cultivation/profiles/' + obj['profile'] + '.json'
const file: fs.FsTextFileOption = {
path: configFilePath,
contents: raw,
}
await fs.writeFile(file)
await fs.writeTextFile(configFilePath, raw)
}
async function readConfigFile() {
const local = await dataDir()
if (!configFilePath) {
configFilePath = local + 'cultivation/configuration.json'
configFilePath = local + '/cultivation/configuration.json'
}
const dataFiles = await fs.readDir(local + 'cultivation')
const dataFiles = await fs.readDir(local + '/cultivation')
// Ensure config exists
if (!dataFiles.find((fileOrDir) => fileOrDir?.name === 'configuration.json')) {
// Create config file
const file: fs.FsTextFileOption = {
path: configFilePath,
contents: JSON.stringify(defaultConfig),
}
await fs.writeFile(file)
await fs.writeTextFile(configFilePath, JSON.stringify(defaultConfig))
}
// Read existing config to get profile name
@@ -201,14 +192,14 @@ async function readConfigFile() {
} else {
pf = 'configuration.json'
}
configFilePath = local + 'cultivation/' + pf
configFilePath = local + '/cultivation/' + pf
// Ensure Cultivation dir exists
const dirs = await fs.readDir(local)
if (!dirs.find((fileOrDir) => fileOrDir?.name === 'cultivation')) {
// Create dir
await fs.createDir(local + 'cultivation').catch((e) => console.log(e))
await fs.mkdir(local + '/cultivation').catch((e) => console.log(e))
}
const innerDirs = await fs.readDir(local + '/cultivation')
@@ -216,7 +207,7 @@ async function readConfigFile() {
// Create grasscutter dir for potential installation
if (!innerDirs.find((fileOrDir) => fileOrDir?.name === 'grasscutter')) {
// Create dir
await fs.createDir(local + 'cultivation/grasscutter').catch((e) => console.log(e))
await fs.mkdir(local + '/cultivation/grasscutter').catch((e) => console.log(e))
}
// Finally, read the file
@@ -225,14 +216,13 @@ async function readConfigFile() {
async function readDefaultConfigFile() {
const local = await dataDir()
configFilePath = local + 'cultivation/configuration.json'
configFilePath = local + '/cultivation/configuration.json'
return await fs.readTextFile(configFilePath)
}
async function writeConfigFile(raw: string) {
// All external config functions call readConfigFile, which ensure files exists
await fs.writeFile({
path: configFilePath,
contents: raw,
})
const encoder = new TextEncoder();
const data = encoder.encode(raw)
await fs.writeFile(configFilePath, data)
}

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api/tauri'
import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'
import { byteToString } from './string'
@@ -57,7 +57,6 @@ export default class DownloadHandler {
// Call onFinish callback
if (this.downloads[index]?.onFinish) {
// @ts-expect-error onFinish is checked for existence before being called
this.downloads[index]?.onFinish()
}
})

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { basename, dirname, join } from '@tauri-apps/api/path'
import { getConfigOption } from './configuration'
@@ -7,12 +7,12 @@ export const getGrasscutterJar = () => getConfigOption('grasscutter_path')
export async function getGameExecutable() {
const exe_path = await getConfigOption('game_install_path')
return await basename(exe_path)
}
}
export async function getGameVersion() {
const execPath = await getConfigOption('game_install_path')
const rootPath = await dirname(execPath)
const baseName = (await basename(execPath, ".exe"))
const baseName = await basename(execPath, '.exe')
const datapath = await join(rootPath, `${baseName}_Data`)
const asbPath = await join(datapath, 'StreamingAssets', 'asb_settings.json')
const hasAsb = await invoke<boolean>('dir_exists', { path: asbPath })

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { getConfigOption } from './configuration'
// Generated with https://transform.tools/json-to-typescript I'm lazy cry about it

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import React from 'react'
import { getConfigOption } from './configuration'

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { getConfigOption } from './configuration'
export async function getModsFolder() {

View File

@@ -1,15 +0,0 @@
import { ReportHandler } from 'web-vitals'
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry)
getFID(onPerfEntry)
getFCP(onPerfEntry)
getLCP(onPerfEntry)
getTTFB(onPerfEntry)
})
}
}
export default reportWebVitals

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
// Patch file from: https://github.com/34736384/RSAPatch/
export async function patchGame(newerGame: boolean, version: string) {

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
export async function toggleEncryption(path: string) {
let serverConf

View File

@@ -1,6 +1,6 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { dataDir } from '@tauri-apps/api/path'
import { convertFileSrc } from '@tauri-apps/api/tauri'
import { convertFileSrc } from '@tauri-apps/api/core'
import { getConfig, setConfigOption } from './configuration'
interface Theme {

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'
interface UnzipPayload {

1
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />