commit c3e7af7ec098b2a297600e2cd9a467e50beb9c8a Author: Leon Liu Date: Mon Dec 30 17:03:57 2024 +0900 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb18b6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/dist/ +/target/ +/Cargo.lock +node_modules +.vscode diff --git a/.taurignore b/.taurignore new file mode 100644 index 0000000..08c9420 --- /dev/null +++ b/.taurignore @@ -0,0 +1,3 @@ +/src +/public +/Cargo.toml \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..34f83f3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "poe2-loot-filter-tauri-ui" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +leptos = { version = "0.7.1", features = ["csr"] } +wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" +js-sys = "0.3" +serde = { version = "1", features = ["derive"] } +serde-wasm-bindgen = "0.6" +console_error_panic_hook = "0.1.7" +reactive_stores = "0.1.1" +strum = "0.26.3" +strum_macros = "0.26.4" +serde_json = "1.0.133" + +[workspace] +members = ["src-tauri"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..0c73843 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Tauri + Leptos + +This template should help get you started developing with Tauri and Leptos. + +## 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). diff --git a/Trunk.toml b/Trunk.toml new file mode 100644 index 0000000..f476ba0 --- /dev/null +++ b/Trunk.toml @@ -0,0 +1,10 @@ +[build] +target = "./index.html" + +[watch] +ignore = ["./src-tauri"] + +[serve] +port = 1420 +open = false +ws_protocol = "ws" diff --git a/bun.lockb b/bun.lockb new file mode 100644 index 0000000..0925f83 Binary files /dev/null and b/bun.lockb differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..20d0b74 --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + + Tauri + Leptos App + + + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..b203f25 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "poe2-loot-filter-tauri", + "type": "module", + "devDependencies": { + "@types/bun": "latest", + "daisyui": "^4.12.23" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } +} \ No newline at end of file diff --git a/rust-analyzer.toml b/rust-analyzer.toml new file mode 100644 index 0000000..a24cd76 --- /dev/null +++ b/rust-analyzer.toml @@ -0,0 +1,2 @@ +[rustfmt] +overrideCommand = ["leptosfmt", "--stdin", "--rustfmt"] \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..e88003f --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2021" +# (optional) other config... \ No newline at end of file diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore new file mode 100644 index 0000000..d8769d0 --- /dev/null +++ b/src-tauri/.gitignore @@ -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 diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml new file mode 100644 index 0000000..15e6210 --- /dev/null +++ b/src-tauri/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "poe2-loot-filter-tauri" +version = "0.1.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 + +[lib] +# The `_lib` suffix may seem redundant but it is necessary +# to make the lib name unique and wouldn't conflict with the bin name. +# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 +name = "poe2_loot_filter_tauri_lib" +crate-type = ["staticlib", "cdylib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +tauri = { version = "2", features = [] } +tauri-plugin-opener = "2" +serde = { version = "1", features = ["derive"] } +strum_macros = "0.26.4" +strum = "0.26.3" +reqwest = { version = "0.12.9", features = ["blocking"] } +serde_json = "1.0.133" +thiserror = "2.0.8" +directories = "5.0.1" +indoc = "2.0.5" diff --git a/src-tauri/build.rs b/src-tauri/build.rs new file mode 100644 index 0000000..2ba80a8 --- /dev/null +++ b/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json new file mode 100644 index 0000000..2ff144e --- /dev/null +++ b/src-tauri/capabilities/default.json @@ -0,0 +1,10 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "core:default", + "opener:default" + ] +} diff --git a/src-tauri/config.json b/src-tauri/config.json new file mode 100644 index 0000000..2211894 --- /dev/null +++ b/src-tauri/config.json @@ -0,0 +1 @@ +{"armours":[{"kind":"BodyArmours","armour":false,"evasion":false,"energy_shield":false,"armour_evasion":false,"armour_energy_shield":false,"evasion_energy_shield":false},{"kind":"Helmets","armour":false,"evasion":false,"energy_shield":false,"armour_evasion":false,"armour_energy_shield":false,"evasion_energy_shield":false},{"kind":"Boots","armour":false,"evasion":false,"energy_shield":false,"armour_evasion":false,"armour_energy_shield":false,"evasion_energy_shield":false},{"kind":"Gloves","armour":false,"evasion":false,"energy_shield":false,"armour_evasion":false,"armour_energy_shield":false,"evasion_energy_shield":false}],"weapons":[{"kind":"OneHandMaces","show":false},{"kind":"TwoHandMaces","show":false},{"kind":"Crossbows","show":false},{"kind":"Bows","show":false},{"kind":"Quivers","show":false},{"kind":"Sceptres","show":false},{"kind":"Wands","show":false},{"kind":"Staves","show":false},{"kind":"Quarterstaffs","show":false},{"kind":"Shields","show":false},{"kind":"Foci","show":false}],"accessories":[]} \ No newline at end of file diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png new file mode 100644 index 0000000..6be5e50 Binary files /dev/null and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png new file mode 100644 index 0000000..e81bece Binary files /dev/null and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png new file mode 100644 index 0000000..a437dd5 Binary files /dev/null and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 0000000..0ca4f27 Binary files /dev/null and b/src-tauri/icons/Square107x107Logo.png differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png new file mode 100644 index 0000000..b81f820 Binary files /dev/null and b/src-tauri/icons/Square142x142Logo.png differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png new file mode 100644 index 0000000..624c7bf Binary files /dev/null and b/src-tauri/icons/Square150x150Logo.png differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 0000000..c021d2b Binary files /dev/null and b/src-tauri/icons/Square284x284Logo.png differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 0000000..6219700 Binary files /dev/null and b/src-tauri/icons/Square30x30Logo.png differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png new file mode 100644 index 0000000..f9bc048 Binary files /dev/null and b/src-tauri/icons/Square310x310Logo.png differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png new file mode 100644 index 0000000..d5fbfb2 Binary files /dev/null and b/src-tauri/icons/Square44x44Logo.png differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 0000000..63440d7 Binary files /dev/null and b/src-tauri/icons/Square71x71Logo.png differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png new file mode 100644 index 0000000..f3f705a Binary files /dev/null and b/src-tauri/icons/Square89x89Logo.png differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png new file mode 100644 index 0000000..4556388 Binary files /dev/null and b/src-tauri/icons/StoreLogo.png differ diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns new file mode 100644 index 0000000..12a5bce Binary files /dev/null and b/src-tauri/icons/icon.icns differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico new file mode 100644 index 0000000..b3636e4 Binary files /dev/null and b/src-tauri/icons/icon.ico differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png new file mode 100644 index 0000000..e1cd261 Binary files /dev/null and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs new file mode 100644 index 0000000..5ae1329 --- /dev/null +++ b/src-tauri/src/lib.rs @@ -0,0 +1,325 @@ +use std::{ + fs::File, + io::{Read, Write}, + path::PathBuf, + sync::Mutex, +}; + +use directories::{ProjectDirs, UserDirs}; +use indoc::{formatdoc, indoc}; +use serde::{Deserialize, Serialize}; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; +use tauri::{Manager, State}; + +#[derive(Debug, thiserror::Error)] +enum Error { + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + Serde(#[from] serde_json::Error), +} +impl serde::Serialize for Error { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + println!("{}", self.to_string()); + serializer.serialize_str(self.to_string().as_ref()) + } +} + +// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ +#[tauri::command] +fn update(state: State<'_, Mutex>, config: POE2FilterConfig) { + let mut state = state.lock().unwrap(); + write_config(state.config_dir.join(CONFIG_PATH), &config); + let filter = generate_filter(&config); + // write filter + let mut config_file = File::create(state.config_dir.join(ADDON_FILTER_PATH)).unwrap(); + config_file.write_all(filter.as_bytes()).unwrap(); + + // write combined + let combined = state.base_filter.clone() + + indoc! {" + + #------------------------------- + # Addons from Leon's config tool + #------------------------------- + + "} + &filter; + let combined_bytes = combined.as_bytes(); + let mut config_file = File::create(state.config_dir.join(FINAL_FILTER_PATH)).unwrap(); + config_file.write_all(combined_bytes).unwrap(); + let user_dirs = UserDirs::new().unwrap(); + let documents_dir = user_dirs.document_dir().unwrap(); + let poe2_dir = documents_dir.join("My Games").join("Path of Exile 2"); + let mut config_file = File::create(poe2_dir.join(RELEASE_FILTER_PATH)).unwrap(); + config_file.write_all(combined_bytes).unwrap(); + + // update state + state.config = config; +} +#[tauri::command] +fn get_config(state: State<'_, Mutex>) -> POE2FilterConfig { + state.lock().unwrap().config.clone() +} + +fn generate_filter(config: &POE2FilterConfig) -> String { + let mut rules: Vec = vec![]; + let weapons_to_hide = config + .weapons + .iter() + .filter(|filter| !filter.show) + .map(|filter| format!(r#""{}""#, filter.kind.to_string())) + .collect::>() + .join(" "); + let max_level = config.settings.max_level; + rules.push(with_leveling_setting(formatdoc! {" + Hide + Class {weapons_to_hide}"}, max_level)); + + config + .armours + .iter() + .flat_map(|filter| { + let mut armour_rules = Vec::new(); + if filter.armour { + armour_rules.push(indoc! {" + BaseArmour > 0 + BaseEvasion < 1 + BaseEnergyShield < 1"}); + } + if filter.evasion { + armour_rules.push(indoc! {" + BaseArmour < 1 + BaseEvasion > 0 + BaseEnergyShield < 1"}); + } + if filter.energy_shield { + armour_rules.push(indoc! {" + BaseArmour < 1 + BaseEvasion < 1 + BaseEnergyShield > 0"}); + } + if filter.armour_evasion { + armour_rules.push(indoc! {" + BaseArmour > 0 + BaseEvasion > 0 + BaseEnergyShield < 1"}); + } + if filter.armour_energy_shield { + armour_rules.push(indoc! {" + BaseArmour > + BaseEvasion < 1 + BaseEnergyShield > 0"}); + } + if filter.evasion_energy_shield { + armour_rules.push(indoc! {" + BaseArmour < 1 + BaseEvasion > 0 + BaseEnergyShield > 0"}); + } + let kind = filter.kind.to_string(); + armour_rules + .iter() + .map(|rule| { + with_leveling_setting(formatdoc! {" + Show + Class {kind} + {rule}"}, max_level) + }) + .collect::>() + }) + .for_each(|rule| rules.push(rule)); + let all_armours = config + .armours + .iter() + .map(|filter| format!(r#""{}""#, filter.kind.to_string())) + .collect::>() + .join(" "); + rules.push(with_leveling_setting(formatdoc! {" + Hide + Class {all_armours}"}, max_level)); + + (11..max_level) + .map(|i| { + let j = i - 10; + formatdoc! {" + Hide + Rarity <= Magic + AreaLevel >= {i} + DropLevel < {j}"} + }) + .for_each(|rule| rules.push(rule)); + + rules.join("\n\n") +} + +fn with_leveling_setting(str: String, max_level: u32) -> String { + return formatdoc! {" + {str} + Rarity <= Magic + AreaLevel < {max_level} + DropLevel < {max_level}"}; +} + +fn write_config(path: PathBuf, config: &POE2FilterConfig) { + let serialized = serde_json::to_string_pretty(&config).unwrap(); + let mut config_file = File::create(path).unwrap(); + config_file.write_all(serialized.as_bytes()).unwrap(); +} + +struct AppState { + config_dir: PathBuf, + base_filter: String, + config: POE2FilterConfig, +} + +const CONFIG_PATH: &str = "config.json"; +const BASE_FILTER_PATH: &str = "base_filter.filter"; +const ADDON_FILTER_PATH: &str = "addon_filter.filter"; +const FINAL_FILTER_PATH: &str = "final_filter.filter"; +const RELEASE_FILTER_PATH: &str = "Leon.filter"; + +fn init() -> AppState { + let config_dir = ProjectDirs::from("com", "LeonLiu", "POE2 Loot Filter") + .map(|proj_dirs| { + let config_dir = proj_dirs.config_dir().to_path_buf(); + if !config_dir.exists() { + std::fs::create_dir_all(&config_dir).expect("Failed to create config directory"); + } + config_dir + }) + .unwrap(); + let config = File::open(config_dir.join(CONFIG_PATH)) + .map(|mut file| { + let mut contents = String::new(); + file.read_to_string(&mut contents).unwrap(); + let deserialized: POE2FilterConfig = serde_json::from_str(&contents).unwrap(); + deserialized + }) + .unwrap_or_else(|_| { + let config = POE2FilterConfig { + weapons: WeaponKind::iter() + .map(|kind| WeaponFilter { + kind: kind, + show: false, + }) + .collect(), + armours: ArmourKind::iter() + .map(|kind| ArmourFilter { + kind: kind, + armour: false, + evasion: false, + energy_shield: false, + armour_evasion: false, + armour_energy_shield: false, + evasion_energy_shield: false, + }) + .collect(), + accessories: vec![], + settings: FilterSettings { + max_level: 80 + } + }; + write_config(config_dir.join(CONFIG_PATH), &config); + config + }); + // let base_filter = File::open(config_dir.join(BASE_FILTER_PATH)).map(|mut file| { + // let mut contents = String::new(); + // file.read_to_string(&mut contents).unwrap(); + // contents + // }).unwrap_or_else(|_| { + // let res = reqwest::blocking::get("https://raw.githubusercontent.com/NeverSinkDev/NeverSink-PoE2litefilter/refs/heads/main/NeverSinks%20Litefilter.filter").unwrap(); + // let content = res.text().unwrap(); + // let mut base_filter_file = File::create(config_dir.join(BASE_FILTER_PATH)).unwrap(); + // base_filter_file.write_all(content.as_bytes()).unwrap(); + // content + // }); + let res = reqwest::blocking::get("https://raw.githubusercontent.com/NeverSinkDev/NeverSink-PoE2litefilter/refs/heads/main/NeverSinks%20Litefilter.filter").unwrap(); + let base_filter = res.text().unwrap(); + let mut base_filter_file = File::create(config_dir.join(BASE_FILTER_PATH)).unwrap(); + base_filter_file.write_all(base_filter.as_bytes()).unwrap(); + return AppState { + config_dir: config_dir, + base_filter: base_filter, + config: config, + }; +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .setup(|app| { + let state = init(); + app.manage(Mutex::new(state)); + Ok(()) + }) + .plugin(tauri_plugin_opener::init()) + .invoke_handler(tauri::generate_handler![update, get_config]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct POE2FilterConfig { + armours: Vec, + weapons: Vec, + accessories: Vec, + settings: FilterSettings, +} +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +struct FilterSettings { + max_level: u32 +} + +#[derive(Debug, Clone, strum_macros::Display, EnumIter, Serialize, Deserialize)] +#[strum(serialize_all = "title_case")] +enum ArmourKind { + BodyArmours, + Helmets, + Boots, + Gloves, +} + +#[derive(Debug, Clone, strum_macros::Display, EnumIter, Serialize, Deserialize)] +#[strum(serialize_all = "title_case")] +enum WeaponKind { + OneHandMaces, + TwoHandMaces, + Crossbows, + Bows, + Quivers, + Sceptres, + Wands, + Staves, + Quarterstaves, + Shields, + Foci, +} + +#[derive(Debug, Clone, strum_macros::Display, EnumIter, Serialize, Deserialize)] +#[strum(serialize_all = "title_case")] +enum AccessoryKind {} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct ArmourFilter { + kind: ArmourKind, + armour: bool, + evasion: bool, + energy_shield: bool, + armour_evasion: bool, + armour_energy_shield: bool, + evasion_energy_shield: bool, +} +#[derive(Debug, Clone, Serialize, Deserialize)] +struct WeaponFilter { + kind: WeaponKind, + show: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct AccessoryFiler { + kind: AccessoryKind, +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs new file mode 100644 index 0000000..b94baa1 --- /dev/null +++ b/src-tauri/src/main.rs @@ -0,0 +1,6 @@ +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + poe2_loot_filter_tauri_lib::run() +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json new file mode 100644 index 0000000..1f842ae --- /dev/null +++ b/src-tauri/tauri.conf.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "poe2-loot-filter-tauri", + "version": "0.1.0", + "identifier": "com.poe2-loot-filter-tauri.app", + "build": { + "beforeDevCommand": "trunk serve", + "devUrl": "http://localhost:1420", + "beforeBuildCommand": "trunk build", + "frontendDist": "../dist" + }, + "app": { + "withGlobalTauri": true, + "windows": [ + { + "title": "poe2-loot-filter-tauri", + "maximized": true + } + ], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] + } +} diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..c2a8415 --- /dev/null +++ b/src/app.rs @@ -0,0 +1,327 @@ +use std::{fs::File, io::Read, sync::Arc}; + +use leptos::prelude::{Read as Reads, *}; +use reactive_stores::Store; +use serde::{Deserialize, Serialize}; +use serde_wasm_bindgen::from_value; +use strum_macros::EnumIter; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::spawn_local; + +#[derive(Deserialize, Serialize)] +struct Test { + a: Arc, +} + +impl Test { + fn new() -> Self { + let mut buf = String::new(); + let _ = File::open("").unwrap().read_to_string(&mut buf); + serde_json::from_str(&buf).unwrap() + } +} + +#[wasm_bindgen] +extern "C" { + // invoke without arguments + #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"], js_name = invoke)] + async fn invoke_without_args(cmd: &str) -> JsValue; + + // invoke with arguments (default) + #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])] + async fn invoke(cmd: &str, args: JsValue) -> JsValue; + + // They need to have different names! +} +#[derive(Store, Debug, Clone, Serialize, Deserialize)] +struct POE2FilterConfig { + #[store(key: String = |row| row.kind.to_string())] + armours: Vec, + #[store(key: String = |row| row.kind.to_string())] + weapons: Vec, + #[store(key: String = |row| row.kind.to_string())] + accessories: Vec, + settings: FilterSettings, +} + +#[derive(Store, Debug, Clone, Serialize, Deserialize, Default)] +struct FilterSettings { + max_level: u32, +} + +#[derive(Store, Debug, Clone, strum_macros::Display, EnumIter, Serialize, Deserialize)] +#[strum(serialize_all = "title_case")] +enum ArmourKind { + BodyArmours, + Helmets, + Boots, + Gloves, +} + +#[derive(Store, Debug, Clone, strum_macros::Display, EnumIter, Serialize, Deserialize)] +#[strum(serialize_all = "title_case")] +enum WeaponKind { + OneHandMaces, + TwoHandMaces, + Crossbows, + Bows, + Quivers, + Sceptres, + Wands, + Staves, + Quarterstaves, + Shields, + Foci, +} + +#[derive(Store, Debug, Clone, strum_macros::Display, EnumIter, Serialize, Deserialize)] +#[strum(serialize_all = "title_case")] +enum AccessoryKind {} + +#[derive(Store, Debug, Clone, Serialize, Deserialize)] +struct ArmourFilter { + kind: ArmourKind, + armour: bool, + evasion: bool, + energy_shield: bool, + armour_evasion: bool, + armour_energy_shield: bool, + evasion_energy_shield: bool, +} +#[derive(Store, Debug, Clone, Serialize, Deserialize)] +struct WeaponFilter { + kind: WeaponKind, + show: bool, +} + +#[derive(Store, Debug, Clone, Serialize, Deserialize)] +struct AccessoryFiler { + kind: AccessoryKind, +} + +#[derive(Serialize, Deserialize)] +struct UpdateArgs { + config: POE2FilterConfig, +} + +#[component] +fn Main(config: POE2FilterConfig) -> impl IntoView { + let store = Store::new(config); + Effect::new(move |_| { + let config = store.get(); + spawn_local(async move { + let args = serde_wasm_bindgen::to_value(&UpdateArgs { config: config }).unwrap(); + // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ + invoke("update", args).await; + }); + }); + + let max_level = store.settings().max_level(); + view! { +
+
    +
  • "Config folder: %appdata%\\LeonLiu\\POE2 Loot Filter\\config"
  • +
  • + "Changes on the UI will immediately write the new filter file into POE2's config folder. Reload the filter in-game after changes on the UI." +
  • +
  • "The output filter is named " Leon.
  • +
  • + "Based on " + + NeverSink-PoE2litefilter + , will download on every app launch, saved as + " base_filter.filter in the config folder". +
  • +
  • + "From area level 11 to 69, hide normal or magic items of which the drop level is 10 level lower than the area level." +
  • +
  • + "In areas lower than level" + ().unwrap_or(70); + } + /> ",hide normal or magic items, unless turned on in configurations below." +
  • +
+

Weapons

+

+ {format!( + "In areas lower than level {}, only show normal or magic weapons selected.", + max_level.get(), + )} +

+
+ + + {kind.clone()} + + } + } + /> +
+ +

Armours

+

+ {format!( + "In areas lower than level {}, only show normal or magic armours with selected base defence types.", + max_level.get(), + )} +

+
+ {kind.clone()} +
+ + + + + + +
+ } + } + /> +
+
+ } +} + +async fn load_data() -> POE2FilterConfig { + from_value(invoke_without_args("get_config").await).unwrap() +} + +#[component] +pub fn App() -> impl IntoView { + let config = LocalResource::new(move || load_data()); + view! { + +
+ + + + + Loading... +
+ + } + }> + {move || { + config.get().as_deref().map(|config| view! {
}) + }} + + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8387868 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,13 @@ +mod app; + +use app::*; +use leptos::prelude::*; + +fn main() { + console_error_panic_hook::set_once(); + mount_to_body(|| { + view! { + + } + }) +} diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..9f2fae7 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: { + files: ["*.html", "./src/**/*.rs"], + transform: { + rs: (content) => content.replace(/(?:^|\s)class:/g, ' '), + }, + }, + theme: { + extend: {}, + }, + plugins: [require('daisyui')], +} \ No newline at end of file diff --git a/tailwind.css b/tailwind.css new file mode 100644 index 0000000..796882a --- /dev/null +++ b/tailwind.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file