Compare commits

..

1 Commits

Author SHA1 Message Date
kvan7
7000dbc58c style(Update to 2): Update branding
Renamed to Exalted PoE2 Trade
2024-12-10 15:47:06 -06:00
53 changed files with 11225 additions and 14785 deletions

View File

@@ -1,24 +0,0 @@
---
name: Something Broken in PoE2
about: Use this for things that worked in PoE 1 and do not in PoE 2
title: "[PoE2]"
labels: bug
assignees: Kvan7
---
**Describe the problem**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem. This is very helpful for comparing the PoE1 vs 2 problems

View File

@@ -20,8 +20,8 @@ jobs:
working-directory: ./renderer
- run: npm run make-index-files
working-directory: ./renderer
- run: npm run lint
working-directory: ./renderer
# - run: npm run lint
# working-directory: ./renderer
- run: npm run build
working-directory: ./renderer
- uses: actions/upload-artifact@v4
@@ -43,11 +43,11 @@ jobs:
with:
name: renderer-dist
path: ./renderer/dist
- run: npm ci
- run: yarn --frozen-lockfile
working-directory: ./main
- run: npm run build
- run: yarn build
working-directory: ./main
- run: npm run package "--" -p onTagOrDraft
- run: yarn package -p onTagOrDraft
working-directory: ./main
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -11,32 +11,32 @@ Note that these 2 both depend on each other, and one cannot run without the othe
The most up-to-date instructions can always be derived from CI:
[.github/workflows/main.yml](https://github.com/Kvan7/exiled-exchange-2/blob/master/.github/workflows/main.yml)
[.github/workflows/main.yml](https://github.com/Kvan7/exalted-poe2-trade/blob/master/.github/workflows/main.yml)
Here's what that looks like as of 2023-12-03.
```shell
cd renderer
npm install
npm run make-index-files
npm run dev
yarn install
yarn make-index-files
yarn dev
# In a second shell
cd main
npm install
npm run dev
yarn install
yarn dev
```
# How to build
```shell
cd renderer
npm install
npm run make-index-files
npm run build
yarn install
yarn make-index-files
yarn build
cd ../main
npm run build
yarn build
# We want to sign with a distribution certificate to ensure other users can
# install without errors
CSC_NAME="Certificate name in Keychain" yarn package

View File

@@ -1,16 +1,16 @@
# ![Exalted Orb](./renderer/public/images/exa.png) Exiled Exchange 2
# ![Exalted Orb](./renderer/public/icon.png) Exalted PoE2 Trade
## Moving from POE1/Awakened PoE Trade
## Moving from POE1
1. Download latest release from [releases](https://github.com/Kvan7/exiled-exchange-2/releases)
1. Download latest release from [releases](https://github.com/Kvan7/exalted-poe2-trade/releases)
- Currently only Windows is supported
- Only available as pre-release right now
2. Run installer
3. Copy `apt-data` from `%APPDATA%\awakened-poe-trade` to `%APPDATA%\exiled-exchange-2` to copy your previous settings
3. Copy `apt-data` from `%APPDATA%\awakened-poe-trade` to `%APPDATA%\exalted-poe2-trade` to copy your previous settings
- Resulting directory structure should look like this:
- `%APPDATA%\exiled-exchange-2\apt-data\`
- `%APPDATA%\exalted-poe2-trade\apt-data\`
- `config.json`
4. Run Exiled Exchange 2
4. Run Exalted PoE2 Trade
## Tool showcase

View File

@@ -1,9 +1,9 @@
import { defineConfig } from 'vitepress'
const BASE = '/exiled-exchange-2/'
const BASE = '/exalted-poe2-trade/'
export default defineConfig({
title: 'Exiled Exchange 2',
title: 'Exalted PoE2 Trade',
description: 'App for price-checking items in Path of Exile 2',
base: BASE,
mpa: true,
@@ -22,7 +22,7 @@ export default defineConfig({
// logo: 'TODO', https://github.com/vuejs/vitepress/issues/1401
appVersion: '3.25.101',
github: {
releasesUrl: 'https://github.com/Kvan7/exiled-exchange-2/releases'
releasesUrl: 'https://github.com/Kvan7/exalted-poe2-trade/releases'
},
socialLinks: [
{
@@ -33,7 +33,7 @@ export default defineConfig({
{
text: 'GitHub',
color: '#181717',
link: 'https://github.com/Kvan7/exiled-exchange-2'
link: 'https://github.com/Kvan7/exalted-poe2-trade'
}
],
sidebar: [

View File

@@ -12,11 +12,11 @@ You can download Exalted Poe Trade here. Any other mirrors are not known
to the developer, downloading from them may be unsafe.
| Download link | Automatic updates | Startup time |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ------------ |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/exiled-exchange-2-Setup-${theme.appVersion}.exe`">Windows 10+ (installer)</a> | ✔ | Fast |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/exiled-exchange-2-${theme.appVersion}.exe`">Windows 10+ (portable)</a> | ❌ | Slower |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/exiled-exchange-2-${theme.appVersion}.AppImage`">Linux (AppImage)</a> | ✔ | n/a |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/exiled-exchange-2-${theme.appVersion}-universal.dmg`">macOS (dmg)</a> | ❌ | n/a |
| --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ------------ |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Exalted-PoE2-Trade-Setup-${theme.appVersion}.exe`">Windows 10+ (installer)</a> | ✔ | Fast |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Exalted-PoE2-Trade-${theme.appVersion}.exe`">Windows 10+ (portable)</a> | ❌ | Slower |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Exalted-PoE2-Trade-${theme.appVersion}.AppImage`">Linux (AppImage)</a> | ✔ | n/a |
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Exalted-PoE2-Trade-${theme.appVersion}-universal.dmg`">macOS (dmg)</a> | ❌ | n/a |
Latest version is <span class="bg-gray-100 border rounded px-1">{{ theme.appVersion }}</span>
@@ -36,6 +36,6 @@ warnings on Windows and [macOS](https://support.apple.com/en-us/HT202491#openany
No Administrator rights required, but\
⚠ **If you run PoE client as Admin, OS security boundaries take effect.
In order for Exiled Exchange 2 to have access to the PoE window, it must be started with Administrator rights.**
In order for Exalted PoE2 Trade to have access to the PoE window, it must be started with Administrator rights.**
**Not compatible with "GeForce Now" or any other cloud gaming service that do not forward clipboard data.**

View File

@@ -14,7 +14,7 @@ title: Common issues
If Awakened works for you with DirectX11/12 renderer,
then problem is old Vulkan drivers for sure.
4. Delete `%appdata%\exiled-exchange-2`
4. Delete `%appdata%\exalted-poe2-trade`
If needed, backup `apt-data` folder with your configuration inside.
@@ -22,7 +22,7 @@ title: Common issues
Launch them later one at a time to identify **conflict**.
6. Restart Exiled Exchange 2.
6. Restart Exalted PoE2 Trade.
*(don't forget to quit first, otherwise launching second instance will do nothing).*

View File

@@ -5,7 +5,7 @@ title: Quick Start
#### First of all, how does it work? {:style="margin-top: 0;"}
When you press `Ctrl + C` Path of Exile 2 copies the item's text (under cursor, if any) to the clipboard.
All that remains is to parse text in Exiled Exchange 2 and show to you in a fancy way.
All that remains is to parse text in Exalted PoE2 Trade and show to you in a fancy way.
### Usage

View File

@@ -25,7 +25,6 @@
"dist/": true
},
"editor.tabSize": 2,
"editor.insertSpaces": true,
"conventionalCommits.scopes": [
"Update to 2"
]

View File

@@ -1,6 +1,6 @@
publish:
- "github"
productName: "Exiled Exchange 2"
productName: "Exalted PoE2 Trade"
npmRebuild: false
files:
- "package.json"

5656
main/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,18 @@
{
"name": "exiled-exchange-2",
"version": "0.0.10",
"name": "exalted-poe2-trade",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "node build/script.mjs",
"build": "tsc --noEmit && node build/script.mjs --prod",
"package": "electron-builder build",
"lint": "eslint src",
"fix": "eslint src --fix"
"package": "electron-builder build"
},
"author": {
"name": "Garrett Parker"
},
"repository": {
"type": "git",
"url": "https://github.com/Kvan7/exiled-exchange-2.git"
"url": "https://github.com/Kvan7/exalted-poe2-trade.git"
},
"main": "dist/main.js",
"dependencies": {
@@ -27,12 +25,15 @@
"@types/ws": "^8.5.3",
"@wokwi/bmp-ts": "^3.0.0",
"comlink": "^4.3.1",
"electron": "33.2.1",
"electron-builder": "25.1.8",
"electron-updater": "^6.3.0",
"esbuild": "^0.24.0",
"ini": "^5.0.0",
"typescript": "5.6.x",
"electron": "31.3.1",
"electron-builder": "24.13.3",
"electron-updater": "^6.1.0",
"esbuild": "^0.23.0",
"ini": "^4.0.0",
"typescript": "5.5.x",
"ws": "^8.16.0"
},
"engines": {
"node": ">=16"
}
}

View File

@@ -23,7 +23,7 @@ export class AppTray {
}
this.tray = new Tray(trayImage);
this.tray.setToolTip(`Exiled Exchange 2 v${app.getVersion()}`);
this.tray.setToolTip(`Exalted PoE2 Trade v${app.getVersion()}`);
this.rebuildMenu();
server.onEventAnyClient("CLIENT->MAIN::user-action", ({ action }) => {

View File

@@ -12,25 +12,25 @@ const POSSIBLE_PATH =
? [
path.join(
app.getPath("documents"),
"My Games\\Path of Exile 2\\poe2_production_Config.ini"
"My Games\\Path of Exile 2\\production_Config.ini"
),
]
: process.platform === "linux"
? [
path.join(
app.getPath("documents"),
"My Games/Path of Exile 2/poe2_production_Config.ini"
"My Games/Path of Exile 2/production_Config.ini"
),
path.join(
app.getPath("home"),
".local/share/Steam/steamapps/compatdata/238960/pfx/drive_c/users/steamuser/Documents/My Games/Path of Exile 2/poe2_production_Config.ini"
".local/share/Steam/steamapps/compatdata/238960/pfx/drive_c/users/steamuser/Documents/My Games/Path of Exile 2/production_Config.ini"
),
]
: process.platform === "darwin"
? [
path.join(
app.getPath("appData"),
"Path of Exile 2/Preferences/poe2_production_Config.ini"
"Path of Exile 2/Preferences/production_Config.ini"
),
]
: [];

View File

@@ -40,6 +40,7 @@ export class HttpProxy {
})
proxyReq.addListener('response', (proxyRes) => {
const resHeaders = { ...proxyRes.headers }
// `net.request` returns an already decoded body
delete resHeaders['content-encoding']
res.writeHead(proxyRes.statusCode, proxyRes.statusMessage, resHeaders)
;(proxyRes as unknown as NodeJS.ReadableStream).pipe(res)
@@ -48,7 +49,6 @@ export class HttpProxy {
logger.write(`error [cors-proxy] ${err.message} (${host})`)
res.destroy(err)
})
req.pipe(proxyReq as unknown as NodeJS.WritableStream)
})
}

View File

@@ -93,7 +93,7 @@ export async function startServer (
socket.on('close', () => {
const clients = websocketServer.clients
if (clients.size === 1) {
lastActiveClient = clients.values().next().value!
lastActiveClient = clients.values().next().value
evBus.emit('CLIENT->MAIN::used-recently', { isOverlay: true })
}
})

View File

@@ -161,7 +161,7 @@ export class OverlayWindow {
// ----------------------
"Path of Exile 2 is running with administrator rights.\n" +
"\n" +
"You need to restart Exiled Exchange 2 with administrator rights."
"You need to restart Exalted PoE2 Trade with administrator rights."
);
} else {
this.server.sendEventTo("broadcast", {

1956
main/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,11 +5,14 @@ module.exports = {
},
plugins: [
'@typescript-eslint',
'prettier'
// 'only-warn'
],
extends: [
'plugin:vue/base',
'standard-with-typescript',
'plugin:prettier/recommended',
'eslint-plugin-prettier/recommended',
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
@@ -37,6 +40,7 @@ module.exports = {
'func-call-spacing': 'off',
// TODO: refactor IPC and enable
'@typescript-eslint/consistent-type-assertions': 'off',
"indent": ["error", "tab"]
},
overrides: [{
files: ['src/main/**/*'],

7
renderer/.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"singleQuote": true,
"endOfLine": "lf",
"tabWidth": 2,
"useTabs": true,
"trailingComma": "es5"
}

View File

@@ -1,18 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="color-scheme" content="dark">
<link rel="icon" href="/icon.ico">
<title>Exiled Exchange 2</title>
</head>
<body>
<title>Exalted PoE2 Trade</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</body>
</html>

View File

@@ -1,12 +1,12 @@
{
"name": "exiled-exchange-2",
"version": "0.0.0",
"name": "exalted-poe2-trade",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "exiled-exchange-2",
"version": "0.0.0",
"name": "exalted-poe2-trade",
"version": "0.0.1",
"dependencies": {
"@fortawesome/fontawesome-free": "6.x.x",
"@sindresorhus/fnv1a": "^3.0.0",
@@ -33,7 +33,10 @@
"@types/object-hash": "^3.0.0",
"@vitejs/plugin-vue": "^4.0.0",
"autoprefixer": "^10.0.2",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"postcss": "^8.2.14",
"prettier": "3.4.2",
"typescript": "5.6.x",
"vite": "^5.0.0",
"vue-tsc": "^2.0.0"
@@ -502,8 +505,8 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
"integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"eslint-visitor-keys": "^3.4.3"
},
@@ -521,8 +524,8 @@
"version": "4.12.1",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
@@ -531,8 +534,8 @@
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
@@ -555,8 +558,8 @@
"version": "8.57.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
@@ -575,8 +578,8 @@
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
"deprecated": "Use @eslint/config-array instead",
"devOptional": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"@humanwhocodes/object-schema": "^2.0.3",
"debug": "^4.3.1",
@@ -590,8 +593,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
"devOptional": true,
"license": "Apache-2.0",
"optional": true,
"engines": {
"node": ">=12.22"
},
@@ -605,8 +608,8 @@
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"deprecated": "Use @eslint/object-schema instead",
"license": "BSD-3-Clause",
"optional": true
"devOptional": true,
"license": "BSD-3-Clause"
},
"node_modules/@intlify/core-base": {
"version": "10.0.4",
@@ -789,6 +792,19 @@
"node": ">=14"
}
},
"node_modules/@pkgr/core": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
"integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
@@ -1383,8 +1399,8 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"license": "ISC",
"optional": true
"devOptional": true,
"license": "ISC"
},
"node_modules/@vitejs/plugin-vue": {
"version": "4.6.2",
@@ -1739,8 +1755,8 @@
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1752,8 +1768,8 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
@@ -1762,8 +1778,8 @@
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -1855,8 +1871,8 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0",
"optional": true
"devOptional": true,
"license": "Python-2.0"
},
"node_modules/array-buffer-byte-length": {
"version": "1.0.1",
@@ -2071,8 +2087,8 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2157,8 +2173,8 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=6"
}
@@ -2197,8 +2213,8 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -2277,8 +2293,8 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
@@ -2377,8 +2393,8 @@
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"ms": "^2.1.3"
},
@@ -2395,8 +2411,8 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/define-data-property": {
"version": "1.1.4",
@@ -2463,8 +2479,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"devOptional": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"esutils": "^2.0.2"
},
@@ -2712,8 +2728,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=10"
},
@@ -2726,8 +2742,8 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -2778,6 +2794,19 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-config-prettier": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
"dev": true,
"license": "MIT",
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
"peerDependencies": {
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-config-standard": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
@@ -3014,6 +3043,37 @@
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-plugin-prettier": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
"integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==",
"dev": true,
"license": "MIT",
"dependencies": {
"prettier-linter-helpers": "^1.0.0",
"synckit": "^0.9.1"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint-plugin-prettier"
},
"peerDependencies": {
"@types/eslint": ">=8.0.0",
"eslint": ">=8.0.0",
"eslint-config-prettier": "*",
"prettier": ">=3.0.0"
},
"peerDependenciesMeta": {
"@types/eslint": {
"optional": true
},
"eslint-config-prettier": {
"optional": true
}
}
},
"node_modules/eslint-plugin-promise": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz",
@@ -3100,8 +3160,8 @@
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"devOptional": true,
"license": "Apache-2.0",
"optional": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -3113,8 +3173,8 @@
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
"integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
@@ -3130,8 +3190,8 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"engines": {
"node": ">=4.0"
}
@@ -3140,8 +3200,8 @@
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
"integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"dependencies": {
"acorn": "^8.9.0",
"acorn-jsx": "^5.3.2",
@@ -3158,8 +3218,8 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"devOptional": true,
"license": "BSD-3-Clause",
"optional": true,
"dependencies": {
"estraverse": "^5.1.0"
},
@@ -3171,8 +3231,8 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"engines": {
"node": ">=4.0"
}
@@ -3181,8 +3241,8 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -3194,8 +3254,8 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"engines": {
"node": ">=4.0"
}
@@ -3220,8 +3280,8 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3232,6 +3292,13 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-diff": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@@ -3264,15 +3331,15 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
@@ -3296,8 +3363,8 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"flat-cache": "^3.0.4"
},
@@ -3321,8 +3388,8 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
@@ -3338,8 +3405,8 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"flatted": "^3.2.9",
"keyv": "^4.5.3",
@@ -3353,8 +3420,8 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
"integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
"license": "ISC",
"optional": true
"devOptional": true,
"license": "ISC"
},
"node_modules/for-each": {
"version": "0.3.3",
@@ -3400,8 +3467,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC",
"optional": true
"devOptional": true,
"license": "ISC"
},
"node_modules/fsevents": {
"version": "2.3.3",
@@ -3498,8 +3565,8 @@
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"devOptional": true,
"license": "ISC",
"optional": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -3531,8 +3598,8 @@
"version": "13.24.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"type-fest": "^0.20.2"
},
@@ -3547,8 +3614,8 @@
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"devOptional": true,
"license": "(MIT OR CC0-1.0)",
"optional": true,
"engines": {
"node": ">=10"
},
@@ -3611,8 +3678,8 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/has-bigints": {
"version": "1.0.2",
@@ -3628,8 +3695,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=8"
}
@@ -3715,8 +3782,8 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 4"
}
@@ -3725,8 +3792,8 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
@@ -3742,8 +3809,8 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=0.8.19"
}
@@ -3753,8 +3820,8 @@
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"devOptional": true,
"license": "ISC",
"optional": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -3764,8 +3831,8 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC",
"optional": true
"devOptional": true,
"license": "ISC"
},
"node_modules/internal-slot": {
"version": "1.0.7",
@@ -4031,8 +4098,8 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=8"
}
@@ -4215,8 +4282,8 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"argparse": "^2.0.1"
},
@@ -4228,22 +4295,22 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/json5": {
"version": "1.0.2",
@@ -4262,8 +4329,8 @@
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"json-buffer": "3.0.1"
}
@@ -4272,8 +4339,8 @@
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
@@ -4301,8 +4368,8 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"p-locate": "^5.0.0"
},
@@ -4324,8 +4391,8 @@
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "10.4.3",
@@ -4377,8 +4444,8 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"devOptional": true,
"license": "ISC",
"optional": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -4409,8 +4476,8 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/muggle-string": {
"version": "0.4.1",
@@ -4452,8 +4519,8 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/natural-compare-lite": {
"version": "1.4.0",
@@ -4629,8 +4696,8 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"devOptional": true,
"license": "ISC",
"optional": true,
"dependencies": {
"wrappy": "1"
}
@@ -4639,8 +4706,8 @@
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
@@ -4657,8 +4724,8 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"yocto-queue": "^0.1.0"
},
@@ -4673,8 +4740,8 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"p-limit": "^3.0.2"
},
@@ -4695,8 +4762,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"callsites": "^3.0.0"
},
@@ -4715,8 +4782,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=8"
}
@@ -4725,8 +4792,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
@@ -4977,18 +5044,47 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-diff": "^1.1.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=6"
}
@@ -5109,8 +5205,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=4"
}
@@ -5130,8 +5226,8 @@
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"devOptional": true,
"license": "ISC",
"optional": true,
"dependencies": {
"glob": "^7.1.3"
},
@@ -5542,8 +5638,8 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=8"
},
@@ -5621,8 +5717,8 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -5642,6 +5738,30 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/synckit": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@pkgr/core": "^0.1.0",
"tslib": "^2.6.2"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/synckit/node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
"node_modules/tailwindcss": {
"version": "3.4.15",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
@@ -5683,8 +5803,8 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"license": "MIT",
"optional": true
"devOptional": true,
"license": "MIT"
},
"node_modules/thenify": {
"version": "3.3.1",
@@ -5774,8 +5894,8 @@
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"devOptional": true,
"license": "MIT",
"optional": true,
"dependencies": {
"prelude-ls": "^1.2.1"
},
@@ -5945,8 +6065,8 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"devOptional": true,
"license": "BSD-2-Clause",
"optional": true,
"dependencies": {
"punycode": "^2.1.0"
}
@@ -6251,8 +6371,8 @@
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
@@ -6355,8 +6475,8 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC",
"optional": true
"devOptional": true,
"license": "ISC"
},
"node_modules/xml-name-validator": {
"version": "4.0.0",
@@ -6384,8 +6504,8 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"devOptional": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=10"
},

View File

@@ -1,11 +1,10 @@
{
"name": "exiled-exchange-2",
"version": "0.0.0",
"name": "exalted-poe2-trade",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite",
"lint": "eslint --ext .ts,.vue src",
"lint-fix": "eslint --ext .ts,.vue src --fix",
"build": "vue-tsc --noEmit && vite build",
"make-index-files": "node src/assets/make-index-files.mjs"
},
@@ -35,7 +34,10 @@
"@types/object-hash": "^3.0.0",
"@vitejs/plugin-vue": "^4.0.0",
"autoprefixer": "^10.0.2",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"postcss": "^8.2.14",
"prettier": "3.4.2",
"typescript": "5.6.x",
"vite": "^5.0.0",
"vue-tsc": "^2.0.0"

View File

@@ -269,7 +269,7 @@
"stack": "Stack"
},
"settings": {
"title": "Settings - Exiled Exchange 2",
"title": "Settings - Exalted PoE2 Trade",
"language": "Language",
"private_league": "or Private League",
"account_name": "Account name",

View File

@@ -266,7 +266,7 @@
"stack": "스택"
},
"settings": {
"title": "세팅 - Exiled Exchange 2",
"title": "세팅 - Exalted PoE2 Trade",
"language": "언어",
"private_league": "개인리그",
"account_name": "계정명",

View File

@@ -282,7 +282,7 @@
"stack": "Стак"
},
"settings": {
"title": "Настройки - Exiled Exchange 2",
"title": "Настройки - Exalted PoE2 Trade",
"language": "Язык",
"private_league": "или Приватная лига",
"account_name": "Имя учетной записи",

View File

@@ -299,8 +299,8 @@ function parseNamePlate (section: string[]) {
const item: ParserState = {
rarity: undefined,
category: undefined,
name,
baseType,
name: name,
baseType: baseType,
isUnidentified: false,
isCorrupted: false,
newMods: [],

View File

@@ -57,41 +57,41 @@ export const WEAPON_ONE_HANDED_MELEE = new Set([
ItemCategory.Claw,
ItemCategory.Dagger,
ItemCategory.RuneDagger,
ItemCategory.Sceptre
])
ItemCategory.Sceptre,
]);
export const WEAPON_ONE_HANDED = new Set([
ItemCategory.Wand,
...WEAPON_ONE_HANDED_MELEE
])
...WEAPON_ONE_HANDED_MELEE,
]);
export const WEAPONE_TWO_HANDED_MELEE = new Set([
ItemCategory.TwoHandedAxe,
ItemCategory.TwoHandedMace,
ItemCategory.TwoHandedSword,
ItemCategory.Staff,
ItemCategory.Warstaff
])
ItemCategory.Warstaff,
]);
export const WEAPON = new Set([
ItemCategory.FishingRod,
ItemCategory.Bow,
...WEAPON_ONE_HANDED,
...WEAPONE_TWO_HANDED_MELEE
])
...WEAPONE_TWO_HANDED_MELEE,
]);
export const ARMOUR = new Set([
ItemCategory.BodyArmour,
ItemCategory.Boots,
ItemCategory.Gloves,
ItemCategory.Helmet,
ItemCategory.Shield
])
ItemCategory.Shield,
]);
export const ACCESSORY = new Set([
ItemCategory.Amulet,
ItemCategory.Belt,
ItemCategory.Ring,
ItemCategory.Trinket
ItemCategory.Trinket,
// ItemCategory.Quiver
])
]);

View File

@@ -109,7 +109,7 @@ export function translateStatWithRoll (
calc.sources.some(s => s.stat.stat.ref === calc.stat.ref && s.stat.roll!.dp)
: undefined
return { string: translation.string, negate: translation.negate || false, dp }
return { string: translation.string, negate: translation.negate || false, dp: dp }
}
export enum ModifierType {

View File

@@ -1,128 +1,128 @@
import { reactive as deepReactive, shallowRef, toRaw } from 'vue'
import isDeepEqual from 'fast-deep-equal'
import { Host } from '@/web/background/IPC'
import { HostConfig, ShortcutAction } from '@ipc/types'
import type * as widget from './overlay/widgets'
import type { StashSearchWidget } from './stash-search/widget'
import type { ItemCheckWidget } from './item-check/widget'
import type { ItemSearchWidget } from './item-search/widget'
import { reactive as deepReactive, shallowRef, toRaw } from 'vue';
import isDeepEqual from 'fast-deep-equal';
import { Host } from '@/web/background/IPC';
import { HostConfig, ShortcutAction } from '@ipc/types';
import type * as widget from './overlay/widgets';
import type { StashSearchWidget } from './stash-search/widget';
import type { ItemCheckWidget } from './item-check/widget';
import type { ItemSearchWidget } from './item-search/widget';
const _config = shallowRef<Config | null>(null)
let _lastSavedConfig: Config | null = null
const _config = shallowRef<Config | null>(null);
let _lastSavedConfig: Config | null = null;
export function AppConfig (): Config
export function AppConfig<T extends widget.Widget> (type: string): T | undefined
export function AppConfig (type?: string) {
export function AppConfig(): Config;
export function AppConfig<T extends widget.Widget>(type: string): T | undefined;
export function AppConfig(type?: string) {
if (!type) {
return _config.value!
return _config.value!;
} else {
return _config.value!.widgets.find((w) => w.wmType === type)
return _config.value!.widgets.find((w) => w.wmType === type);
}
}
export function updateConfig (updates: Config) {
_config.value = deepReactive(JSON.parse(JSON.stringify(updates)))
document.documentElement.style.fontSize = `${_config.value!.fontSize}px`
export function updateConfig(updates: Config) {
_config.value = deepReactive(JSON.parse(JSON.stringify(updates)));
document.documentElement.style.fontSize = `${_config.value!.fontSize}px`;
}
export function saveConfig (opts?: { isTemporary: boolean }) {
const rawConfig = toRaw(_config.value!)
export function saveConfig(opts?: { isTemporary: boolean }) {
const rawConfig = toRaw(_config.value!);
if (
rawConfig.widgets.some(
(w) => w.wmZorder === 'exclusive' && w.wmWants === 'show'
)
) {
return
return;
}
if (!isDeepEqual(rawConfig, _lastSavedConfig)) {
_lastSavedConfig = JSON.parse(JSON.stringify(rawConfig))
_lastSavedConfig = JSON.parse(JSON.stringify(rawConfig));
Host.sendEvent({
name: 'CLIENT->MAIN::save-config',
payload: {
contents: JSON.stringify(AppConfig()),
isTemporary: opts?.isTemporary ?? false
}
})
isTemporary: opts?.isTemporary ?? false,
},
});
}
}
export function pushHostConfig () {
export function pushHostConfig() {
Host.sendEvent({
name: 'CLIENT->MAIN::update-host-config',
payload: getConfigForHost()
})
payload: getConfigForHost(),
});
}
export async function initConfig () {
export async function initConfig() {
Host.onEvent('MAIN->CLIENT::config-changed', (e) => {
_lastSavedConfig = JSON.parse(e.contents) // should be a deep copy
updateConfig(JSON.parse(e.contents))
})
_lastSavedConfig = JSON.parse(e.contents); // should be a deep copy
updateConfig(JSON.parse(e.contents));
});
const contents = await Host.getConfig()
const contents = await Host.getConfig();
if (!contents) {
updateConfig(defaultConfig())
return
updateConfig(defaultConfig());
return;
}
let config: Config
let config: Config;
try {
config = JSON.parse(contents)
config = JSON.parse(contents);
} catch {
updateConfig(defaultConfig())
saveConfig({ isTemporary: true })
return
updateConfig(defaultConfig());
saveConfig({ isTemporary: true });
return;
// TODO
// dialog.showErrorBox(
// 'Exiled Exchange 2 - Incompatible configuration',
// 'Exalted PoE2 Trade - Incompatible configuration',
// // ----------------------
// 'You are trying to use an older version of Exiled Exchange 2 with a newer incompatible configuration file.\n' +
// 'You are trying to use an older version of Exalted PoE2 Trade with a newer incompatible configuration file.\n' +
// 'You need to install the latest version to continue using it.'
// )
}
updateConfig(upgradeConfig(config))
updateConfig(upgradeConfig(config));
}
export function poeWebApi () {
const { language, realm } = AppConfig()
export function poeWebApi() {
const { language, realm } = AppConfig();
switch (language) {
case 'en':
return 'www.pathofexile.com'
return 'www.pathofexile.com';
case 'ru':
return 'ru.pathofexile.com'
return 'ru.pathofexile.com';
case 'cmn-Hant':
return realm === 'pc-garena' ? 'pathofexile.tw' : 'www.pathofexile.com'
return realm === 'pc-garena' ? 'pathofexile.tw' : 'www.pathofexile.com';
case 'ko':
return 'poe.game.daum.net'
return 'poe.game.daum.net';
}
}
export interface Config {
configVersion: number
leagueId?: string
overlayKey: string
overlayBackground: string
overlayBackgroundClose: boolean
restoreClipboard: boolean
configVersion: number;
leagueId?: string;
overlayKey: string;
overlayBackground: string;
overlayBackgroundClose: boolean;
restoreClipboard: boolean;
commands: Array<{
text: string
hotkey: string | null
send: boolean
}>
clientLog: string | null
gameConfig: string | null
windowTitle: string
logKeys: boolean
accountName: string
stashScroll: boolean
language: 'en' | 'ru' | 'cmn-Hant' | 'ko'
realm: 'pc-ggg' | 'pc-garena'
widgets: widget.Widget[]
fontSize: number
showAttachNotification: boolean
text: string;
hotkey: string | null;
send: boolean;
}>;
clientLog: string | null;
gameConfig: string | null;
windowTitle: string;
logKeys: boolean;
accountName: string;
stashScroll: boolean;
language: 'en' | 'ru' | 'cmn-Hant' | 'ko';
realm: 'pc-ggg' | 'pc-garena';
widgets: widget.Widget[];
fontSize: number;
showAttachNotification: boolean;
}
export const defaultConfig = (): Config => ({
@@ -136,33 +136,33 @@ export const defaultConfig = (): Config => ({
{
text: '/hideout',
hotkey: 'F5',
send: true
send: true,
},
{
text: '/exit',
hotkey: 'F9',
send: true
send: true,
},
{
text: '@last ty',
hotkey: null,
send: true
send: true,
},
{
text: '/invite @last',
hotkey: null,
send: true
send: true,
},
{
text: '/tradewith @last',
hotkey: null,
send: true
send: true,
},
{
text: '/hideout @last',
hotkey: null,
send: true
}
send: true,
},
],
clientLog: null,
gameConfig: null,
@@ -185,9 +185,9 @@ export const defaultConfig = (): Config => ({
anchor: {
pos: 'tl',
x: 5,
y: 5
y: 5,
},
alwaysShow: false
alwaysShow: false,
} as widget.WidgetMenu,
{
wmId: 2,
@@ -210,7 +210,7 @@ export const defaultConfig = (): Config => ({
searchStatRange: 10,
showCursor: true,
requestPricePrediction: false,
rememberCurrency: false
rememberCurrency: false,
} as widget.PriceCheckWidget,
{
wmId: 3,
@@ -230,22 +230,22 @@ export const defaultConfig = (): Config => ({
selectedStats: [
{
matcher: '#% maximum Player Resistances',
decision: 'w--'
decision: 'w--',
},
{
matcher: 'Monsters reflect #% of Physical Damage',
decision: 'd--'
decision: 'd--',
},
{
matcher: 'Monsters reflect #% of Elemental Damage',
decision: 'd--'
decision: 'd--',
},
{
matcher: 'Area contains two Unique Bosses',
decision: 'g--'
}
]
}
decision: 'g--',
},
],
},
} as ItemCheckWidget,
{
wmId: 4,
@@ -254,7 +254,7 @@ export const defaultConfig = (): Config => ({
wmWants: 'hide',
wmZorder: 4,
wmFlags: ['hide-on-focus', 'skip-menu'],
toggleKey: null
toggleKey: null,
} as widget.DelveGridWidget,
{
wmId: 5,
@@ -262,7 +262,7 @@ export const defaultConfig = (): Config => ({
wmTitle: '',
wmWants: 'hide',
wmZorder: 'exclusive',
wmFlags: ['invisible-on-blur', 'ignore-ui-visibility']
wmFlags: ['invisible-on-blur', 'ignore-ui-visibility'],
},
{
wmId: 6,
@@ -274,8 +274,8 @@ export const defaultConfig = (): Config => ({
anchor: {
pos: 'tl',
x: 10,
y: 20
}
y: 20,
},
} as ItemSearchWidget,
// --- DEFAULT ---
{
@@ -288,14 +288,14 @@ export const defaultConfig = (): Config => ({
anchor: {
pos: 'tl',
x: 35,
y: 46
y: 46,
},
entries: [
{ id: 1, name: '', text: '"Pack Size: +3"', hotkey: null },
{ id: 2, name: '', text: 'Reflect', hotkey: null },
{ id: 3, name: '', text: '"Cannot Leech Life"', hotkey: null },
{ id: 4, name: '', text: '"Cannot Leech Mana"', hotkey: null }
]
{ id: 4, name: '', text: '"Cannot Leech Mana"', hotkey: null },
],
} as StashSearchWidget,
{
wmId: 102,
@@ -307,7 +307,7 @@ export const defaultConfig = (): Config => ({
anchor: {
pos: 'tl',
x: 34,
y: 56
y: 56,
},
entries: [
{ id: 1, name: '', text: 'Currency', hotkey: null },
@@ -318,10 +318,10 @@ export const defaultConfig = (): Config => ({
id: 5,
name: '',
text: '"Map Device" "Rarity: Normal"',
hotkey: null
hotkey: null,
},
{ id: 6, name: '', text: 'Tane Laboratory', hotkey: null }
]
{ id: 6, name: '', text: 'Tane Laboratory', hotkey: null },
],
} as StashSearchWidget,
{
wmId: 103,
@@ -333,90 +333,90 @@ export const defaultConfig = (): Config => ({
anchor: {
pos: 'tc',
x: 50,
y: 10
y: 10,
},
images: [{ id: 1, url: 'syndicate.jpg' }]
} as widget.ImageStripWidget
]
})
images: [{ id: 1, url: 'syndicate.jpg' }],
} as widget.ImageStripWidget,
],
});
function upgradeConfig (_config: Config): Config {
function upgradeConfig(_config: Config): Config {
const config = _config as Omit<Config, 'widgets'> & {
widgets: Array<Record<string, any>>
}
widgets: Array<Record<string, any>>;
};
if (config.configVersion < 3) {
config.widgets.push({
...defaultConfig().widgets.find((w) => w.wmType === 'image-strip')!,
wmId: Math.max(0, ...config.widgets.map((_) => _.wmId)) + 1,
wmZorder: null
})
wmZorder: null,
});
config.widgets.push({
...defaultConfig().widgets.find((w) => w.wmType === 'delve-grid')!,
wmId: Math.max(0, ...config.widgets.map((_) => _.wmId)) + 1,
wmZorder: null
})
wmZorder: null,
});
config.widgets.find((w) => w.wmType === 'menu')!.alwaysShow = false
config.widgets.find((w) => w.wmType === 'menu')!.alwaysShow = false;
config.configVersion = 3
config.configVersion = 3;
}
if (config.configVersion < 4) {
config.widgets.find(
(w) => w.wmType === 'price-check'
)!.chaosPriceThreshold = 0.05
)!.chaosPriceThreshold = 0.05;
const mapCheck = config.widgets.find((w) => w.wmType === 'map-check')!;
(mapCheck as any).selectedStats.forEach((e: any) => {
e.matcher = e.matchRef
e.matchRef = undefined
})
e.matcher = e.matchRef;
e.matchRef = undefined;
});
{
const widgets = config.widgets.filter((w) => w.wmType === 'image-strip')!
const widgets = config.widgets.filter((w) => w.wmType === 'image-strip')!;
widgets.forEach((imgStrip: any) => {
imgStrip.images.forEach((e: any, idx: number) => {
e.id = idx
})
})
e.id = idx;
});
});
}
config.configVersion = 4
config.configVersion = 4;
}
if (config.configVersion < 5) {
config.commands.forEach((cmd) => {
cmd.send = true
})
cmd.send = true;
});
config.configVersion = 5
config.configVersion = 5;
}
if (config.configVersion < 6) {
config.widgets.find((w) => w.wmType === 'price-check')!.showRateLimitState =
(config as any).logLevel === 'debug'
(config as any).logLevel === 'debug';
config.widgets.find((w) => w.wmType === 'price-check')!.apiLatencySeconds =
2
2;
config.configVersion = 6
config.configVersion = 6;
}
if (config.configVersion < 7) {
const mapCheck = config.widgets.find((w) => w.wmType === 'map-check')!
mapCheck.wmType = 'item-check'
mapCheck.maps = { selectedStats: mapCheck.selectedStats }
const mapCheck = config.widgets.find((w) => w.wmType === 'map-check')!;
mapCheck.wmType = 'item-check';
mapCheck.maps = { selectedStats: mapCheck.selectedStats };
mapCheck.selectedStats = undefined;
(config as any).itemCheckKey = (config as any).mapCheckKey || null;
(config as any).mapCheckKey = undefined
(config as any).mapCheckKey = undefined;
config.configVersion = 7
config.configVersion = 7;
}
if (config.configVersion < 8) {
const itemCheck = config.widgets.find((w) => w.wmType === 'item-check')!;
(itemCheck as ItemCheckWidget).maps.showNewStats = false
(itemCheck as ItemCheckWidget).maps.showNewStats = false;
itemCheck.maps.selectedStats = (
itemCheck as ItemCheckWidget
).maps.selectedStats.map((entry) => ({
@@ -427,120 +427,120 @@ function upgradeConfig (_config: Config): Config {
? 'warning'
: (entry as any).valueDesirable
? 'desirable'
: 'seen'
}))
: 'seen',
}));
config.configVersion = 8
config.configVersion = 8;
}
if (config.configVersion < 9) {
config.widgets.find((w) => w.wmType === 'price-check')!.collapseListings =
'api'
'api';
config.widgets.find((w) => w.wmType === 'price-check')!.smartInitialSearch =
true
true;
config.widgets.find(
(w) => w.wmType === 'price-check'
)!.lockedInitialSearch = true
)!.lockedInitialSearch = true;
config.widgets.find(
(w) => w.wmType === 'price-check'
)!.activateStockFilter = false
)!.activateStockFilter = false;
config.configVersion = 9
config.configVersion = 9;
}
if (config.configVersion < 10) {
config.widgets.push({
...defaultConfig().widgets.find((w) => w.wmType === 'settings')!,
wmId: Math.max(0, ...config.widgets.map((_) => _.wmId)) + 1
})
wmId: Math.max(0, ...config.widgets.map((_) => _.wmId)) + 1,
});
const priceCheck = config.widgets.find((w) => w.wmType === 'price-check')!
priceCheck.hotkey = (config as any).priceCheckKey
priceCheck.hotkeyHold = (config as any).priceCheckKeyHold
priceCheck.hotkeyLocked = (config as any).priceCheckLocked
priceCheck.showSeller = (config as any).showSeller
priceCheck.searchStatRange = (config as any).searchStatRange
priceCheck.showCursor = (config as any).priceCheckShowCursor
const priceCheck = config.widgets.find((w) => w.wmType === 'price-check')!;
priceCheck.hotkey = (config as any).priceCheckKey;
priceCheck.hotkeyHold = (config as any).priceCheckKeyHold;
priceCheck.hotkeyLocked = (config as any).priceCheckLocked;
priceCheck.showSeller = (config as any).showSeller;
priceCheck.searchStatRange = (config as any).searchStatRange;
priceCheck.showCursor = (config as any).priceCheckShowCursor;
if (priceCheck.chaosPriceThreshold === 0.05) {
priceCheck.chaosPriceThreshold = 0
priceCheck.chaosPriceThreshold = 0;
}
config.configVersion = 10
config.configVersion = 10;
}
if (config.configVersion < 11) {
config.widgets.find(
(w) => w.wmType === 'price-check'
)!.requestPricePrediction = false
)!.requestPricePrediction = false;
config.configVersion = 11
config.configVersion = 11;
}
if (config.configVersion < 12) {
const afterSettings = config.widgets.findIndex(
(w) => w.wmType === 'settings'
)
);
config.widgets.splice(afterSettings + 1, 0, {
...defaultConfig().widgets.find((w) => w.wmType === 'item-search')!,
wmWants: 'show',
wmId: Math.max(0, ...config.widgets.map((_) => _.wmId)) + 1
})
wmId: Math.max(0, ...config.widgets.map((_) => _.wmId)) + 1,
});
config.realm = 'pc-ggg'
config.realm = 'pc-ggg';
if (config.language === ('zh_TW' as string)) {
config.language = 'cmn-Hant'
config.language = 'cmn-Hant';
}
config.configVersion = 12
config.configVersion = 12;
}
if (config.configVersion < 13) {
config.showAttachNotification = true
config.showAttachNotification = true;
config.configVersion = 13
config.configVersion = 13;
}
if (config.configVersion < 14) {
const imgWidgets = config.widgets.filter(
(w) => w.wmType === 'image-strip'
) as widget.ImageStripWidget[]
) as widget.ImageStripWidget[];
imgWidgets.forEach((imgStrip) => {
imgStrip.images.forEach((e) => {
e.url = e.url.startsWith('app-file://')
? e.url.slice('app-file://'.length)
: e.url
})
})
: e.url;
});
});
const itemCheck = config.widgets.find(
(w) => w.wmType === 'item-check'
) as ItemCheckWidget
itemCheck.wikiKey = (config as any).wikiKey
itemCheck.poedbKey = null
itemCheck.craftOfExileKey = (config as any).craftOfExileKey
itemCheck.stashSearchKey = null
) as ItemCheckWidget;
itemCheck.wikiKey = (config as any).wikiKey;
itemCheck.poedbKey = null;
itemCheck.craftOfExileKey = (config as any).craftOfExileKey;
itemCheck.stashSearchKey = null;
config.configVersion = 14
config.configVersion = 14;
}
if (config.configVersion < 15) {
const priceCheck = config.widgets.find(
(w) => w.wmType === 'price-check'
) as widget.PriceCheckWidget
priceCheck.builtinBrowser = false
) as widget.PriceCheckWidget;
priceCheck.builtinBrowser = false;
const itemSearch = config.widgets.find(
(w) => w.wmType === 'item-search'
) as ItemSearchWidget
itemSearch.ocrGemsKey = null
) as ItemSearchWidget;
itemSearch.ocrGemsKey = null;
const itemCheck = config.widgets.find(
(w) => w.wmType === 'item-check'
) as ItemCheckWidget
itemCheck.maps.profile = 1
) as ItemCheckWidget;
itemCheck.maps.profile = 1;
for (const stat of itemCheck.maps.selectedStats) {
const p1decision =
stat.decision === 'danger'
@@ -549,114 +549,114 @@ function upgradeConfig (_config: Config): Config {
? 'w'
: stat.decision === 'desirable'
? 'g'
: 's'
: 's';
stat.decision = `${p1decision}--`
stat.decision = `${p1decision}--`;
}
config.configVersion = 15
config.configVersion = 15;
}
if (config.configVersion < 16) {
const delve = config.widgets.find(
(w) => w.wmType === 'delve-grid'
) as widget.DelveGridWidget
delve.toggleKey = (config as any).delveGridKey
) as widget.DelveGridWidget;
delve.toggleKey = (config as any).delveGridKey;
const itemCheck = config.widgets.find(
(w) => w.wmType === 'item-check'
) as ItemCheckWidget
itemCheck.hotkey = (config as any).itemCheckKey
) as ItemCheckWidget;
itemCheck.hotkey = (config as any).itemCheckKey;
if (itemCheck.maps.profile === undefined) {
itemCheck.maps.profile = 1
itemCheck.maps.selectedStats = []
itemCheck.maps.profile = 1;
itemCheck.maps.selectedStats = [];
}
config.configVersion = 16
config.configVersion = 16;
}
if (config.logKeys === undefined) {
config.logKeys = false
config.logKeys = false;
}
const priceCheck = config.widgets.find(
(w) => w.wmType === 'price-check'
) as widget.PriceCheckWidget
) as widget.PriceCheckWidget;
if (priceCheck.rememberCurrency === undefined) {
priceCheck.rememberCurrency = false
priceCheck.rememberCurrency = false;
}
for (const widget of config.widgets) {
if (widget.wmType === 'stash-search') {
(widget as StashSearchWidget).enableHotkeys ??= true
(widget as StashSearchWidget).enableHotkeys ??= true;
}
}
return config as unknown as Config
return config as unknown as Config;
}
function getConfigForHost (): HostConfig {
const actions: ShortcutAction[] = []
function getConfigForHost(): HostConfig {
const actions: ShortcutAction[] = [];
const config = AppConfig()
const priceCheck = AppConfig('price-check') as widget.PriceCheckWidget
const config = AppConfig();
const priceCheck = AppConfig('price-check') as widget.PriceCheckWidget;
if (priceCheck.hotkey) {
actions.push({
shortcut: `${priceCheck.hotkeyHold} + ${priceCheck.hotkey}`,
action: { type: 'copy-item', target: 'price-check', focusOverlay: false },
keepModKeys: true
})
keepModKeys: true,
});
}
if (priceCheck.hotkeyLocked) {
actions.push({
shortcut: priceCheck.hotkeyLocked,
action: { type: 'copy-item', target: 'price-check', focusOverlay: true }
})
action: { type: 'copy-item', target: 'price-check', focusOverlay: true },
});
}
actions.push({
shortcut: config.overlayKey,
action: { type: 'toggle-overlay' },
keepModKeys: true
})
const itemCheck = AppConfig('item-check') as ItemCheckWidget
keepModKeys: true,
});
const itemCheck = AppConfig('item-check') as ItemCheckWidget;
if (itemCheck.wikiKey) {
actions.push({
shortcut: itemCheck.wikiKey,
action: { type: 'copy-item', target: 'open-wiki' }
})
action: { type: 'copy-item', target: 'open-wiki' },
});
}
if (itemCheck.craftOfExileKey) {
actions.push({
shortcut: itemCheck.craftOfExileKey,
action: { type: 'copy-item', target: 'open-craft-of-exile' }
})
action: { type: 'copy-item', target: 'open-craft-of-exile' },
});
}
if (itemCheck.poedbKey) {
actions.push({
shortcut: itemCheck.poedbKey,
action: { type: 'copy-item', target: 'open-poedb' }
})
action: { type: 'copy-item', target: 'open-poedb' },
});
}
if (itemCheck.stashSearchKey) {
actions.push({
shortcut: itemCheck.stashSearchKey,
action: { type: 'copy-item', target: 'search-similar' }
})
action: { type: 'copy-item', target: 'search-similar' },
});
}
if (itemCheck.hotkey) {
actions.push({
shortcut: itemCheck.hotkey,
action: { type: 'copy-item', target: 'item-check', focusOverlay: true }
})
action: { type: 'copy-item', target: 'item-check', focusOverlay: true },
});
}
const delveGrid = AppConfig('delve-grid') as widget.DelveGridWidget
const delveGrid = AppConfig('delve-grid') as widget.DelveGridWidget;
if (delveGrid.toggleKey) {
actions.push({
shortcut: delveGrid.toggleKey,
action: { type: 'trigger-event', target: 'delve-grid' },
keepModKeys: true
})
keepModKeys: true,
});
}
for (const command of config.commands) {
if (command.hotkey) {
@@ -665,35 +665,35 @@ function getConfigForHost (): HostConfig {
action: {
type: 'paste-in-chat',
text: command.text,
send: command.send
}
})
send: command.send,
},
});
}
}
for (const widget of config.widgets) {
if (widget.wmType === 'stash-search') {
const stashSearch = widget as StashSearchWidget
if (!stashSearch.enableHotkeys) continue
const stashSearch = widget as StashSearchWidget;
if (!stashSearch.enableHotkeys) continue;
for (const entry of stashSearch.entries) {
if (entry.hotkey) {
actions.push({
shortcut: entry.hotkey,
action: { type: 'stash-search', text: entry.text }
})
action: { type: 'stash-search', text: entry.text },
});
}
}
} else if (widget.wmType === 'timer') {
const stopwatch = widget as widget.StopwatchWidget
const stopwatch = widget as widget.StopwatchWidget;
if (stopwatch.toggleKey) {
actions.push({
shortcut: stopwatch.toggleKey,
keepModKeys: true,
action: {
type: 'trigger-event',
target: `stopwatch-start-stop:${widget.wmId}`
}
})
target: `stopwatch-start-stop:${widget.wmId}`,
},
});
}
if (stopwatch.resetKey) {
actions.push({
@@ -701,18 +701,18 @@ function getConfigForHost (): HostConfig {
keepModKeys: true,
action: {
type: 'trigger-event',
target: `stopwatch-reset:${widget.wmId}`
}
})
target: `stopwatch-reset:${widget.wmId}`,
},
});
}
} else if (widget.wmType === 'item-search') {
const itemSearch = widget as ItemSearchWidget
const itemSearch = widget as ItemSearchWidget;
if (itemSearch.ocrGemsKey) {
actions.push({
shortcut: itemSearch.ocrGemsKey,
keepModKeys: true,
action: { type: 'ocr-text', target: 'heist-gems' }
})
action: { type: 'ocr-text', target: 'heist-gems' },
});
}
}
}
@@ -726,6 +726,6 @@ function getConfigForHost (): HostConfig {
overlayKey: config.overlayKey,
logKeys: config.logKeys,
windowTitle: config.windowTitle,
language: config.language
}
language: config.language,
};
}

View File

@@ -1,71 +1,72 @@
import { computed, shallowRef, readonly } from 'vue'
import { createGlobalState } from '@vueuse/core'
import { AppConfig } from '@/web/Config'
import { computed, shallowRef, readonly } from 'vue';
import { createGlobalState } from '@vueuse/core';
import { AppConfig, poeWebApi } from '@/web/Config';
import { Host } from './IPC';
// pc-ggg, pc-garena
// const PERMANENT_SC = ['Standard', '標準模式']
const PERMANENT_HC = ['Hardcore', '專家模式']
const PERMANENT_HC = ['Hardcore', '專家模式'];
interface ApiLeague {
id: string
event?: boolean
rules: Array<{ id: string }>
id: string;
event?: boolean;
rules: Array<{ id: string }>;
}
interface League {
id: string
isPopular: boolean
}
export const useLeagues = createGlobalState(() => {
const isLoading = shallowRef(false)
const error = shallowRef<string | null>(null)
const tradeLeagues = shallowRef<League[]>([])
const DEFAULT_POE2_LEAGUES: ApiLeague[] = [
const DEFAULT_POE2_LEAGUES: ApiLeague[] = [
{ id: 'Standard', rules: [] },
{
id: 'Hardcore',
rules: [
{
id: 'Hardcore'
}
]
}
]
id: 'Hardcore',
},
],
},
];
interface League {
id: string;
isPopular: boolean;
}
export const useLeagues = createGlobalState(() => {
const isLoading = shallowRef(false);
const error = shallowRef<string | null>(null);
const tradeLeagues = shallowRef<League[]>([]);
const selectedId = computed<string | undefined>({
get () {
return tradeLeagues.value.length ? AppConfig().leagueId : undefined
get() {
return tradeLeagues.value.length ? AppConfig().leagueId : undefined;
},
set (id) {
AppConfig().leagueId = id
}
})
set(id) {
AppConfig().leagueId = id;
},
});
const selected = computed(() => {
const { leagueId } = AppConfig()
if (!tradeLeagues.value || !leagueId) return undefined
const listed = tradeLeagues.value.find((league) => league.id === leagueId)
const { leagueId } = AppConfig();
if (!tradeLeagues.value || !leagueId) return undefined;
const listed = tradeLeagues.value.find((league) => league.id === leagueId);
return {
id: leagueId,
realm: AppConfig().realm,
isPopular: !isPrivateLeague(leagueId) && Boolean(listed?.isPopular)
}
})
isPopular: !isPrivateLeague(leagueId) && Boolean(listed?.isPopular),
};
});
async function load () {
isLoading.value = true
error.value = null
async function load() {
isLoading.value = true;
error.value = null;
try {
// const response = await Host.proxy(
// `${poeWebApi()}/api/leagues?type=main&realm=pc`
// );
// if (!response.ok)
// throw new Error(JSON.stringify(Object.fromEntries(response.headers)));
const response = await Host.proxy(
`${poeWebApi()}/api/leagues?type=main&realm=pc`
);
if (!response.ok)
throw new Error(JSON.stringify(Object.fromEntries(response.headers)));
// const leagues: ApiLeague[] = await response.json();
const leagues: ApiLeague[] = DEFAULT_POE2_LEAGUES
const leagues: ApiLeague[] = DEFAULT_POE2_LEAGUES;
tradeLeagues.value = leagues
.filter(
(league) =>
@@ -77,25 +78,25 @@ export const useLeagues = createGlobalState(() => {
)
)
.map((league) => {
return { id: league.id, isPopular: true }
})
return { id: league.id, isPopular: true };
});
const leagueIsAlive = tradeLeagues.value.some(
(league) => league.id === selectedId.value
)
);
if (!leagueIsAlive && !isPrivateLeague(selectedId.value ?? '')) {
if (tradeLeagues.value.length > 1) {
const TMP_CHALLENGE = 1
selectedId.value = tradeLeagues.value[TMP_CHALLENGE].id
const TMP_CHALLENGE = 1;
selectedId.value = tradeLeagues.value[TMP_CHALLENGE].id;
} else {
const STANDARD = 0
selectedId.value = tradeLeagues.value[STANDARD].id
const STANDARD = 0;
selectedId.value = tradeLeagues.value[STANDARD].id;
}
}
} catch (e) {
error.value = (e as Error).message
error.value = (e as Error).message;
} finally {
isLoading.value = false
isLoading.value = false;
}
}
@@ -105,13 +106,13 @@ export const useLeagues = createGlobalState(() => {
selectedId,
selected,
list: readonly(tradeLeagues),
load
}
})
load,
};
});
function isPrivateLeague (id: string) {
function isPrivateLeague(id: string) {
if (id.includes('Ruthless')) {
return true
return true;
}
return /\(PL\d+\)$/.test(id)
return /\(PL\d+\)$/.test(id);
}

View File

@@ -19,7 +19,7 @@ import type { ItemCheckWidget } from './widget.js'
import Widget from '../overlay/Widget.vue'
import MapCheck from '../map-check/MapCheck.vue'
import ItemInfo from './ItemInfo.vue'
import ConversionWarningBanner from '../conversion-warn-banner/ConversionWarningBanner.vue'
import ConversionWarningBanner from "../conversion-warn-banner/ConversionWarningBanner.vue";
const props = defineProps<{
config: ItemCheckWidget

View File

@@ -1,53 +1,54 @@
import { Host } from '@/web/background/IPC'
import { AppConfig } from '@/web/Config'
import { ParsedItem, parseClipboard } from '@/parser'
import { Host } from '@/web/background/IPC';
import { AppConfig } from '@/web/Config';
import { ParsedItem, parseClipboard } from '@/parser';
const POEDB_LANGS = { 'en': 'us', 'ru': 'ru', 'cmn-Hant': 'tw', 'ko': 'kr' }
const POEDB_LANGS = { en: 'us', ru: 'ru', 'cmn-Hant': 'tw', ko: 'kr' };
export function registerActions () {
export function registerActions() {
Host.onEvent('MAIN->CLIENT::item-text', (e) => {
if (
![
'open-wiki',
'open-craft-of-exile',
'open-poedb',
'search-similar'
'search-similar',
].includes(e.target)
) { return }
const parsed = parseClipboard(e.clipboard)
if (!parsed.isOk()) return
)
return;
const parsed = parseClipboard(e.clipboard);
if (!parsed.isOk()) return;
if (e.target === 'open-wiki') {
openWiki(parsed.value)
openWiki(parsed.value);
} else if (e.target === 'open-craft-of-exile') {
openCoE(parsed.value)
openCoE(parsed.value);
} else if (e.target === 'open-poedb') {
openPoedb(parsed.value)
openPoedb(parsed.value);
} else if (e.target === 'search-similar') {
findSimilarItems(parsed.value)
findSimilarItems(parsed.value);
}
})
});
}
export function openWiki (item: ParsedItem) {
window.open(`https://www.poe2wiki.net/wiki/${item.info.refName}`)
export function openWiki(item: ParsedItem) {
window.open(`https://www.poe2wiki.net/wiki/${item.info.refName}`);
}
export function openPoedb (item: ParsedItem) {
export function openPoedb(item: ParsedItem) {
window.open(
`https://poe2db.tw/${POEDB_LANGS[AppConfig().language]}/search?q=${item.info.refName}`
)
);
}
export function openCoE (item: ParsedItem) {
const encodedClipboard = encodeURIComponent(item.rawText)
export function openCoE(item: ParsedItem) {
const encodedClipboard = encodeURIComponent(item.rawText);
window.open(
`https://craftofexile.com/?game=poe2&eimport=${encodedClipboard}`
)
);
}
export function findSimilarItems (item: ParsedItem) {
const text = JSON.stringify(item.info.name)
export function findSimilarItems(item: ParsedItem) {
const text = JSON.stringify(item.info.name);
Host.sendEvent({
name: 'CLIENT->MAIN::user-action',
payload: { action: 'stash-search', text }
})
payload: { action: 'stash-search', text },
});
}

View File

@@ -1,10 +1,12 @@
<template>
<transition enter-active-class="animate__animated animate__fadeIn"
leave-active-class="animate__animated animate__backOutDown">
<transition
enter-active-class="animate__animated animate__fadeIn"
leave-active-class="animate__animated animate__backOutDown"
>
<div :class="$style.widget" v-if="show">
<div :class="$style.box">
<div class="py-2 px-4">
<div class="text-base">Exiled Exchange 2</div>
<div class="text-base">Exalted PoE2 Trade</div>
<p>{{ t('app_is_ready') }}</p>
</div>
</div>
@@ -13,23 +15,23 @@
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { useI18n } from 'vue-i18n'
import { Host } from '@/web/background/IPC'
import { AppConfig } from '@/web/Config'
import { shallowRef } from 'vue';
import { useI18n } from 'vue-i18n';
import { Host } from '@/web/background/IPC';
import { AppConfig } from '@/web/Config';
const { t } = useI18n()
const { t } = useI18n();
const show = shallowRef(false)
const show = shallowRef(false);
Host.onEvent('MAIN->OVERLAY::overlay-attached', () => {
if (!show.value && AppConfig().showAttachNotification) {
show.value = true
show.value = true;
setTimeout(() => {
show.value = false
}, 2500)
show.value = false;
}, 2500);
}
})
});
</script>
<style lang="postcss" module>

View File

@@ -61,7 +61,7 @@ export default defineComponent({
required: true
}
},
setup (props) {
setup(props) {
const wm = inject<WidgetManager>('wm')!
const widgets = computed(() => {
@@ -79,17 +79,17 @@ export default defineComponent({
return {
t,
widgets,
createOfType (type: string) {
createOfType(type: string) {
wm.create(type)
},
toggle (widget: IWidget) {
toggle(widget: IWidget) {
if (widget.wmWants === 'hide') {
wm.show(widget.wmId)
} else {
wm.hide(widget.wmId)
}
},
handleItemPaste (e: Event) {
handleItemPaste(e: Event) {
const target = e.target as HTMLInputElement
const inputRect = target.getBoundingClientRect()
Host.selfDispatch({

View File

@@ -71,7 +71,7 @@ export default defineComponent({
required: true
}
},
setup (props) {
setup(props) {
const widget = computed(() => AppConfig<PriceCheckWidget>('price-check')!)
const leagues = useLeagues()
@@ -177,7 +177,7 @@ export default defineComponent({
props.item.info.unique == null)
})
function handleSearchMouseenter (e: MouseEvent) {
function handleSearchMouseenter(e: MouseEvent) {
if ((filtersComponent.value.$el as HTMLElement).contains(e.relatedTarget as HTMLElement)) {
doSearch.value = true
@@ -216,10 +216,10 @@ export default defineComponent({
showSupportLinks,
presets: computed(() => presets.value.presets.map(preset =>
({ id: preset.id, active: (preset.id === presets.value.active) }))),
selectPreset (id: string) {
selectPreset(id: string) {
presets.value.active = id
},
makeTradeLink () {
makeTradeLink() {
return `https://${getTradeEndpoint()}/trade2/search/poe2/${itemFilters.value.trade.league}?q=${JSON.stringify(createTradeRequest(itemFilters.value, itemStats.value, props.item))}`
}
}

View File

@@ -117,26 +117,35 @@
</template>
<script lang="ts">
import { defineComponent, inject, PropType, shallowRef, watch, computed, nextTick, provide } from 'vue'
import { Result, ok, err } from 'neverthrow'
import { useI18n } from 'vue-i18n'
import UiErrorBox from '@/web/ui/UiErrorBox.vue'
import UiPopover from '@/web/ui/Popover.vue'
import CheckedItem from './CheckedItem.vue'
import BackgroundInfo from './BackgroundInfo.vue'
import { MainProcess, Host } from '@/web/background/IPC'
import { usePoeninja } from '../background/Prices'
import { useLeagues } from '@/web/background/Leagues'
import { AppConfig } from '@/web/Config'
import { ItemCategory, ItemRarity, parseClipboard, ParsedItem } from '@/parser'
import RelatedItems from './related-items/RelatedItems.vue'
import RateLimiterState from './trade/RateLimiterState.vue'
import UnidentifiedResolver from './unidentified-resolver/UnidentifiedResolver.vue'
import CheckPositionCircle from './CheckPositionCircle.vue'
import AppTitleBar from '@/web/ui/AppTitlebar.vue'
import ItemQuickPrice from '@/web/ui/ItemQuickPrice.vue'
import { PriceCheckWidget, WidgetManager } from '../overlay/interfaces'
import ConversionWarningBanner from '../conversion-warn-banner/ConversionWarningBanner.vue'
import {
defineComponent,
inject,
PropType,
shallowRef,
watch,
computed,
nextTick,
provide,
} from 'vue';
import { Result, ok, err } from 'neverthrow';
import { useI18n } from 'vue-i18n';
import UiErrorBox from '@/web/ui/UiErrorBox.vue';
import UiPopover from '@/web/ui/Popover.vue';
import CheckedItem from './CheckedItem.vue';
import BackgroundInfo from './BackgroundInfo.vue';
import { MainProcess, Host } from '@/web/background/IPC';
import { usePoeninja } from '../background/Prices';
import { useLeagues } from '@/web/background/Leagues';
import { AppConfig } from '@/web/Config';
import { ItemCategory, ItemRarity, parseClipboard, ParsedItem } from '@/parser';
import RelatedItems from './related-items/RelatedItems.vue';
import RateLimiterState from './trade/RateLimiterState.vue';
import UnidentifiedResolver from './unidentified-resolver/UnidentifiedResolver.vue';
import CheckPositionCircle from './CheckPositionCircle.vue';
import AppTitleBar from '@/web/ui/AppTitlebar.vue';
import ItemQuickPrice from '@/web/ui/ItemQuickPrice.vue';
import { PriceCheckWidget, WidgetManager } from '../overlay/interfaces';
import ConversionWarningBanner from '../conversion-warn-banner/ConversionWarningBanner.vue';
type ParseError = {
name: string;
@@ -156,40 +165,44 @@ export default defineComponent({
ItemQuickPrice,
UiErrorBox,
UiPopover,
ConversionWarningBanner
ConversionWarningBanner,
},
props: {
config: {
type: Object as PropType<PriceCheckWidget>,
required: true
}
required: true,
},
setup (props) {
const wm = inject<WidgetManager>('wm')!
const { xchgRate, initialLoading: xchgRateLoading, queuePricesFetch } = usePoeninja()
},
setup(props) {
const wm = inject<WidgetManager>('wm')!;
const {
xchgRate,
initialLoading: xchgRateLoading,
queuePricesFetch,
} = usePoeninja();
nextTick(() => {
props.config.wmWants = 'hide'
props.config.wmFlags = ['hide-on-blur', 'skip-menu']
})
props.config.wmWants = 'hide';
props.config.wmFlags = ['hide-on-blur', 'skip-menu'];
});
const item = shallowRef<null | Result<ParsedItem, ParseError>>(null)
const advancedCheck = shallowRef(false)
const checkPosition = shallowRef({ x: 1, y: 1 })
const item = shallowRef<null | Result<ParsedItem, ParseError>>(null);
const advancedCheck = shallowRef(false);
const checkPosition = shallowRef({ x: 1, y: 1 });
MainProcess.onEvent('MAIN->CLIENT::item-text', (e) => {
if (e.target !== 'price-check') return
if (e.target !== 'price-check') return;
if (Host.isElectron && !e.focusOverlay) {
// everything in CSS pixels
const width = 28.75 * AppConfig().fontSize
const width = 28.75 * AppConfig().fontSize;
const screenX =
e.position.x - window.screenX > window.innerWidth / 2
? window.screenX +
window.innerWidth -
wm.poePanelWidth.value -
width
: window.screenX + wm.poePanelWidth.value
: window.screenX + wm.poePanelWidth.value;
MainProcess.sendEvent({
name: 'OVERLAY->MAIN::track-area',
payload: {
@@ -200,16 +213,16 @@ export default defineComponent({
x: screenX,
y: window.screenY,
width,
height: window.innerHeight
height: window.innerHeight,
},
dpr: window.devicePixelRatio
dpr: window.devicePixelRatio,
},
});
}
})
}
closeBrowser()
wm.show(props.config.wmId)
checkPosition.value = e.position
advancedCheck.value = e.focusOverlay
closeBrowser();
wm.show(props.config.wmId);
checkPosition.value = e.position;
advancedCheck.value = e.focusOverlay;
item.value = (
e.item ? ok(e.item as ParsedItem) : parseClipboard(e.clipboard)
@@ -225,89 +238,100 @@ export default defineComponent({
.mapErr((err) => ({
name: `${err}`,
message: `${err}_help`,
rawText: e.clipboard
}))
rawText: e.clipboard,
}));
if (item.value.isOk()) {
queuePricesFetch()
queuePricesFetch();
}
})
});
function handleIdentification (identified: ParsedItem) {
item.value = ok(identified)
function handleIdentification(identified: ParsedItem) {
item.value = ok(identified);
}
MainProcess.onEvent('MAIN->OVERLAY::hide-exclusive-widget', () => {
wm.hide(props.config.wmId)
})
wm.hide(props.config.wmId);
});
watch(
() => props.config.wmWants,
(state) => {
if (state === 'hide') {
closeBrowser()
closeBrowser();
}
}
)
);
const leagues = useLeagues()
const title = computed(() => leagues.selectedId.value || 'Exiled Exchange 2')
const stableOrbCost = computed(() => (xchgRate.value) ? Math.round(xchgRate.value) : null)
const isBrowserShown = computed(() => props.config.wmFlags.includes('has-browser'))
const overlayKey = computed(() => AppConfig().overlayKey)
const showCheckPos = computed(() => wm.active.value && props.config.showCursor)
const isLeagueSelected = computed(() => Boolean(leagues.selectedId.value))
const leagues = useLeagues();
const title = computed(
() => leagues.selectedId.value || 'Exalted PoE2 Trade'
);
const stableOrbCost = computed(() =>
xchgRate.value ? Math.round(xchgRate.value) : null
);
const isBrowserShown = computed(() =>
props.config.wmFlags.includes('has-browser')
);
const overlayKey = computed(() => AppConfig().overlayKey);
const showCheckPos = computed(
() => wm.active.value && props.config.showCursor
);
const isLeagueSelected = computed(() => Boolean(leagues.selectedId.value));
const clickPosition = computed(() => {
if (isBrowserShown.value) {
return 'inventory'
return 'inventory';
} else {
return checkPosition.value.x > (window.screenX + window.innerWidth / 2)
return checkPosition.value.x > window.screenX + window.innerWidth / 2
? 'inventory'
: 'stash'
: 'stash';
// or {chat, vendor, center of screen}
}
})
});
watch(isBrowserShown, (isShown) => {
if (isShown) {
wm.setFlag(props.config.wmId, 'hide-on-blur', false)
wm.setFlag(props.config.wmId, 'invisible-on-blur', true)
wm.setFlag(props.config.wmId, 'hide-on-blur', false);
wm.setFlag(props.config.wmId, 'invisible-on-blur', true);
} else {
wm.setFlag(props.config.wmId, 'invisible-on-blur', false)
wm.setFlag(props.config.wmId, 'hide-on-blur', true)
wm.setFlag(props.config.wmId, 'invisible-on-blur', false);
wm.setFlag(props.config.wmId, 'hide-on-blur', true);
}
})
});
function closePriceCheck () {
function closePriceCheck() {
if (isBrowserShown.value || !Host.isElectron) {
wm.hide(props.config.wmId)
wm.hide(props.config.wmId);
} else {
Host.sendEvent({ name: 'OVERLAY->MAIN::focus-game', payload: undefined })
Host.sendEvent({
name: 'OVERLAY->MAIN::focus-game',
payload: undefined,
});
}
}
function openLeagueSelection () {
const settings = wm.widgets.value.find(w => w.wmType === 'settings')!
wm.setFlag(settings.wmId, `settings:widget:${props.config.wmId}`, true)
wm.show(settings.wmId)
function openLeagueSelection() {
const settings = wm.widgets.value.find((w) => w.wmType === 'settings')!;
wm.setFlag(settings.wmId, `settings:widget:${props.config.wmId}`, true);
wm.show(settings.wmId);
}
const iframeEl = shallowRef<HTMLIFrameElement | null>(null)
const iframeEl = shallowRef<HTMLIFrameElement | null>(null);
function showBrowser (url: string) {
wm.setFlag(props.config.wmId, 'has-browser', true)
function showBrowser(url: string) {
wm.setFlag(props.config.wmId, 'has-browser', true);
nextTick(() => {
iframeEl.value!.src = url
})
iframeEl.value!.src = url;
});
}
function closeBrowser () {
wm.setFlag(props.config.wmId, 'has-browser', false)
function closeBrowser() {
wm.setFlag(props.config.wmId, 'has-browser', false);
}
provide<(url: string) => void>('builtin-browser', showBrowser)
provide<(url: string) => void>('builtin-browser', showBrowser);
const { t } = useI18n()
const { t } = useI18n();
return {
t,
@@ -325,8 +349,8 @@ export default defineComponent({
handleIdentification,
overlayKey,
isLeagueSelected,
openLeagueSelection
}
}
})
openLeagueSelection,
};
},
});
</script>

View File

@@ -63,7 +63,7 @@ const stats = computed(() => {
if (!parsed.roll) {
return {
text: parsed.translation.string,
contribution,
contribution: contribution,
contributes: true
}
}

View File

@@ -176,7 +176,7 @@ export function createFilters (
}
filters.searchRelaxed = {
category: item.category,
disabled
disabled: disabled
}
}
}

View File

@@ -177,7 +177,7 @@ export function calculatedStatToFilter (
? FilterTag.Enchant
: FilterTag.Variant,
oils: decodeOils(calc),
sources,
sources: sources,
option: {
value: sources[0].contributes!.value
},
@@ -197,7 +197,7 @@ export function calculatedStatToFilter (
text: translation.string,
tag: (type as unknown) as FilterTag,
oils: decodeOils(calc),
sources,
sources: sources,
roll: undefined,
disabled: true
}
@@ -288,7 +288,7 @@ export function calculatedStatToFilter (
bounds: (item.rarity === ItemRarity.Unique && roll.min !== roll.max && calc.stat.better !== StatBetter.NotComparable)
? filterBounds
: undefined,
dp,
dp: dp,
isNegated: false,
tradeInvert: calc.stat.trade.inverted
}

View File

@@ -335,7 +335,7 @@ export function filterPseudo (ctx: FiltersCreationContext) {
const filter = calculatedStatToFilter({
stat: STAT_BY_REF(rule.pseudo)!,
type: ModifierType.Pseudo,
sources
sources: sources
}, ctx.searchInRange, ctx.item)
filter.disabled = rule.disabled ?? true

View File

@@ -257,7 +257,7 @@ function propToFilter (opts: {
better: StatBetter.PositiveRoll
}
const filter = calculatedStatToFilter({
stat,
stat: stat,
type: ModifierType.Pseudo,
sources: [{
modifier: {
@@ -265,7 +265,7 @@ function propToFilter (opts: {
stats: []
},
stat: {
stat,
stat: stat,
translation: stat.matchers[0],
roll: {
dp: opts.dp ?? false,

View File

@@ -1,79 +1,79 @@
import { ParsedItem } from '@/parser'
import { useLeagues } from '@/web/background/Leagues'
import { Host } from '@/web/background/IPC'
import { Cache } from '../trade/Cache'
import { usePoeninja } from '@/web/background/Prices'
import { ParsedItem } from '@/parser';
import { useLeagues } from '@/web/background/Leagues';
import { Host } from '@/web/background/IPC';
import { Cache } from '../trade/Cache';
import { usePoeninja } from '@/web/background/Prices';
const cache = new Cache()
const cache = new Cache();
interface PoepricesApiResponse {
/* eslint-disable camelcase */ currency: 'chaos' | 'divine' | 'exalt'
error: number
error_msg: string
warning_msg: string
max: number
min: number
pred_confidence_score: number
pred_explanation: Array<[string, number]>
/* eslint-disable camelcase */ currency: 'chaos' | 'divine' | 'exalt';
error: number;
error_msg: string;
warning_msg: string;
max: number;
min: number;
pred_confidence_score: number;
pred_explanation: Array<[string, number]>;
}
export interface RareItemPrice {
max: number
min: number
confidence: number
currency: 'chaos' | 'div'
max: number;
min: number;
confidence: number;
currency: 'chaos' | 'div';
explanation: Array<{
name: string
contrib: number
}>
name: string;
contrib: number;
}>;
}
export async function requestPoeprices (
export async function requestPoeprices(
item: ParsedItem
): Promise<RareItemPrice> {
const query = querystring({
i: utf8ToBase64(transformItemText(item.rawText)),
l: useLeagues().selectedId.value,
s: 'awakened-poe-trade' // might be required name here
})
s: 'awakened-poe-trade', // might be required name here
});
let data = cache.get<PoepricesApiResponse>(query)
let data = cache.get<PoepricesApiResponse>(query);
if (!data) {
const response = await Host.proxy(`www.poeprices.info/api?${query}`)
const response = await Host.proxy(`www.poeprices.info/api?${query}`);
try {
data = (await response.json()) as PoepricesApiResponse
data = (await response.json()) as PoepricesApiResponse;
} catch (e) {
throw new Error(
`${response.status}, poeprices.info API is under load or down.`
)
);
}
if (data.error !== 0) {
throw new Error(data.error_msg)
throw new Error(data.error_msg);
}
cache.set<PoepricesApiResponse>(query, data, 300)
cache.set<PoepricesApiResponse>(query, data, 300);
}
if (data.currency === 'exalt') {
const { findPriceByQuery, autoCurrency } = usePoeninja()
const { findPriceByQuery, autoCurrency } = usePoeninja();
const xchgExalted = findPriceByQuery({
ns: 'ITEM',
name: 'Exalted Orb',
variant: undefined
})
variant: undefined,
});
if (!xchgExalted) {
throw new Error('poeprices.info gave the price in Exalted Orbs.')
throw new Error('poeprices.info gave the price in Exalted Orbs.');
}
const converted = autoCurrency([
data.min * xchgExalted.chaos,
data.max * xchgExalted.chaos
])
data.min = converted.min
data.max = converted.max
data.currency = converted.currency === 'div' ? 'divine' : 'chaos'
data.max * xchgExalted.chaos,
]);
data.min = converted.min;
data.max = converted.max;
data.currency = converted.currency === 'div' ? 'divine' : 'chaos';
} else if (data.currency !== 'divine' && data.currency !== 'chaos') {
throw new Error('poeprices.info gave the price in unknown currency.')
throw new Error('poeprices.info gave the price in unknown currency.');
}
return {
@@ -83,62 +83,62 @@ export async function requestPoeprices (
confidence: Math.round(data.pred_confidence_score),
explanation: data.pred_explanation.map((expl) => ({
name: expl[0],
contrib: Math.round(expl[1] * 100)
}))
}
contrib: Math.round(expl[1] * 100),
})),
};
}
export function getExternalLink (item: ParsedItem): string {
export function getExternalLink(item: ParsedItem): string {
const query = querystring({
i: utf8ToBase64(transformItemText(item.rawText)),
l: useLeagues().selectedId.value,
s: 'awakened-poe-trade',
w: 1
})
return `https://www.poeprices.info/api?${query}`
w: 1,
});
return `https://www.poeprices.info/api?${query}`;
}
export async function sendFeedback (
feedback: { text: string, option: 'fair' | 'low' | 'high' },
export async function sendFeedback(
feedback: { text: string; option: 'fair' | 'low' | 'high' },
prediction: Pick<PoepricesApiResponse, 'min' | 'max' | 'currency'>,
item: ParsedItem
): Promise<void> {
const body = new FormData()
body.append('selector', feedback.option)
body.append('feedbacktxt', feedback.text)
body.append('qitem_txt', utf8ToBase64(transformItemText(item.rawText)))
body.append('source', 'awakened-poe-trade')
body.append('min', String(prediction.min))
body.append('max', String(prediction.max))
body.append('currency', prediction.currency)
body.append('league', useLeagues().selectedId.value!)
const body = new FormData();
body.append('selector', feedback.option);
body.append('feedbacktxt', feedback.text);
body.append('qitem_txt', utf8ToBase64(transformItemText(item.rawText)));
body.append('source', 'awakened-poe-trade');
body.append('min', String(prediction.min));
body.append('max', String(prediction.max));
body.append('currency', prediction.currency);
body.append('league', useLeagues().selectedId.value!);
// body.append('debug', String(1))
const response = await Host.proxy('www.poeprices.info/send_feedback', {
method: 'POST',
body
})
body,
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const text = await response.text()
const text = await response.text();
// console.assert(text === `"${feedback.option}"`)
}
function utf8ToBase64 (value: string) {
return btoa(unescape(encodeURIComponent(value)))
function utf8ToBase64(value: string) {
return btoa(unescape(encodeURIComponent(value)));
}
function querystring (q: Record<string, any>) {
function querystring(q: Record<string, any>) {
return Object.entries(q)
.map((pair) => pair.map(encodeURIComponent).join('='))
.join('&')
.join('&');
}
/**
* @deprecated TODO blocked by poeprices.info not supporting advanced text
*/
function transformItemText (rawText: string) {
function transformItemText(rawText: string) {
// this may not account for all cases
return rawText
.replace(/(?<=\d)(\([^)]+\))/gm, '')
.replace(/^\{.+\}$\n/gm, '')
.replace(/^\{.+\}$\n/gm, '');
}

View File

@@ -111,7 +111,7 @@ import TradeLinks from './TradeLinks.vue'
const slowdown = artificialSlowdown(900)
function useBulkApi () {
function useBulkApi() {
type BulkSearchExtended = Record<'xchgChaos' | 'xchgStable', {
listed: Ref<BulkSearch | null>
listedLazy: ComputedRef<PricingResult[]>
@@ -121,7 +121,7 @@ function useBulkApi () {
const error = shallowRef<string | null>(null)
const result = shallowRef<BulkSearchExtended | null>(null)
async function search (item: ParsedItem, filters: ItemFilters) {
async function search(item: ParsedItem, filters: ItemFilters) {
try {
searchId += 1
error.value = null
@@ -149,7 +149,7 @@ function useBulkApi () {
}
}
function getResultsByHave (
function getResultsByHave(
item: ParsedItem,
filters: ItemFilters,
preloaded: Array<BulkSearch | null>,
@@ -203,7 +203,7 @@ export default defineComponent({
required: true
}
},
setup (props) {
setup(props) {
const widget = computed(() => AppConfig<PriceCheckWidget>('price-check')!)
const { error, result, search } = useBulkApi()
@@ -236,7 +236,7 @@ export default defineComponent({
}
})
function makeTradeLink (_have?: string[]) {
function makeTradeLink(_have?: string[]) {
const have = _have ?? ((selectedCurr.value === 'xchgStable') ? ['divine'] : ['chaos'])
const httpPostBody = createTradeRequest(props.filters, props.item, have)
const httpGetQuery = { exchange: httpPostBody.query }
@@ -254,7 +254,7 @@ export default defineComponent({
execSearch: () => { search(props.item, props.filters) },
showSeller: computed(() => widget.value.showSeller),
makeTradeLink,
openTradeLink () {
openTradeLink() {
showBrowser(makeTradeLink(['mirror']))
}
}

View File

@@ -105,7 +105,7 @@ const API_FETCH_LIMIT = 100
const MIN_NOT_GROUPED = 7
const MIN_GROUPED = 10
function useTradeApi () {
function useTradeApi() {
let searchId = 0
const error = shallowRef<string | null>(null)
const searchResult = shallowRef<SearchResult | null>(null)
@@ -143,7 +143,7 @@ function useTradeApi () {
return out
})
async function search (filters: ItemFilters, stats: StatFilter[], item: ParsedItem) {
async function search(filters: ItemFilters, stats: StatFilter[], item: ParsedItem) {
try {
searchId += 1
error.value = null
@@ -174,7 +174,7 @@ function useTradeApi () {
}
let fetched = 20
async function fetchMore (): Promise<void> {
async function fetchMore(): Promise<void> {
if (_searchId !== searchId) return
const totalGrouped = groupedResults.value.length
const totalNotGrouped = groupedResults.value.reduce((len, res) =>
@@ -215,7 +215,7 @@ export default defineComponent({
required: true
}
},
setup (props) {
setup(props) {
const widget = computed(() => AppConfig<PriceCheckWidget>('price-check')!)
watch(() => props.item, (item) => {
@@ -226,7 +226,7 @@ export default defineComponent({
const showBrowser = inject<(url: string) => void>('builtin-browser')!
function makeTradeLink () {
function makeTradeLink() {
return (searchResult.value)
? `https://${getTradeEndpoint()}/trade2/search/poe2/${props.filters.trade.league}/${searchResult.value.id}`
: `https://${getTradeEndpoint()}/trade2/search/poe2/${props.filters.trade.league}?q=${JSON.stringify(createTradeRequest(props.filters, props.stats, props.item))}`
@@ -253,7 +253,7 @@ export default defineComponent({
error,
showSeller: computed(() => widget.value.showSeller),
makeTradeLink,
openTradeLink () {
openTradeLink() {
showBrowser(makeTradeLink())
}
}

View File

@@ -1,5 +1,5 @@
import { DateTime } from 'luxon'
import { Host } from '@/web/background/IPC'
import { DateTime } from 'luxon';
import { Host } from '@/web/background/IPC';
import {
TradeResponse,
Account,
@@ -7,105 +7,105 @@ import {
RATE_LIMIT_RULES,
adjustRateLimits,
tradeTag,
preventQueueCreation
} from './common'
import { RateLimiter } from './RateLimiter'
import { ItemFilters } from '../filters/interfaces'
import { ParsedItem } from '@/parser'
import { Cache } from './Cache'
preventQueueCreation,
} from './common';
import { RateLimiter } from './RateLimiter';
import { ItemFilters } from '../filters/interfaces';
import { ParsedItem } from '@/parser';
import { Cache } from './Cache';
interface TradeRequest {
/* eslint-disable camelcase */ engine: 'new'
/* eslint-disable camelcase */ engine: 'new';
query: {
status: { option: 'online' | 'onlineleague' | 'any' }
have: string[]
want: string[]
minimum?: number
fulfillable?: null
}
sort: { have: 'asc' }
status: { option: 'online' | 'onlineleague' | 'any' };
have: string[];
want: string[];
minimum?: number;
fulfillable?: null;
};
sort: { have: 'asc' };
}
interface SearchResult {
id: string
result: Record<string, FetchResult>
total: number
id: string;
result: Record<string, FetchResult>;
total: number;
}
interface FetchResult {
id: string
id: string;
listing: {
indexed: string
indexed: string;
offers: Array<{
exchange: {
currency: string
amount: number
}
currency: string;
amount: number;
};
item: {
amount: number
stock: number
}
}>
account: Account
}
amount: number;
stock: number;
};
}>;
account: Account;
};
}
export interface PricingResult {
id: string
relativeDate: string
exchangeAmount: number
itemAmount: number
stock: number
accountStatus: 'offline' | 'online' | 'afk'
isMine: boolean
accountName: string
ign: string
id: string;
relativeDate: string;
exchangeAmount: number;
itemAmount: number;
stock: number;
accountStatus: 'offline' | 'online' | 'afk';
isMine: boolean;
accountName: string;
ign: string;
}
const cache = new Cache()
const cache = new Cache();
async function requestTradeResultList (
async function requestTradeResultList(
body: TradeRequest,
leagueId: string
): Promise<SearchResult> {
let data = cache.get<SearchResult>([body, leagueId])
let data = cache.get<SearchResult>([body, leagueId]);
if (!data) {
preventQueueCreation([{ count: 1, limiters: RATE_LIMIT_RULES.EXCHANGE }])
preventQueueCreation([{ count: 1, limiters: RATE_LIMIT_RULES.EXCHANGE }]);
await RateLimiter.waitMulti(RATE_LIMIT_RULES.EXCHANGE)
await RateLimiter.waitMulti(RATE_LIMIT_RULES.EXCHANGE);
const response = await Host.proxy(
`${getTradeEndpoint()}/api/trade2/exchange/${leagueId}`,
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(body)
body: JSON.stringify(body),
}
)
adjustRateLimits(RATE_LIMIT_RULES.EXCHANGE, response.headers)
);
adjustRateLimits(RATE_LIMIT_RULES.EXCHANGE, response.headers);
const _data = (await response.json()) as TradeResponse<SearchResult>
const _data = (await response.json()) as TradeResponse<SearchResult>;
if (_data.error) {
throw new Error(_data.error.message)
throw new Error(_data.error.message);
} else {
data = _data
data = _data;
}
cache.set<SearchResult>(
[body, leagueId],
data,
Cache.deriveTtl(...RATE_LIMIT_RULES.EXCHANGE)
)
);
}
return data
return data;
}
function toPricingResult (
function toPricingResult(
result: FetchResult,
opts: { accountName: string },
offer: number
@@ -125,18 +125,18 @@ function toPricingResult (
? result.listing.account.online.status === 'afk'
? 'afk'
: 'online'
: 'offline'
}
: 'offline',
};
}
export interface BulkSearch {
queryId: string
haveTag: string
total: number
listed: PricingResult[]
queryId: string;
haveTag: string;
total: number;
listed: PricingResult[];
}
export function createTradeRequest (
export function createTradeRequest(
filters: ItemFilters,
item: ParsedItem,
have: string[]
@@ -144,29 +144,29 @@ export function createTradeRequest (
return {
engine: 'new',
query: {
have,
have: have,
want: [tradeTag(item)!],
status: {
option: filters.trade.offline
? 'any'
: filters.trade.onlineInLeague
? 'onlineleague'
: 'online'
: 'online',
},
minimum:
filters.stackSize && !filters.stackSize.disabled
? filters.stackSize.value
: undefined
: undefined,
// fulfillable: null
},
sort: { have: 'asc' }
}
sort: { have: 'asc' },
};
}
const SHOW_RESULTS = 20
const API_FETCH_LIMIT = 100
const SHOW_RESULTS = 20;
const API_FETCH_LIMIT = 100;
export async function execBulkSearch (
export async function execBulkSearch(
item: ParsedItem,
filters: ItemFilters,
have: string[],
@@ -175,23 +175,23 @@ export async function execBulkSearch (
const query = await requestTradeResultList(
createTradeRequest(filters, item, have),
filters.trade.league
)
);
const offer = 0
const offer = 0;
const results = Object.values(query.result).filter(
(result) => result.listing.offers.length === 1
)
);
const resultByHave = have.map((tradeTag) => {
const resultsTag = results.filter(
(result) => result.listing.offers[offer].exchange.currency === tradeTag
)
);
const loadedOnDemand =
tradeTag === 'chaos' &&
resultsTag.length < SHOW_RESULTS &&
query.total > API_FETCH_LIMIT
if (loadedOnDemand) return null
query.total > API_FETCH_LIMIT;
if (loadedOnDemand) return null;
const listed = resultsTag
.sort(
@@ -202,13 +202,13 @@ export async function execBulkSearch (
b.listing.offers[offer].item.amount
)
.slice(0, SHOW_RESULTS)
.map((result) => toPricingResult(result, opts, offer))
.map((result) => toPricingResult(result, opts, offer));
const chaosIsLoaded =
tradeTag === 'divine' &&
resultsTag.length < results.length &&
(results.length - resultsTag.length >= SHOW_RESULTS ||
query.total <= API_FETCH_LIMIT)
query.total <= API_FETCH_LIMIT);
return {
queryId: query.id,
@@ -217,9 +217,9 @@ export async function execBulkSearch (
total: chaosIsLoaded
? resultsTag.length
: query.total - (results.length - resultsTag.length),
listed
}
})
listed: listed,
};
});
return resultByHave
return resultByHave;
}

File diff suppressed because it is too large Load Diff

View File

@@ -104,7 +104,7 @@ export default defineComponent({
: autoCurrency(trend.chaos)
return {
price,
price: price,
change: deltaFromGraph(trend.graph),
url: trend.url
}

View File

@@ -28,7 +28,7 @@ export default defineComponent({
default: null
}
},
setup (props, ctx) {
setup(props, ctx) {
const identifiedVariants = computed(() => {
const baseType = props.item!.info.refName
const possible: BaseType[] = []
@@ -55,10 +55,10 @@ export default defineComponent({
!props.item.info.unique
})
function select (info: BaseType) {
function select(info: BaseType) {
const newItem: ParsedItem = {
...props.item!,
info
info: info
}
ctx.emit('identify', newItem)
}

View File

@@ -69,7 +69,7 @@ import SettingsStopwatch from './stopwatch.vue'
import SettingsItemSearch from '../item-search/settings-item-search.vue'
import ConversionWarningBanner from '../conversion-warn-banner/ConversionWarningBanner.vue'
function shuffle<T> (array: T[]): T[] {
function shuffle<T>(array: T[]): T[] {
let currentIndex = array.length
while (currentIndex !== 0) {
const randomIndex = Math.floor(Math.random() * currentIndex)
@@ -80,7 +80,7 @@ function shuffle<T> (array: T[]): T[] {
return array
}
function quit () {
function quit() {
Host.sendEvent({
name: 'CLIENT->MAIN::user-action',
payload: { action: 'quit' }
@@ -95,7 +95,7 @@ export default defineComponent({
required: true
}
},
setup (props) {
setup(props) {
const wm = inject<WidgetManager>('wm')!
const { t } = useI18n()
@@ -143,7 +143,7 @@ export default defineComponent({
menuByType(configWidget.value?.wmType)
.map(group => group.map(component => ({
name: t(component.name!),
select () { selectedComponent.value = component },
select() { selectedComponent.value = component },
isSelected: (selectedComponent.value === component),
type: 'menu-item' as const
}))),
@@ -152,14 +152,14 @@ export default defineComponent({
return {
t,
save () {
save() {
updateConfig(configClone.value!)
saveConfig()
pushHostConfig()
wm.hide(props.config.wmId)
},
cancel () {
cancel() {
wm.hide(props.config.wmId)
},
quit,
@@ -178,13 +178,13 @@ export default defineComponent({
})
}),
podiumVisible,
showPodium () { podiumVisible.value = true },
hidePodium () { podiumVisible.value = false }
showPodium() { podiumVisible.value = true },
hidePodium() { podiumVisible.value = false }
}
}
})
function menuByType (type?: string) {
function menuByType(type?: string) {
switch (type) {
case 'stash-search':
return [[SettingsStashSearch]]
@@ -206,7 +206,7 @@ function menuByType (type?: string) {
}
}
function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
function flatJoin<T, J>(arr: T[][], joinEl: () => J) {
const out: Array<T | J> = []
for (const nested of arr) {
out.push(...nested)

View File

@@ -1,101 +1,129 @@
<template>
<div class="p-2 flex flex-col h-full items-center">
<div class="flex flex-col items-center p-2 mb-4">
<img class="w-12 h-12" src="/images/TransferOrb.png">
<p class="text-base">Exiled Exchange 2</p>
<img class="w-12 h-12" src="/images/exa.png" />
<p class="text-base">Exalted PoE2 Trade</p>
<p class="">{{ t('app.version', [version]) }}</p>
<div class="flex gap-2">
<a class="border-b" href="https://github.com/Kvan7/exiled-exchange-2/releases" target="_blank">{{
t('app.release_notes') }}</a>
<a class="border-b" href="https://github.com/Kvan7/exiled-exchange-2/issues" target="_blank">{{
t('app.report_bug') }}</a>
<a
class="border-b"
href="https://github.com/Kvan7/exalted-poe2-trade/releases"
target="_blank"
>{{ t('app.release_notes') }}</a
>
<a
class="border-b"
href="https://github.com/Kvan7/exalted-poe2-trade/issues"
target="_blank"
>{{ t('app.report_bug') }}</a
>
</div>
</div>
<div class="border border-gray-600 rounded p-2 whitespace-nowrap min-w-min w-72">
<div
class="border border-gray-600 rounded p-2 whitespace-nowrap min-w-min w-72"
>
<p>{{ info.str1 }}</p>
<p>{{ info.str2 }}</p>
<button v-if="info.action" @click="info.action" class="btn w-full mt-1">{{ info.actionText }}</button>
<button v-if="info.action" @click="info.action" class="btn w-full mt-1">
{{ info.actionText }}
</button>
</div>
<div class="text-center mt-auto py-8">
<p>{{ t('app.contact_me') }} <br><span
class="font-sans text-gray-500 select-all">&lt;@295216259795124225&gt;</span></p>
<p>
{{ t('app.contact_me') }} <br /><span
class="font-sans text-gray-500 select-all"
>&lt;@295216259795124225&gt;</span
>
</p>
<ul class="flex gap-4">
<li><img class="rounded inline" src="/images/dc_tft.gif"> <a class="border-b" href="https://discord.gg/tftrove"
target="_blank">The Forbidden Trove</a></li>
<li><img class="rounded inline" src="/images/dc_reddit.png"> <a class="border-b"
href="https://discord.gg/pathofexile" target="_blank">r/pathofexile</a></li>
<li>
<img class="rounded inline" src="/images/dc_tft.gif" />
<a class="border-b" href="https://discord.gg/tftrove" target="_blank"
>The Forbidden Trove</a
>
</li>
<li>
<img class="rounded inline" src="/images/dc_reddit.png" />
<a
class="border-b"
href="https://discord.gg/pathofexile"
target="_blank"
>r/pathofexile</a
>
</li>
</ul>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { Host } from '@/web/background/IPC'
import { DateTime } from 'luxon'
import { defineComponent, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { Host } from '@/web/background/IPC';
import { DateTime } from 'luxon';
function checkForUpdates () {
function checkForUpdates() {
Host.sendEvent({
name: 'CLIENT->MAIN::user-action',
payload: { action: 'check-for-update' }
})
payload: { action: 'check-for-update' },
});
}
function openDownloadPage () {
window.open('https://github.com/Kvan7/exiled-exchange-2/releases')
function openDownloadPage() {
// don't have this setup yet
window.open('https://kvan7.github.io/exalted-poe2-trade/download');
}
function quitAndInstall () {
function quitAndInstall() {
Host.sendEvent({
name: 'CLIENT->MAIN::user-action',
payload: { action: 'update-and-restart' }
})
payload: { action: 'update-and-restart' },
});
}
function fmtTime (millis: number) {
return DateTime.fromMillis(millis).toRelative({ style: 'long' }) ?? 'n/a'
function fmtTime(millis: number) {
return DateTime.fromMillis(millis).toRelative({ style: 'long' }) ?? 'n/a';
}
export default defineComponent({
name: 'settings.about',
inheritAttrs: false,
setup () {
const { t } = useI18n()
setup() {
const { t } = useI18n();
const info = computed(() => {
const rawInfo = Host.updateInfo.value
const rawInfo = Host.updateInfo.value;
switch (rawInfo.state) {
case 'initial':
return {
str1: t('updates.maybe_outdated'),
str2: t('updates.never_checked'),
action: checkForUpdates,
actionText: t('updates.check_now')
}
actionText: t('updates.check_now'),
};
case 'checking-for-update':
return { str1: t('updates.checking'), str2: t('please_wait') }
return { str1: t('updates.checking'), str2: t('please_wait') };
case 'update-not-available':
return {
str1: t('updates.latest'),
str2: t('updates.last_checked', [fmtTime(rawInfo.checkedAt)]),
action: checkForUpdates,
actionText: t('updates.check_now')
}
actionText: t('updates.check_now'),
};
case 'error':
return {
str1: t('updates.maybe_outdated'),
str2: t('updates.error'),
action: openDownloadPage,
actionText: t('updates.downloads_page')
}
actionText: t('updates.downloads_page'),
};
case 'update-downloaded':
return {
str1: t('updates.available', [rawInfo.version]),
str2: t('updates.installed_on_exit'),
action: quitAndInstall,
actionText: t('updates.install_now')
}
actionText: t('updates.install_now'),
};
case 'update-available':
return rawInfo.noDownloadReason
? {
@@ -105,20 +133,20 @@ export default defineComponent({
? t('updates.download_manually')
: t('updates.download_disabled'),
action: openDownloadPage,
actionText: t('updates.downloads_page')
actionText: t('updates.downloads_page'),
}
: {
str1: t('updates.available', [rawInfo.version]),
str2: t('updates.downloading')
str2: t('updates.downloading'),
};
}
}
})
});
return {
t,
info,
version: Host.version
}
}
})
version: Host.version,
};
},
});
</script>

View File

@@ -33,7 +33,7 @@
<div class="mb-4">
<div class="flex-1 mb-1">{{ t(':poe_cfg_file') }}</div>
<input v-model.trim="gameConfig"
class="rounded bg-gray-900 px-1 block w-full font-sans" placeholder="...?/My Games/Path of Exile 2/poe2_production_Config.ini">
class="rounded bg-gray-900 px-1 block w-full font-sans" placeholder="...?/My Games/Path of Exile 2/production_Config.ini">
</div>
<hr class="mb-4 mx-8 border-gray-700">
<div class="mb-2">

View File

@@ -1,22 +0,0 @@
#!/bin/bash
# Remove ./renderer/dist if it exists
rm -rf ./renderer/dist
# Remove ./main/dist if it exists
rm -rf ./main/dist
cd ./renderer
npm install
npm run make-index-files
npm run build
cd ..
cd ./main
npm install
npm run build
npm run package