update
@ -13,6 +13,7 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/plugin-fs": "~2",
|
||||
"file-saver": "^2.0.5",
|
||||
"fp-ts": "^2.16.9",
|
||||
"pinia": "^2.3.0",
|
||||
@ -24,6 +25,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tauri-apps/cli": "^2.2.0",
|
||||
"@tsconfig/node22": "^22.0.0",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/node": "^22.10.2",
|
||||
|
||||
4
src-tauri/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
/gen/schemas
|
||||
4834
src-tauri/Cargo.lock
generated
Normal file
26
src-tauri/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.77.2"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.3", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4"
|
||||
tauri = { version = "2.2.0", features = [] }
|
||||
tauri-plugin-log = "2.0.0-rc"
|
||||
tauri-plugin-fs = "2"
|
||||
3
src-tauri/build.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
16
src-tauri/capabilities/default.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "enables the default permissions",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"fs:default",
|
||||
{
|
||||
"identifier": "fs:allow-write-text-file",
|
||||
"allow": [{ "path": "$DOCUMENT/My Games/Path of Exile 2/*" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src-tauri/icons/icon.icns
Normal file
BIN
src-tauri/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
src-tauri/icons/icon.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
17
src-tauri/src/lib.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.setup(|app| {
|
||||
if cfg!(debug_assertions) {
|
||||
app.handle().plugin(
|
||||
tauri_plugin_log::Builder::default()
|
||||
.level(log::LevelFilter::Info)
|
||||
.build(),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
6
src-tauri/src/main.rs
Normal file
@ -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() {
|
||||
app_lib::run();
|
||||
}
|
||||
37
src-tauri/tauri.conf.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "poe2-loot-filter-vue",
|
||||
"version": "0.1.0",
|
||||
"identifier": "com.tauri.dev",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"beforeDevCommand": "bun dev",
|
||||
"beforeBuildCommand": "bun build"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "poe2-loot-filter-vue",
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"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"
|
||||
]
|
||||
}
|
||||
}
|
||||
18
src/App.vue
@ -10,6 +10,7 @@ import { pipe } from 'fp-ts/function'
|
||||
import FileSaver from 'file-saver'
|
||||
import { generateFilterText, type Filter, type FilterConfig, type FilterNode } from './models'
|
||||
import { filterToTreeNode, treeNodeToFilter } from './services/filter'
|
||||
import { exists, BaseDirectory, writeTextFile } from '@tauri-apps/plugin-fs';
|
||||
|
||||
const darkMode = ref(document.documentElement.classList.contains('dark'))
|
||||
|
||||
@ -57,15 +58,23 @@ function exportFilter() {
|
||||
|
||||
function download() {
|
||||
var blob = new Blob([previewText.value], { type: "text/plain;charset=utf-8" });
|
||||
FileSaver.saveAs(blob, "poe2.filter")
|
||||
FileSaver.saveAs(blob, "Clearfell Default.filter")
|
||||
}
|
||||
|
||||
const exportDialogVisible = ref(false);
|
||||
|
||||
function save() {
|
||||
async function save(toastOnComplete?: boolean) {
|
||||
if (nodes.value) {
|
||||
const filters = toRaw(nodes.value).map(treeNodeToFilter)
|
||||
localStorage.setItem("filters", JSON.stringify(filters))
|
||||
|
||||
let text = generateFilterText(filters)
|
||||
await writeTextFile('My Games/Path of Exile 2/Clearfell Default.filter', text, {
|
||||
baseDir: BaseDirectory.Document,
|
||||
});
|
||||
if (toastOnComplete) {
|
||||
toast.add({ severity: 'success', summary: 'Success', detail: 'Content Saved', life: 3000 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +89,11 @@ setInterval(save, 5000)
|
||||
<article class="prose dark:prose-invert p-4">
|
||||
<h1>Path of Exile 2 Loot Filter Config</h1>
|
||||
</article><Button :icon @click="darkMode = !darkMode" severity="secondary" variant="outlined" rounded />
|
||||
<Button icon="pi pi-save" label="Save" severity="secondary" variant="outlined" rounded
|
||||
@click="save(); toast.add({ severity: 'success', summary: 'Success', detail: 'Content Saved', life: 3000 });" />
|
||||
<Button icon="pi pi-save" label="Save" severity="secondary" variant="outlined" rounded @click="save(true)" />
|
||||
<Button icon="pi pi-file-export" label="Export" severity="primary" @click="exportFilter" />
|
||||
<Dialog v-model:visible="exportDialogVisible" modal header="Preview Filter Text">
|
||||
<template #default>
|
||||
<ScrollPanel class="h-[50vh]">
|
||||
<ScrollPanel class="h-[50vh] w-[50vw]">
|
||||
<pre>{{ previewText }}</pre>
|
||||
</ScrollPanel>
|
||||
</template>
|
||||
|
||||
@ -4,6 +4,7 @@ import { computed, ref, watchEffect } from 'vue'
|
||||
import { Button, ColorPicker, ScrollPanel, Tabs, Tab, TabPanels, TabList, TabPanel, ToggleButton, InputText, InputNumber, Select, ToggleSwitch, MultiSelect } from 'primevue'
|
||||
import { useConfirm } from "primevue/useconfirm";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import { CLASSES, COLORS, BASE_TYPES, RARITIES, SHAPES, OPERATORS } from '@/models/settings';
|
||||
|
||||
const confirm = useConfirm();
|
||||
const toast = useToast();
|
||||
@ -36,55 +37,7 @@ const props = defineProps<{
|
||||
node: FilterNode,
|
||||
onDelete: () => void
|
||||
}>()
|
||||
const OPERATORS = ['=', '==', '!=', '<', '<=', '>', '>='];
|
||||
|
||||
const COLORS = [
|
||||
'Red',
|
||||
'Green',
|
||||
'Blue',
|
||||
'Brown',
|
||||
'White',
|
||||
'Yellow',
|
||||
'Cyan',
|
||||
'Grey',
|
||||
'Orange',
|
||||
'Pink',
|
||||
'Purple'
|
||||
];
|
||||
|
||||
const SHAPES = [
|
||||
'Circle',
|
||||
'Diamond',
|
||||
'Hexagon',
|
||||
'Square',
|
||||
'Star',
|
||||
'Triangle',
|
||||
'Cross',
|
||||
'Moon',
|
||||
'Raindrop',
|
||||
'Kite',
|
||||
'Pentagon',
|
||||
'UpsideDownHouse'
|
||||
];
|
||||
|
||||
const RARITIES = ['Normal', 'Magic', 'Rare', 'Unique'];
|
||||
|
||||
const CLASSES = [
|
||||
'Currency', 'Stackable Currency', 'Jewel', 'Abyss Jewel', 'Divination Card',
|
||||
'Gem', 'Flask', 'Map', 'Map Fragment', 'Fishing Rods', 'Amulet', 'Ring',
|
||||
'Claw', 'Dagger', 'Wand', 'One Hand Sword', 'Thrusting One Hand Sword',
|
||||
'One Hand Axe', 'One Hand Mace', 'Sceptre', 'Rune Dagger', 'Bow', 'Staff',
|
||||
'Two Hand Sword', 'Two Hand Axe', 'Two Hand Mace', 'Warstaff', 'Body Armour',
|
||||
'Boots', 'Gloves', 'Helmet', 'Shield', 'Quiver'
|
||||
];
|
||||
|
||||
const BASE_TYPES = [
|
||||
'Exalted Orb', 'Mirror of Kalandra', 'Eternal Orb', 'Divine Orb',
|
||||
'Orb of Annulment', 'Chaos Orb', 'Vaal Orb', 'Regal Orb', 'Orb of Alchemy',
|
||||
'Orb of Fusing', 'Blessed Orb', 'Cartographer\'s Chisel', 'Orb of Scouring',
|
||||
'Jeweller\'s Orb', 'Chromatic Orb', 'Orb of Chance', 'Orb of Alteration',
|
||||
'Orb of Transmutation', 'Scroll of Wisdom', 'Portal Scroll'
|
||||
];
|
||||
|
||||
const filter = computed(() => props.node.data)
|
||||
|
||||
|
||||
88
src/models/settings.ts
Normal file
@ -0,0 +1,88 @@
|
||||
export const OPERATORS = ['=', '==', '!=', '<', '<=', '>', '>=']
|
||||
|
||||
export const COLORS = [
|
||||
'Red',
|
||||
'Green',
|
||||
'Blue',
|
||||
'Brown',
|
||||
'White',
|
||||
'Yellow',
|
||||
'Cyan',
|
||||
'Grey',
|
||||
'Orange',
|
||||
'Pink',
|
||||
'Purple',
|
||||
]
|
||||
|
||||
export const SHAPES = [
|
||||
'Circle',
|
||||
'Diamond',
|
||||
'Hexagon',
|
||||
'Square',
|
||||
'Star',
|
||||
'Triangle',
|
||||
'Cross',
|
||||
'Moon',
|
||||
'Raindrop',
|
||||
'Kite',
|
||||
'Pentagon',
|
||||
'UpsideDownHouse',
|
||||
]
|
||||
|
||||
export const RARITIES = ['Normal', 'Magic', 'Rare', 'Unique']
|
||||
|
||||
export const CLASSES = [
|
||||
'Currency',
|
||||
'Stackable Currency',
|
||||
'Jewel',
|
||||
'Abyss Jewel',
|
||||
'Divination Card',
|
||||
'Gem',
|
||||
'Flask',
|
||||
'Map',
|
||||
'Map Fragment',
|
||||
'Fishing Rods',
|
||||
'Amulet',
|
||||
'Ring',
|
||||
'Claw',
|
||||
'Dagger',
|
||||
'Wand',
|
||||
'One Hand Sword',
|
||||
'One Hand Axe',
|
||||
'One Hand Mace',
|
||||
'Sceptre',
|
||||
'Bow',
|
||||
'Staff',
|
||||
'Two Hand Sword',
|
||||
'Two Hand Axe',
|
||||
'Two Hand Mace',
|
||||
'Body Armour',
|
||||
'Boots',
|
||||
'Gloves',
|
||||
'Helmet',
|
||||
'Shield',
|
||||
'Quiver',
|
||||
]
|
||||
|
||||
export const BASE_TYPES = [
|
||||
'Exalted Orb',
|
||||
'Mirror of Kalandra',
|
||||
'Eternal Orb',
|
||||
'Divine Orb',
|
||||
'Orb of Annulment',
|
||||
'Chaos Orb',
|
||||
'Vaal Orb',
|
||||
'Regal Orb',
|
||||
'Orb of Alchemy',
|
||||
'Orb of Fusing',
|
||||
'Blessed Orb',
|
||||
"Cartographer's Chisel",
|
||||
'Orb of Scouring',
|
||||
"Jeweller's Orb",
|
||||
'Chromatic Orb',
|
||||
'Orb of Chance',
|
||||
'Orb of Alteration',
|
||||
'Orb of Transmutation',
|
||||
'Scroll of Wisdom',
|
||||
'Portal Scroll',
|
||||
]
|
||||
@ -3,16 +3,32 @@ import { fileURLToPath, URL } from 'node:url'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
|
||||
const host = process.env.TAURI_DEV_HOST
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
],
|
||||
// prevent vite from obscuring rust errors
|
||||
clearScreen: false,
|
||||
server: {
|
||||
// Tauri expects a fixed port, fail if that port is not available
|
||||
strictPort: true,
|
||||
// if the host Tauri is expecting is set, use it
|
||||
host: host || false,
|
||||
port: 5173,
|
||||
},
|
||||
// Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`.
|
||||
envPrefix: ['VITE_', 'TAURI_ENV_*'],
|
||||
build: {
|
||||
// Tauri uses Chromium on Windows and WebKit on macOS and Linux
|
||||
target: process.env.TAURI_ENV_PLATFORM == 'windows' ? 'chrome105' : 'safari13',
|
||||
// don't minify for debug builds
|
||||
minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false,
|
||||
// produce sourcemaps for debug builds
|
||||
sourcemap: !!process.env.TAURI_ENV_DEBUG,
|
||||
},
|
||||
plugins: [vue(), vueDevTools()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||