[feat] better store operation

This commit is contained in:
2025-03-17 11:48:30 +08:00
parent 47dc77732f
commit db3cf9aef2
15 changed files with 169 additions and 127 deletions

View File

@@ -0,0 +1,2 @@
**添加规则文件可帮助模型精准理解你的编码偏好,如框架、代码风格等**
**规则文件只对当前工程生效单文件限制10000字符。如果无需将该文件提交到远程 Git 仓库,请将其添加到 .gitignore**

BIN
bun.lockb

Binary file not shown.

View File

@@ -35,7 +35,7 @@
"@types/throttle-debounce": "^5.0.2",
"framer-motion": "^12.5.0",
"jotai": "^2.12.2",
"next": "15.2.0",
"next": "15.2.2",
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
@@ -65,7 +65,7 @@
"eslint": "9.14.0",
"eslint-config-next": "15.0.3",
"husky": "^9.1.7",
"lint-staged": "^15.4.3",
"lint-staged": "^15.5.0",
"postcss": "^8.5.3",
"postcss-import": "^16.1.0",
"postcss-nesting": "^13.0.1",

View File

@@ -1,18 +1,16 @@
"use client"
import { appStore } from "@/store/app"
import { useSnapshot } from "valtio"
import { useAppStore } from "@/store/app"
export default function Page() {
void appStore.start()
const app = useSnapshot(appStore.state)
const app = useAppStore()
return (
<div className="flex flex-col items-start gap-3 pt-2 pb-1">
<p>{app.version}</p>
<p>{app.hasUpdate ? "有" : "无"}</p>
<p>{app.inited ? "是" : "否"}</p>
<p>{app.notice}</p>
<p>使{app.useMirror ? "是" : "否"}</p>
<p>{app.state.version}</p>
<p>{app.state.hasUpdate ? "有" : "无"}</p>
<p>{app.state.inited ? "是" : "否"}</p>
<p>{app.state.notice}</p>
<p>使{app.state.useMirror ? "是" : "否"}</p>
</div>
)
}

View File

@@ -1,18 +1,16 @@
"use client"
import { currentUser, steamStore } from "@/store/steam"
import { useSnapshot } from "valtio"
import { useSteamStore } from "@/store/steam"
export default function Page() {
void steamStore.start()
const steam = useSnapshot(steamStore.state)
const steam = useSteamStore()
return (
<div className="flex flex-col items-start gap-3 pt-2 pb-1">
<p>Steam路径{steam.dir}</p>
<p>{steam.csDir}</p>
<p>Steam路径有效{steam.isDirValid ? "是" : "否"}</p>
<p>{steam.isCsDirValid ? "是" : "否"}</p>
<p>Steam账号{currentUser().accountName}</p>
<p>Steam路径{steam.state.dir}</p>
<p>{steam.state.csDir}</p>
<p>Steam路径有效{steam.state.isDirValid ? "是" : "否"}</p>
<p>{steam.state.isCsDirValid ? "是" : "否"}</p>
<p>Steam账号{steam.currentUser().accountName}</p>
</div>
)
}

View File

@@ -1,18 +1,16 @@
"use client"
import { currentUser, setCsDir, setDir, steamStore } from "@/store/steam"
import { useSteamStore } from "@/store/steam"
import { useEffect, useState } from "react"
import { useSnapshot } from "valtio"
export default function Page() {
void steamStore.start()
const steam = useSnapshot(steamStore.state)
const [steamDir, setSteamDir] = useState(steam.dir)
const [cs2Dir, setCs2Dir] = useState(steam.csDir)
const steam = useSteamStore()
const [steamDir, setSteamDir] = useState(steam.state.dir)
const [cs2Dir, setCs2Dir] = useState(steam.state.csDir)
useEffect(() => {
setSteamDir(steam.dir)
setCs2Dir(steam.csDir)
}, [steam.dir, steam.csDir])
setSteamDir(steam.state.dir)
setCs2Dir(steam.state.csDir)
}, [steam.state.dir, steam.state.csDir])
return (
<div
@@ -29,7 +27,7 @@ export default function Page() {
value={steamDir}
onChange={(e) => {
setSteamDir(e.target.value)
setDir(e.target.value)
steam.setDir(e.target.value)
}}
/>
<p>CS2所在文件夹</p>
@@ -38,10 +36,10 @@ export default function Page() {
value={cs2Dir}
onChange={(e) => {
setCs2Dir(e.target.value)
setCsDir(e.target.value)
steam.setCsDir(e.target.value)
}}
/>
<p>64SteamID{currentUser().steamID64}</p>
<p>64SteamID{steam.currentUser().steamID64}</p>
</div>
</div>
)

View File

@@ -1,16 +1,13 @@
import { steamStore } from "@/store/steam"
import { toolStore } from "@/store/tool"
import { useSteamStore } from "@/store/steam"
import { useToolStore } from "@/store/tool"
import { TakeOff } from "@icon-park/react"
import { invoke } from "@tauri-apps/api/core"
import { useSnapshot } from "valtio"
import { Card, CardBody, CardHeader, CardIcon } from "../window/Card"
// import { addToast } from "@heroui/react"
const FastLaunch = () => {
void toolStore.start()
void steamStore.start()
const { launchOptions, launchIndex } = useSnapshot(toolStore.state)
const { dir } = useSnapshot(steamStore.state)
const steam = useSteamStore()
const tool = useToolStore()
return (
<Card>
@@ -25,8 +22,8 @@ const FastLaunch = () => {
type="button"
onClick={() =>
invoke("launch_game", {
steamPath: `${dir}/steam.exe`,
launchOption: launchOptions[launchIndex] || "",
steamPath: `${steam.state.dir}/steam.exe`,
launchOption: tool.state.launchOptions[tool.state.launchIndex] || "",
server: "perfectworld",
})
}
@@ -38,8 +35,8 @@ const FastLaunch = () => {
type="button"
onClick={() =>
invoke("launch_game", {
steamPath: `${dir}/steam.exe`,
launchOption: launchOptions[launchIndex] || "",
steamPath: `${steam.state.dir}/steam.exe`,
launchOption: tool.state.launchOptions[tool.state.launchIndex] || "",
server: "worldwide",
})
}

View File

@@ -1,23 +1,16 @@
import {
addLaunchOption,
setLaunchIndex,
setLaunchOption,
toolStore,
} from "@/store/tool"
import { useToolStore } from "@/store/tool"
import { Plus, SettingConfig, Switch } from "@icon-park/react"
import { useEffect, useState } from "react"
import { useSnapshot } from "valtio"
import { Card, CardBody, CardHeader, CardIcon, CardTool } from "../window/Card"
import { ToolButton } from "../window/ToolButton"
const LaunchOption = () => {
void toolStore.start()
const { launchOptions, launchIndex } = useSnapshot(toolStore.state)
const [launchOpt, setLaunchOpt] = useState(launchOptions[launchIndex] || "")
const tool = useToolStore()
const [launchOpt, setLaunchOpt] = useState(tool.state.launchOptions[tool.state.launchIndex] || "")
useEffect(() => {
setLaunchOpt(launchOptions[launchIndex] || "")
}, [launchIndex, launchOptions])
setLaunchOpt(tool.state.launchOptions[tool.state.launchIndex] || "")
}, [tool.state.launchIndex, tool.state.launchOptions])
return (
<Card>
@@ -26,12 +19,12 @@ const LaunchOption = () => {
<SettingConfig />
</CardIcon>
<CardTool>
{launchOptions.map((option, index) => (
<ToolButton key={option} onClick={() => setLaunchIndex(index)}>
{tool.state.launchOptions.map((option, index) => (
<ToolButton key={option} onClick={() => tool.setLaunchIndex(index)}>
{index + 1}
</ToolButton>
))}
<ToolButton onClick={() => addLaunchOption("")}>
<ToolButton onClick={() => tool.addLaunchOption("")}>
<Plus />
</ToolButton>
@@ -46,9 +39,9 @@ const LaunchOption = () => {
placeholder="请输入启动选项"
value={launchOpt}
onChange={(e) => {
if (launchIndex < 0 || launchIndex > 10) return
if (tool.state.launchIndex < 0 || tool.state.launchIndex > 10) return
setLaunchOpt(e.target.value)
setLaunchOption(e.target.value, launchIndex)
tool.setLaunchOption(e.target.value, tool.state.launchIndex)
}}
className="w-full font-mono text-base bg-transparent outline-none resize-none min-h-20"
/>

View File

@@ -6,12 +6,11 @@ import {
CardIcon,
CardTool,
} from "@/components/window/Card"
import { appStore } from "@/store/app"
import { useAppStore } from "@/store/app"
import { createClient } from "@/utils/supabase/client"
import { Skeleton } from "@heroui/react"
import { Refresh, VolumeNotice } from "@icon-park/react"
import useSWR, { useSWRConfig } from "swr"
import { useSnapshot } from "valtio"
import { ToolButton } from "../window/ToolButton"
const Notice = () => {
@@ -38,8 +37,7 @@ const Notice = () => {
}
const NoticeBody = () => {
void appStore.start()
const app = useSnapshot(appStore.state)
const app = useAppStore()
const noticeFetcher = async () => {
const supabase = createClient()
@@ -68,7 +66,7 @@ const NoticeBody = () => {
return (
<>
{notice?.content ||
app.notice ||
app.state.notice ||
"不会真的有人要更新CSGO工具箱吧不会吧不会吧 xswl"}
</>
)

View File

@@ -1,27 +1,26 @@
import { Button, Spinner } from "@heroui/react"
import { useRouter } from "next/navigation"
import { useEffect, useState } from "react"
import { useSnapshot } from "valtio"
import { setCsDir, setDir, steamStore } from "@/store/steam"
import { useSteamStore } from "@/store/steam"
import { open } from "@tauri-apps/plugin-dialog"
export function Prepare() {
const steam = useSteamStore()
const router = useRouter()
const steam = useSnapshot(steamStore.state)
const [loading, setLoading] = useState(true)
const [steamDir, setSteamDir] = useState(steam.dir)
const [cs2Dir, setCs2Dir] = useState(steam.csDir)
const [steamDir, setSteamDir] = useState(steam.state.dir)
const [cs2Dir, setCs2Dir] = useState(steam.state.csDir)
useEffect(() => {
const checkPaths = () => {
if (steam.dir && steam.csDir) {
router.push("/home")
} else {
setLoading(false)
if (steam.state.dir && steam.state.csDir) {
// router.push("/home")
}
setLoading(false)
}
checkPaths()
}, [steam.dir, steam.csDir, router])
}, [steam.state.dir, steam.state.csDir, router])
const handleSelectSteamDir = async () => {
const selected = await open({
@@ -31,7 +30,7 @@ export function Prepare() {
if (selected) {
const dir = selected.replace(/\\[^\\]+$/, "")
setSteamDir(dir)
setDir(dir)
steam.setDir(dir)
}
}
@@ -42,14 +41,14 @@ export function Prepare() {
})
if (selected) {
setCs2Dir(selected)
setCsDir(selected)
steam.setCsDir(selected)
}
}
if (loading) {
return (
<div className="flex flex-col items-center justify-center w-full h-screen gap-6">
<Spinner size="lg" />
<div className="flex flex-col items-center justify-center gap-6">
<Spinner size="lg" variant="simple" />
<p>...</p>
</div>
)
@@ -64,7 +63,9 @@ export function Prepare() {
<input
className="flex-grow px-2 py-1 mb-2 rounded-lg"
value={steamDir}
onChange={(e) => setSteamDir(e.target.value)}
onChange={(e) => {
setSteamDir(e.target.value), steam.setDir(e.target.value)
}}
/>
<Button onPress={handleSelectSteamDir} variant="solid" color="primary" size="sm">
@@ -75,21 +76,34 @@ export function Prepare() {
<input
className="flex-grow px-2 py-1 mb-2 rounded-lg"
value={cs2Dir}
onChange={(e) => setCs2Dir(e.target.value)}
onChange={(e) => {
setCs2Dir(e.target.value), steam.setCsDir(e.target.value)
}}
/>
<Button onPress={handleSelectCs2Dir} variant="solid" color="primary" size="sm">
</Button>
</div>
<Button
onPress={() => router.push("/home")}
variant="solid"
color="primary"
size="sm"
isDisabled={!steamDir || !cs2Dir}
>
</Button>
<section className="flex justify-center w-full gap-3 mt-6">
<Button
onPress={() => alert("获取")}
variant="ghost"
color="default"
size="sm"
>
</Button>
<Button
onPress={() => router.push("/home")}
variant="solid"
color="primary"
size="sm"
isDisabled={!steamDir || !cs2Dir}
>
</Button>
</section>
</div>
)
}

View File

@@ -1,7 +1,7 @@
"use client"
import { setTheme as setTauriTheme } from "@/hooks/tauri/theme"
import { resetAppStore } from "@/store/app"
import { resetToolStore } from "@/store/tool"
import { useAppStore } from "@/store/app"
import { useToolStore } from "@/store/tool"
import { addToast } from "@heroui/react"
import { Close, Minus, Moon, Refresh, RocketOne, Square, SunOne } from "@icon-park/react"
import { type Theme, getCurrentWindow } from "@tauri-apps/api/window"
@@ -11,6 +11,8 @@ import { usePathname, useRouter } from "next/navigation"
import { saveAllNow } from "tauri-plugin-valtio"
const Nav = () => {
const app = useAppStore()
const tool = useToolStore()
const { theme, setTheme } = useTheme()
const setAppTheme = async (theme: Theme) => {
setTheme(theme)
@@ -46,8 +48,8 @@ const Nav = () => {
type="button"
className="px-2 py-0 transition duration-150 rounded hover:bg-zinc-200/80 dark:hover:bg-zinc-100/10 active:scale-95"
onClick={() => {
resetAppStore()
resetToolStore()
app.resetAppStore()
tool.resetToolStore()
addToast({
title: "重置成功",
color: "success",

View File

@@ -12,8 +12,7 @@ import { usePathname, useRouter } from "next/navigation"
import type { ReactNode } from "react"
// import { platform } from "@tauri-apps/plugin-os"
import { appStore, setVersion } from "@/store/app"
import { useSnapshot } from "valtio"
import { useAppStore } from "@/store/app"
interface SideButtonProps {
route: string
@@ -71,8 +70,7 @@ const Avatar = () => {
}
const SideBar = () => {
void appStore.start()
const { version } = useSnapshot(appStore.state)
const app = useAppStore()
return (
<div
@@ -119,9 +117,9 @@ const SideBar = () => {
variant="light"
size="sm"
className="mt-0.5 text-zinc-600"
onPress={() => setVersion("x.y.z")}
onPress={() => app.setVersion("x.y.z")}
>
{version}
{app.state.version}
</Button>
</div>
</div>

View File

@@ -1,13 +1,7 @@
import { store } from "tauri-plugin-valtio"
import { useSnapshot } from "valtio"
import { DEFAULT_STORE_CONFIG } from "."
// Usage:
// import {appStore} from "@/store/app"
// import { useSnapshot } from "valtio"
// const app = useSnapshot(appStore.state)
// { app.version }
// () => appStore.setVersion("0.0.1")
const defaultValue = {
version: "0.0.1",
hasUpdate: false,
@@ -18,26 +12,41 @@ const defaultValue = {
export const appStore = store("app", { ...defaultValue }, DEFAULT_STORE_CONFIG)
export const setVersion = (version: string) => {
export const useAppStore = () => {
void appStore.start
const state = useSnapshot(appStore.state)
return {
state,
setVersion,
setHasUpdate,
setInited,
setNotice,
setUseMirror,
resetAppStore,
}
}
const setVersion = (version: string) => {
appStore.state.version = version
}
export const setHasUpdate = (hasUpdate: boolean) => {
const setHasUpdate = (hasUpdate: boolean) => {
appStore.state.hasUpdate = hasUpdate
}
export const setInited = (inited: boolean) => {
const setInited = (inited: boolean) => {
appStore.state.inited = inited
}
export const setNotice = (notice: string) => {
const setNotice = (notice: string) => {
appStore.state.notice = notice
}
export const setUseMirror = (useMirror: boolean) => {
const setUseMirror = (useMirror: boolean) => {
appStore.state.useMirror = useMirror
}
export const resetAppStore = () => {
const resetAppStore = () => {
setVersion(defaultValue.version)
setHasUpdate(defaultValue.hasUpdate)
setInited(defaultValue.inited)
setNotice(defaultValue.notice)
setUseMirror(defaultValue.useMirror)
}
}

View File

@@ -1,6 +1,7 @@
import type { SteamUser } from "@/types/steam"
import { store } from "tauri-plugin-valtio"
import { DEFAULT_STORE_CONFIG } from "."
import { useSnapshot } from "valtio"
const defaultValue = {
dir: "C:\\Program Files (x86)\\Steam",
@@ -18,33 +19,50 @@ const defaultValue = {
isDirValid: false,
isCsDirValid: false,
}
export const steamStore = store(
"steam",
{ ...defaultValue },
DEFAULT_STORE_CONFIG,
)
export const setDir = (dir: string) => {
export const useSteamStore = () => {
void steamStore.start
const state = useSnapshot(steamStore.state)
return {
state,
setDir,
setCsDir,
setUsers,
setIsDirValid,
setIsCsDirValid,
currentUser,
resetSteamStore,
}
}
const setDir = (dir: string) => {
steamStore.state.dir = dir
}
export const setCsDir = (dir: string) => {
const setCsDir = (dir: string) => {
steamStore.state.csDir = dir
}
export const setUsers = (users: SteamUser[]) => {
const setUsers = (users: SteamUser[]) => {
steamStore.state.users = users
}
export const setIsDirValid = (valid: boolean) => {
const setIsDirValid = (valid: boolean) => {
steamStore.state.isDirValid = valid
}
export const setIsCsDirValid = (valid: boolean) => {
const setIsCsDirValid = (valid: boolean) => {
steamStore.state.isCsDirValid = valid
}
export const currentUser = () => {
const currentUser = () => {
return steamStore.state.users[0] || defaultValue.users[0]
}
export const resetSteamStore = () => {
const resetSteamStore = () => {
setDir(defaultValue.dir)
setCsDir(defaultValue.csDir)
setUsers(defaultValue.users)

View File

@@ -1,6 +1,8 @@
import { store } from "tauri-plugin-valtio"
import { useSnapshot } from "valtio"
import { DEFAULT_STORE_CONFIG } from "."
const defaultValue = {
launchOptions: [
"-novid -high -freq 144 -fullscreen",
@@ -17,7 +19,22 @@ export const toolStore = store(
DEFAULT_STORE_CONFIG,
)
export const setLaunchOption = (option: string, index: number) => {
export const useToolStore = () => {
void toolStore.start
const state = useSnapshot(toolStore.state)
return {
state,
setLaunchOption,
setLaunchOptions,
setLaunchIndex,
setPowerPlan,
addLaunchOption,
resetToolStore,
}
}
const setLaunchOption = (option: string, index: number) => {
toolStore.state.launchOptions = [
...toolStore.state.launchOptions.slice(0, index),
option,
@@ -25,19 +42,19 @@ export const setLaunchOption = (option: string, index: number) => {
]
}
export const setLaunchOptions = (options: string[]) => {
const setLaunchOptions = (options: string[]) => {
toolStore.state.launchOptions = options
}
export const setLaunchIndex = (index: number) => {
const setLaunchIndex = (index: number) => {
toolStore.state.launchIndex = index
}
export const setPowerPlan = (plan: number) => {
const setPowerPlan = (plan: number) => {
toolStore.state.powerPlan = plan
}
export const addLaunchOption = (option: string) => {
const addLaunchOption = (option: string) => {
// 限制最高10个
if (toolStore.state.launchOptions.length >= 10) {
return
@@ -45,7 +62,7 @@ export const addLaunchOption = (option: string) => {
toolStore.state.launchOptions = [...toolStore.state.launchOptions, option]
}
export const resetToolStore = () => {
const resetToolStore = () => {
setLaunchOptions(defaultValue.launchOptions)
setLaunchIndex(defaultValue.launchIndex)
setPowerPlan(defaultValue.powerPlan)