first commit
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/dist/
|
||||||
|
/target/
|
||||||
|
/Cargo.lock
|
||||||
|
.vscode/extensions.json
|
||||||
|
.vscode/settings.json
|
||||||
|
public/tauri.svg
|
||||||
|
public/yew.png
|
||||||
3
.taurignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/src
|
||||||
|
/public
|
||||||
|
/Cargo.toml
|
||||||
19
Cargo.toml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "kaihai-ui"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
[dependencies]
|
||||||
|
yew = { version = "0.21", features = ["csr"] }
|
||||||
|
yew-router = "0.18"
|
||||||
|
wasm-bindgen = "0.2"
|
||||||
|
wasm-bindgen-futures = "0.4"
|
||||||
|
web-sys = "0.3"
|
||||||
|
js-sys = "0.3"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde-wasm-bindgen = "0.6"
|
||||||
|
console_error_panic_hook = "0.1.7"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = ["src-tauri"]
|
||||||
7
README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Tauri + Yew
|
||||||
|
|
||||||
|
This template should help get you started developing with Tauri and Yew.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
[VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
|
||||||
10
Trunk.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[build]
|
||||||
|
target = "./index.html"
|
||||||
|
|
||||||
|
[watch]
|
||||||
|
ignore = ["./src-tauri"]
|
||||||
|
|
||||||
|
[serve]
|
||||||
|
address = "127.0.0.1"
|
||||||
|
port = 1420
|
||||||
|
open = false
|
||||||
11
index.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Tauri + Yew App</title>
|
||||||
|
<link data-trunk rel="css" href="styles.css" />
|
||||||
|
<link data-trunk rel="copy-dir" href="public" />
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
d
|
||||||
|
</html>
|
||||||
7
src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
|
||||||
|
# Generated by Tauri
|
||||||
|
# will have schema files for capabilities auto-completion
|
||||||
|
/gen/schemas
|
||||||
20
src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "kaihai"
|
||||||
|
version = "0.0.0"
|
||||||
|
description = "A Tauri App"
|
||||||
|
authors = ["you"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tauri-build = { version = "1", features = [] }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tauri = { version = "1", features = ["shell-open"] }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||||
|
custom-protocol = ["tauri/custom-protocol"]
|
||||||
3
src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
tauri_build::build()
|
||||||
|
}
|
||||||
BIN
src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 974 B |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 903 B |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src-tauri/icons/icon.icns
Normal file
BIN
src-tauri/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
src-tauri/icons/icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
15
src-tauri/src/main.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||||
|
#[tauri::command]
|
||||||
|
fn greet(name: &str) -> String {
|
||||||
|
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.invoke_handler(tauri::generate_handler![greet])
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");
|
||||||
|
}
|
||||||
44
src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"beforeDevCommand": "trunk serve",
|
||||||
|
"beforeBuildCommand": "trunk build",
|
||||||
|
"devPath": "http://localhost:1420",
|
||||||
|
"distDir": "../dist",
|
||||||
|
"withGlobalTauri": true
|
||||||
|
},
|
||||||
|
"package": {
|
||||||
|
"productName": "kaihai",
|
||||||
|
"version": "0.0.0"
|
||||||
|
},
|
||||||
|
"tauri": {
|
||||||
|
"allowlist": {
|
||||||
|
"all": false,
|
||||||
|
"shell": {
|
||||||
|
"all": false,
|
||||||
|
"open": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"title": "kaihai",
|
||||||
|
"width": 800,
|
||||||
|
"height": 600
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"security": {
|
||||||
|
"csp": null
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"active": true,
|
||||||
|
"targets": "all",
|
||||||
|
"identifier": "com.tauri.dev",
|
||||||
|
"icon": [
|
||||||
|
"icons/32x32.png",
|
||||||
|
"icons/128x128.png",
|
||||||
|
"icons/128x128@2x.png",
|
||||||
|
"icons/icon.icns",
|
||||||
|
"icons/icon.ico"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/app.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
use yew::prelude::*;
|
||||||
|
use yew_router::prelude::*;
|
||||||
|
|
||||||
|
use crate::views::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "tauri"])]
|
||||||
|
async fn invoke(cmd: &str, args: JsValue) -> JsValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Routable, PartialEq)]
|
||||||
|
pub enum Route {
|
||||||
|
#[at("/")]
|
||||||
|
Home,
|
||||||
|
#[at("/extract")]
|
||||||
|
Extract,
|
||||||
|
#[at("/settings")]
|
||||||
|
Settings,
|
||||||
|
#[not_found]
|
||||||
|
#[at("/404")]
|
||||||
|
NotFound,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[function_component(App)]
|
||||||
|
pub fn app() -> Html {
|
||||||
|
html! {
|
||||||
|
<BrowserRouter>
|
||||||
|
<nav::Nav/>
|
||||||
|
<Switch<Route> render={switch} />
|
||||||
|
</BrowserRouter>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn switch(routes: Route) -> Html {
|
||||||
|
match routes {
|
||||||
|
Route::Home => html! { <Home/> },
|
||||||
|
Route::Extract => html! { <Extract/> },
|
||||||
|
Route::Settings => html! { <Settings/> },
|
||||||
|
Route::NotFound => html! { <h1>{"404 Page Not Found"}</h1> },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
38
src/config_settings.rs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
use std::fs;
|
||||||
|
use rocket::config;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, FromForm)]
|
||||||
|
pub struct Config {
|
||||||
|
pub cslol_dir: String,
|
||||||
|
pub wad_dir: String,
|
||||||
|
pub extract_dir: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_config() {
|
||||||
|
if fs::metadata("config.toml").is_err() {
|
||||||
|
let config = Config {
|
||||||
|
cslol_dir: "".to_string(),
|
||||||
|
wad_dir: "C:\\Riot Games\\League of Legends\\Game\\DATA\\FINAL\\Champions".to_string(),
|
||||||
|
extract_dir: "".to_string(),
|
||||||
|
};
|
||||||
|
write_config(&config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_config() -> Config {
|
||||||
|
let config = fs::read_to_string("config.toml")
|
||||||
|
.expect("Failed to read config.toml file");
|
||||||
|
|
||||||
|
toml::from_str(&config)
|
||||||
|
.expect("Failed to parse config.toml file")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_config(config: &Config) {
|
||||||
|
let config_content = toml::to_string(config)
|
||||||
|
.expect("Failed to serialize config");
|
||||||
|
|
||||||
|
fs::write("config.toml", config_content)
|
||||||
|
.expect("Failed to write to config.toml file");
|
||||||
|
}
|
||||||
|
|
||||||
56
src/extractor.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
use std::process::Command;
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::config_settings;
|
||||||
|
|
||||||
|
pub fn extract_wad() {
|
||||||
|
let config = config_settings::load_config();
|
||||||
|
let wad_files: Vec<OsString> = WalkDir::new(config.wad_dir)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|entry| entry.ok())
|
||||||
|
.filter(|entry| {
|
||||||
|
let path = entry.path();
|
||||||
|
let file_name = path.file_name().and_then(|name| name.to_str()).unwrap_or("");
|
||||||
|
let extension = path.extension().and_then(|ext| ext.to_str()).unwrap_or("");
|
||||||
|
extension == "client" &&
|
||||||
|
file_name.ends_with(".wad.client") &&
|
||||||
|
file_name.split('.').count() == 3
|
||||||
|
})
|
||||||
|
.map(|entry| entry.path().to_owned().into_os_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if wad_files.is_empty() {
|
||||||
|
eprintln!("No valid .wad.client files found in the directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_dir = env::current_dir().expect("Failed to get current directory");
|
||||||
|
let extraction_path = current_dir.join("wads");
|
||||||
|
let bat_path = PathBuf::from(config.cslol_dir).join("cslol-tools\\wad-extract.exe");
|
||||||
|
|
||||||
|
if !extraction_path.exists() {
|
||||||
|
fs::create_dir_all(&extraction_path).expect("Failed to create extraction folder");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, wad_file) in wad_files.iter().enumerate() {
|
||||||
|
let status = Command::new(&bat_path)
|
||||||
|
.arg(&wad_file)
|
||||||
|
.arg(&extraction_path)
|
||||||
|
.status()
|
||||||
|
.expect("Failed to execute command");
|
||||||
|
|
||||||
|
if status.success() {
|
||||||
|
println!("Successfully executed wad-extract.bat for {:?}", wad_file);
|
||||||
|
} else {
|
||||||
|
eprintln!("wad-extract.bat returned a non-zero status for {:?}", wad_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= 3 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
mod app;
|
||||||
|
mod views;
|
||||||
|
|
||||||
|
use app::App;
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
yew::Renderer::<App>::new().render();
|
||||||
|
}
|
||||||
18
src/views/extract.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
use yew::prelude::*;
|
||||||
|
|
||||||
|
#[function_component(Extract)]
|
||||||
|
pub fn extract() -> Html {
|
||||||
|
html! {
|
||||||
|
<div class="content">
|
||||||
|
<h2>{"Extract"}</h2>
|
||||||
|
<p>{"Exctract shit"}</p>
|
||||||
|
|
||||||
|
<form action="/extract-wads" method="post">
|
||||||
|
<div class="option">
|
||||||
|
<button type="submit">{"Extract WADs"}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/views/home.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use yew::prelude::*;
|
||||||
|
|
||||||
|
#[function_component(Home)]
|
||||||
|
pub fn home() -> Html {
|
||||||
|
html! {
|
||||||
|
<div class="content">
|
||||||
|
<h2>{"Home Page"}</h2>
|
||||||
|
<p>{"Welcome to the Home page!"}</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/views/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pub mod extract;
|
||||||
|
pub mod home;
|
||||||
|
pub mod nav;
|
||||||
|
pub mod settings;
|
||||||
|
|
||||||
|
pub use extract::*;
|
||||||
|
pub use home::*;
|
||||||
|
pub use settings::*;
|
||||||
14
src/views/nav.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
use yew::prelude::*;
|
||||||
|
use yew_router::prelude::*;
|
||||||
|
use crate::app::Route;
|
||||||
|
|
||||||
|
#[function_component(Nav)]
|
||||||
|
pub fn nav() -> Html {
|
||||||
|
html! {
|
||||||
|
<div class="nav">
|
||||||
|
<Link<Route> to={Route::Home}>{"Home"}</Link<Route>>
|
||||||
|
<Link<Route> to={Route::Extract}>{"Extract"}</Link<Route>>
|
||||||
|
<Link<Route> to={Route::Settings}>{"Settings"}</Link<Route>>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/views/settings.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use yew::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
|
#[function_component(Settings)]
|
||||||
|
pub fn settings() -> Html {
|
||||||
|
html! {
|
||||||
|
<div class="content">
|
||||||
|
<h2>{"Settings"}</h2>
|
||||||
|
<form action="/write-settings" method="post">
|
||||||
|
<div class="option">
|
||||||
|
<label for="cslol_dir">{"Location of CSLoL"}</label>
|
||||||
|
<br/>
|
||||||
|
<input type="text" name="cslol_dir" id="cslol_dir" value="{{ config.cslol_dir }}"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option">
|
||||||
|
<label for="wad_dir">{"Custom location of Champion Wads"}</label>
|
||||||
|
<br/>
|
||||||
|
<input type="text" name="wad_dir" id="wad_dir" value="{{ config.wad_dir }}"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option">
|
||||||
|
<label for="extract_dir">{"Custom location to Extract to"}</label>
|
||||||
|
<br/>
|
||||||
|
<input type="text" name="extract_dir" id="extract_dir" value="{{ config.extract_dir }}"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option">
|
||||||
|
<button type="submit">{"Save Settings"}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
86
styles.css
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
color: white;
|
||||||
|
background-color: #181a1b;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style the side navigation */
|
||||||
|
.nav {
|
||||||
|
height: 100%;
|
||||||
|
width: 200px;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: #111;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Side navigation links */
|
||||||
|
.nav a {
|
||||||
|
color: white;
|
||||||
|
padding: 16px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change color on hover */
|
||||||
|
.nav a:hover {
|
||||||
|
background-color: #363b3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style the content */
|
||||||
|
.content {
|
||||||
|
margin-left: 200px;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
/* Adds space below each option group */
|
||||||
|
padding: 10px 0px;
|
||||||
|
/* Adds padding inside each option group */
|
||||||
|
border-radius: 5px;
|
||||||
|
/* Rounds the corners of the option group */
|
||||||
|
}
|
||||||
|
|
||||||
|
.option label {
|
||||||
|
margin: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option input {
|
||||||
|
outline: none;
|
||||||
|
border: 2px solid #111;
|
||||||
|
background-color: #111;
|
||||||
|
color: white;
|
||||||
|
width: 50%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin: 10px 0px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option input:focus {
|
||||||
|
background-color: #363b3d;
|
||||||
|
border: 2px solid #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option button {
|
||||||
|
background-color: #111;
|
||||||
|
border: 2px solid #111;
|
||||||
|
color: white;
|
||||||
|
padding: 16px 32px;
|
||||||
|
margin: 10px 0px;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.option button:hover {
|
||||||
|
background-color: #363b3d;
|
||||||
|
border: 2px solid #111;
|
||||||
|
}
|
||||||