This commit is contained in:
2025-04-07 16:08:40 +08:00
15 changed files with 190 additions and 30 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -23,44 +23,44 @@
"@reactuses/core": "6.0.1",
"@supabase/ssr": "0.6.1",
"@tauri-apps/api": "2.4.0",
"@tauri-apps/plugin-autostart": "^2.2.0",
"@tauri-apps/plugin-cli": "~2",
"@tauri-apps/plugin-autostart": "^2.3.0",
"@tauri-apps/plugin-cli": "~2.2.0",
"@tauri-apps/plugin-clipboard-manager": "2.2.2",
"@tauri-apps/plugin-deep-link": "~2.2.0",
"@tauri-apps/plugin-dialog": "~2.2.0",
"@tauri-apps/plugin-deep-link": "~2.2.1",
"@tauri-apps/plugin-dialog": "~2.2.1",
"@tauri-apps/plugin-fs": "2.2.0",
"@tauri-apps/plugin-global-shortcut": "2.2.0",
"@tauri-apps/plugin-http": "2.4.2",
"@tauri-apps/plugin-notification": "2.2.2",
"@tauri-apps/plugin-os": "2.2.1",
"@tauri-apps/plugin-process": "2.2.0",
"@tauri-apps/plugin-shell": "2.2.0",
"@tauri-apps/plugin-shell": "~2.2.1",
"@tauri-apps/plugin-store": "^2.2.0",
"@tauri-store/valtio": "2.1.1",
"@types/throttle-debounce": "^5.0.2",
"ahooks": "^3.8.4",
"framer-motion": "^12.5.0",
"next": "15.2.4",
"framer-motion": "^12.6.3",
"next": "15.2.3",
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-markdown": "^10.1.0",
"remark-gfm": "^4.0.1",
"swr": "^2.3.3",
"tauri-plugin-system-info-api": "^2.0.10"
},
"devDependencies": {
"@tauri-apps/cli": "^2.4.0",
"@tauri-apps/cli": "^2.4.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/node": "^22.13.13",
"@types/node": "^22.13.17",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"@typescript-eslint/eslint-plugin": "^8.29.0",
"@typescript-eslint/parser": "^8.29.0",
"autoprefixer": "^10.4.21",
"clsx": "^2.1.1",
"cross-env": "^7.0.3",

View File

@@ -41,7 +41,7 @@ tauri-plugin-fs = "2.2.0"
tauri-plugin-dialog = "2.2.0"
tauri-plugin-os = "2.2.1"
tauri-plugin-clipboard-manager = "2.2.2"
tauri-plugin-shell = "2.2.0"
tauri-plugin-shell = "2"
tauri-plugin-http = "2.4.2"
tauri-plugin-notification = "2.2.2"
tauri-plugin-valtio = "2.1.1"

View File

@@ -28,6 +28,8 @@
"autostart:default",
"autostart:allow-enable",
"autostart:allow-disable",
"cli:default"
"cli:default",
"fs:allow-read-text-file",
"fs:allow-resource-read-recursive"
]
}

View File

@@ -1 +1 @@
{"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["global-shortcut:default","theme:default","store:default","store:allow-set","store:allow-get-store","store:allow-has","store:allow-delete","store:allow-clear","store:allow-values","store:allow-save","store:allow-load","store:allow-reset","store:allow-entries","deep-link:default","deep-link:allow-register","deep-link:allow-get-current","autostart:default","autostart:allow-enable","autostart:allow-disable","cli:default"],"platforms":["macOS","windows","linux"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","fs:allow-read-file","fs:allow-write-file","fs:allow-read-dir","fs:allow-copy-file","fs:allow-mkdir","fs:allow-remove","fs:allow-remove","fs:allow-rename","fs:allow-exists","core:window:allow-create","core:window:allow-center","core:window:allow-request-user-attention","core:window:allow-set-resizable","core:window:allow-set-maximizable","core:window:allow-set-minimizable","core:window:allow-set-closable","core:window:allow-set-title","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-set-always-on-top","core:window:allow-set-content-protected","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-set-max-size","core:window:allow-set-position","core:window:allow-set-fullscreen","core:window:allow-set-focus","core:window:allow-set-icon","core:window:allow-set-skip-taskbar","core:window:allow-set-cursor-grab","core:window:allow-set-cursor-visible","core:window:allow-set-cursor-icon","core:window:allow-set-cursor-position","core:window:allow-set-ignore-cursor-events","core:window:allow-start-dragging","core:webview:allow-print","shell:allow-execute","shell:allow-open","dialog:allow-open","dialog:allow-save","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","http:default","notification:default","global-shortcut:allow-is-registered","global-shortcut:allow-register","global-shortcut:allow-register-all","global-shortcut:allow-unregister","global-shortcut:allow-unregister-all","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","process:allow-restart","process:allow-exit","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","core:app:allow-set-app-theme","process:default","fs:default","dialog:default","os:default","clipboard-manager:default"]},"system-info":{"identifier":"system-info","description":"","local":true,"windows":["*"],"permissions":["system-info:allow-all"]},"valtio":{"identifier":"valtio","description":"","local":true,"windows":["*"],"permissions":["valtio:default","core:event:default"]}}
{"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["global-shortcut:default","theme:default","store:default","store:allow-set","store:allow-get-store","store:allow-has","store:allow-delete","store:allow-clear","store:allow-values","store:allow-save","store:allow-load","store:allow-reset","store:allow-entries","deep-link:default","deep-link:allow-register","deep-link:allow-get-current","autostart:default","autostart:allow-enable","autostart:allow-disable","cli:default","fs:allow-read-text-file","fs:allow-resource-read-recursive"],"platforms":["macOS","windows","linux"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","fs:allow-read-file","fs:allow-write-file","fs:allow-read-dir","fs:allow-copy-file","fs:allow-mkdir","fs:allow-remove","fs:allow-remove","fs:allow-rename","fs:allow-exists","core:window:allow-create","core:window:allow-center","core:window:allow-request-user-attention","core:window:allow-set-resizable","core:window:allow-set-maximizable","core:window:allow-set-minimizable","core:window:allow-set-closable","core:window:allow-set-title","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-set-always-on-top","core:window:allow-set-content-protected","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-set-max-size","core:window:allow-set-position","core:window:allow-set-fullscreen","core:window:allow-set-focus","core:window:allow-set-icon","core:window:allow-set-skip-taskbar","core:window:allow-set-cursor-grab","core:window:allow-set-cursor-visible","core:window:allow-set-cursor-icon","core:window:allow-set-cursor-position","core:window:allow-set-ignore-cursor-events","core:window:allow-start-dragging","core:webview:allow-print","shell:allow-execute","shell:allow-open","dialog:allow-open","dialog:allow-save","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","http:default","notification:default","global-shortcut:allow-is-registered","global-shortcut:allow-register","global-shortcut:allow-register-all","global-shortcut:allow-unregister","global-shortcut:allow-unregister-all","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","process:allow-restart","process:allow-exit","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","core:app:allow-set-app-theme","process:default","fs:default","dialog:default","os:default","clipboard-manager:default"]},"system-info":{"identifier":"system-info","description":"","local":true,"windows":["*"],"permissions":["system-info:allow-all"]},"valtio":{"identifier":"valtio","description":"","local":true,"windows":["*"],"permissions":["valtio:default","core:event:default"]}}

Binary file not shown.

View File

@@ -4,6 +4,12 @@ use crate::vdf::preset;
use crate::vdf::preset::VideoConfig;
use crate::wrap_err;
use anyhow::Result;
use std::fs::File;
use std::fs;
use tauri::path::BaseDirectory;
use tauri::Manager;
// use tauri_plugin_shell::ShellExt;
// pub type Result<T, String = ()> = Result<T, String>;
@@ -16,7 +22,17 @@ pub fn greet(name: &str) -> Result<String, String> {
#[tauri::command]
pub fn launch_game(steam_path: &str, launch_option: &str, server: &str) -> Result<String, String> {
wrap_err!(steam::launch_game(steam_path, launch_option, server));
println!(
"{}: launching game on server: {}, with launch Option {}",
steam_path, server, launch_option
);
// wrap_err!(steam::launch_game(steam_path, launch_option, server));
// 如果有错误,打印出来
if let Err(e) = steam::launch_game(steam_path, launch_option, server) {
println!("Error: {}", e);
return Err(e.to_string());
}
// steam::launch_game(steam_path, launch_option, server);
Ok(format!(
"Launching game on server: {}, with launch Option {}",
@@ -111,3 +127,64 @@ pub fn set_cs2_video_config(
pub fn check_path(path: &str) -> Result<bool, String> {
Ok(std::path::Path::new(&path).exists())
}
///// 录像
#[tauri::command]
pub async fn analyze_replay(app: tauri::AppHandle, path: &str) -> Result<String, String> {
// 检测文件是否存在
if !std::path::Path::new(&path).exists() {
return Err("文件不存在".to_string());
}
// 获取应用配置目录
let config_dir = app
.path()
.resolve("metadata", BaseDirectory::AppConfig)
.expect("无法获取配置目录");
// 确保 metadata 文件夹存在
if !config_dir.exists() {
fs::create_dir_all(&config_dir).expect("无法创建 metadata 文件夹");
}
// 提取文件名部分
let file_name = std::path::Path::new(path)
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("default_filename");
// 拼接输出文件路径
let output_path = config_dir.join(format!("{}.json", file_name));
// 确保输出文件存在,如果不存在则创建空文件
if !output_path.exists() {
File::create(&output_path).expect("无法创建输出文件");
}
// 调用项目绑定cli程序
let cli_path = app
.path()
.resolve("resources/csda", BaseDirectory::Resource)
.expect("analyzer not found");
println!("cli path: {}", cli_path.display());
let output = std::process::Command::new(cli_path)
.arg("-demo-path")
.arg(path)
.arg("-format")
.arg("json")
.arg("-minify")
.arg("-output")
.arg(output_path.to_str().expect("路径转换失败"))
.output()
.expect("Failed to execute command");
// 获取输出
let output_str = String::from_utf8_lossy(&output.stdout);
// 打印输出
println!("{}", output_str);
// 返回结果
Ok(output_str.to_string())
}

View File

@@ -134,6 +134,7 @@ fn main() {
cmds::get_cs2_video_config,
cmds::set_cs2_video_config,
cmds::check_path,
cmds::analyze_replay,
on_button_clicked
])
.run(ctx)

View File

@@ -12,6 +12,9 @@
"copyright": "",
"targets": "all",
"externalBin": [],
"resources": [
"resources/csda.exe"
],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
@@ -32,7 +35,6 @@
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"linux": {
"deb": {
@@ -42,7 +44,7 @@
},
"productName": "CS工具箱",
"mainBinaryName": "cstb",
"version": "0.0.6-beta.1",
"version": "0.0.6-beta.2",
"identifier": "upup.cool",
"plugins": {
"deep-link": {

View File

@@ -1,4 +1,66 @@
"use client"
import { Card, CardBody, CardHeader, CardIcon, CardTool } from "@/components/window/Card"
import { MovieBoard } from "@icon-park/react"
import { ToolButton } from "@/components/window/ToolButton"
import { invoke } from "@tauri-apps/api/core"
import path from "path"
import { useSteamStore } from "@/store/steam"
import { addToast } from "@heroui/react"
// import { Command } from "@tauri-apps/plugin-shell"
export default function Page() {
return <div>Movie</div>
const steam = useSteamStore()
const testDemo = async (demo_name: string) => {
const res = await invoke("analyze_replay", {
path: path.resolve(
steam.cs2BaseDir(),
"game",
"csgo",
"replays",
"test.dem"
),
})
console.log("test.dem", "→", res)
// const demo_path = path.resolve(
// '"',
// steam.cs2BaseDir(),
// "game",
// "csgo",
// "replays",
// demo_name,
// '"'
// )
// const command = Command.sidecar("bin/csda", [
// "-demo-path",
// "D:\\Programs\\Steam\\steamapps\\common\\Counter-Strike Global Offensive\\game\\csgo\\replays",
// "-format",
// "json",
// "-minify",
// ])
// const output = await command.execute()
// console.log("output", output)
addToast({ title: "解析成功" })
}
return (
<section className="flex flex-col gap-4 overflow-hidden">
<Card className="overflow-hidden">
<CardHeader>
<CardIcon>
<MovieBoard />
</CardIcon>
<CardTool>
<ToolButton
onClick={async () => {
await testDemo("test.dem")
}}
>
</ToolButton>
</CardTool>
</CardHeader>
<CardBody className="overflow-y-hidden"></CardBody>
</Card>
</section>
)
}

View File

@@ -10,7 +10,7 @@ export default function PreferenceLayout({
// const pathname = usePathname()
return (
<div className="flex w-full gap-3">
<div className="flex w-full h-full gap-3 overflow-hidden">
{/* <Card className="flex-grow max-w-ful">
<CardHeader>
<CardIcon

View File

@@ -1,7 +1,7 @@
"use client"
import { init } from "@/store"
import { useSteamStore } from "@/store/steam"
import { useToolStore } from "@/store/tool"
import { steamStore, useSteamStore } from "@/store/steam"
import { toolStore, useToolStore } from "@/store/tool"
import { addToast } from "@heroui/react"
import { invoke } from "@tauri-apps/api/core"
import { listen } from "@tauri-apps/api/event"
@@ -20,11 +20,11 @@ export default function RootLayout({ children }: { children: React.ReactNode })
void listen<string>("tray://launch_game", async (event) => {
await invoke("launch_game", {
steamPath: `${steam.state.steamDir}/steam.exe`,
launchOption: tool.state.launchOptions[tool.state.launchIndex].option || "",
steamPath: `${steamStore.state.steamDir}\\steam.exe`,
launchOption: toolStore.state.launchOptions[toolStore.state.launchIndex].option || "",
server: event.payload || "worldwide",
})
addToast({ title: "启动国服成功" })
addToast({ title: `启动${event.payload === "worldwide" ? "国际服" : "国服"}成功` })
})
void listen("tray://kill_steam", async () => {
@@ -38,7 +38,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
})
void listen<number>("tray://set_powerplan", async (event) => {
if (typeof(event.payload) === "number" && event.payload <= 0 && event.payload > 4) return
if (typeof event.payload === "number" && event.payload <= 0 && event.payload > 4) return
await invoke("set_powerplan", { plan: event.payload })
const current = await invoke<number>("get_powerplan")
tool.setPowerPlan(current)

View File

@@ -20,7 +20,7 @@ const SteamUsers = ({ className }: { className?: string }) => {
}
return (
<Card /* className={cn("max-w-96", className)} */>
<Card className="overflow-hidden">
<CardHeader>
<CardIcon>
<User /> Steam用户
@@ -32,8 +32,11 @@ const SteamUsers = ({ className }: { className?: string }) => {
</ToolButton>
</CardTool>
</CardHeader>
<CardBody>
<ul className="flex flex-col gap-3 mt-1" ref={parent}>
<CardBody className="overflow-y-hidden">
<ul
className="flex flex-col h-full gap-3 mt-1 overflow-y-auto rounded-lg hide-scrollbar"
ref={parent}
>
{steam.state.users.map((user, id) => (
<li
key={user.account_name}

View File

@@ -6,6 +6,7 @@ import { addToast, NumberInput, Tab, Tabs, Tooltip } from "@heroui/react"
import { motion } from "framer-motion"
import { useToolStore, VideoSetting as VideoConfig, VideoSettingTemplate } from "@/store/tool"
import { useSteamStore } from "@/store/steam"
import { useDebounce } from "ahooks"
const VideoSetting = () => {
const [hide, setHide] = useState(false)
@@ -253,6 +254,17 @@ const VideoSetting = () => {
void tool.getVideoConfig(steam.state.steamDir, steam.currentUser()?.steam_id32 || 0)
}, [])
const debounceCurrentUserId = useDebounce(steam.currentUser()?.steam_id32, {
wait: 500,
leading: false,
trailing: true,
maxWait: 2500,
})
useEffect(() => {
if (steam.state.steamDirValid && steam.currentUser())
void tool.getVideoConfig(steam.state.steamDir, steam.currentUser()?.steam_id32 || 0)
}, [debounceCurrentUserId])
return (
<Card>
<CardHeader>

View File

@@ -4,6 +4,7 @@ import { DEFAULT_STORE_CONFIG } from "./config"
import { emit } from "@tauri-apps/api/event"
import { invoke } from "@tauri-apps/api/core"
import VideoSetting from "@/components/cstb/VideoSetting"
import { useSteamStore } from "./steam"
interface LaunchOption {
option: string