mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2025-11-12 12:37:49 +00:00
Compare commits
12 Commits
fix/dumpTa
...
v0.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cf0cfa347 | ||
|
|
2f694ff0f7 | ||
|
|
3eef0397fa | ||
|
|
e8c08a18a7 | ||
|
|
5f61646cdf | ||
|
|
0f5bb3eaf1 | ||
|
|
a44e14398d | ||
|
|
592d99f645 | ||
|
|
bc4579b9f0 | ||
|
|
789e10eac4 | ||
|
|
066364e962 | ||
|
|
17955b452e |
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
@@ -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
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
needs: renderer
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-2019, ubuntu-20.04, macos-12]
|
||||
os: [windows-2019] # ubuntu-20.04, macos-14 is a missing runner
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -59,4 +59,4 @@ jobs:
|
||||
run: cat ./main/dist/latest-linux.yml
|
||||
- name: Hash
|
||||
if: ${{ startsWith(matrix.os, 'macos') }}
|
||||
run: cat ./main/dist/latest-mac.yml
|
||||
run: cat ./main/dist/latest-mac.yml
|
||||
@@ -11,7 +11,7 @@ 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/SnosMe/awakened-poe-trade/blob/master/.github/workflows/main.yml)
|
||||
[.github/workflows/main.yml](https://github.com/Kvan7/awakened-poe2-trade2/blob/master/.github/workflows/main.yml)
|
||||
|
||||
Here's what that looks like as of 2023-12-03.
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#  Awakened PoE Trade
|
||||
#  Awakened PoE2 Trade2
|
||||
|
||||
[](https://somsubhra.github.io/github-release-stats/?username=SnosMe&repository=awakened-poe-trade)
|
||||
[](https://patreon.com/awakened_poe_trade)
|
||||
[](https://github.com/SnosMe/awakened-poe-trade/issues/22)
|
||||
|
||||
|
||||
|
||||
➡ [Download for Windows & Linux](https://snosme.github.io/awakened-poe-trade/download) ⬅
|
||||
|
||||
## Tool showcase
|
||||
|
||||
| Gem | Rare | Unique | Currency |
|
||||
|-----|------|--------|----------|
|
||||
| Gem | Rare | Unique | Currency |
|
||||
| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ |
|
||||
|  |  |  |  |
|
||||
|
||||
### Development
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "renderer",
|
||||
"path": "renderer"
|
||||
},
|
||||
{
|
||||
"name": "main",
|
||||
"path": "main"
|
||||
},
|
||||
{
|
||||
"name": "docs",
|
||||
"path": "docs"
|
||||
},
|
||||
{
|
||||
"name": "root",
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.exclude": {
|
||||
"main/": true,
|
||||
"renderer/": true,
|
||||
"docs/": true,
|
||||
"dist/": true
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"name": "renderer",
|
||||
"path": "renderer"
|
||||
},
|
||||
{
|
||||
"name": "main",
|
||||
"path": "main"
|
||||
},
|
||||
{
|
||||
"name": "docs",
|
||||
"path": "docs"
|
||||
},
|
||||
{
|
||||
"name": "root",
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.exclude": {
|
||||
"main/": true,
|
||||
"renderer/": true,
|
||||
"docs/": true,
|
||||
"dist/": true
|
||||
},
|
||||
"editor.tabSize": 2,
|
||||
"conventionalCommits.scopes": [
|
||||
"Update to 2"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
const BASE = '/awakened-poe-trade/'
|
||||
const BASE = '/awakened-poe2-trade2/'
|
||||
|
||||
export default defineConfig({
|
||||
title: 'Awakened PoE Trade',
|
||||
description: 'App for price-checking items in Path of Exile',
|
||||
title: 'Awakened PoE2 Trade2',
|
||||
description: 'App for price-checking items in Path of Exile 2',
|
||||
base: BASE,
|
||||
mpa: true,
|
||||
head: [
|
||||
@@ -22,14 +22,9 @@ export default defineConfig({
|
||||
// logo: 'TODO', https://github.com/vuejs/vitepress/issues/1401
|
||||
appVersion: '3.25.101',
|
||||
github: {
|
||||
releasesUrl: 'https://github.com/SnosMe/awakened-poe-trade/releases'
|
||||
releasesUrl: 'https://github.com/Kvan7/awakened-poe2-trade2/releases'
|
||||
},
|
||||
socialLinks: [
|
||||
{
|
||||
text: 'Discord',
|
||||
color: '#7289DA',
|
||||
link: 'https://github.com/SnosMe/awakened-poe-trade/issues/22'
|
||||
},
|
||||
{
|
||||
text: 'Patreon',
|
||||
color: '#FF424D',
|
||||
@@ -38,7 +33,7 @@ export default defineConfig({
|
||||
{
|
||||
text: 'GitHub',
|
||||
color: '#181717',
|
||||
link: 'https://github.com/SnosMe/awakened-poe-trade'
|
||||
link: 'https://github.com/Kvan7/awakened-poe2-trade2'
|
||||
}
|
||||
],
|
||||
sidebar: [
|
||||
|
||||
@@ -11,12 +11,12 @@ const { theme } = useData()
|
||||
You can download Awakened 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}/Awakened-PoE-Trade-Setup-${theme.appVersion}.exe`">Windows 10+ (installer)</a> | ✔ | Fast |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE-Trade-${theme.appVersion}.exe`">Windows 10+ (portable)</a> | ❌ | Slower |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE-Trade-${theme.appVersion}.AppImage`">Linux (AppImage)</a> | ✔ | n/a |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE-Trade-${theme.appVersion}-universal.dmg`">macOS (dmg)</a> | ❌ | n/a |
|
||||
| Download link | Automatic updates | Startup time |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ------------ |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE2-Trade2-Setup-${theme.appVersion}.exe`">Windows 10+ (installer)</a> | ✔ | Fast |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE2-Trade2-${theme.appVersion}.exe`">Windows 10+ (portable)</a> | ❌ | Slower |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE2-Trade2-${theme.appVersion}.AppImage`">Linux (AppImage)</a> | ✔ | n/a |
|
||||
| <a :href="`${theme.github.releasesUrl}/download/v${theme.appVersion}/Awakened-PoE2-Trade2-${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 Awakened PoE Trade to have access to the PoE window, it must be started with Administrator rights.**
|
||||
In order for Awakened PoE2 Trade2 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.**
|
||||
|
||||
@@ -4,7 +4,7 @@ title: FAQ
|
||||
|
||||
- **Where can I change settings, league?**
|
||||
|
||||
Open Path of Exile and press overlay key `Shift + Space`. Click on the button with cog icon there.
|
||||
Open Path of Exile 2 and press overlay key `Shift + Space`. Click on the button with cog icon there.
|
||||

|
||||
|
||||
- **Where can I find the logs?**
|
||||
|
||||
@@ -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%\awakened-poe-trade`
|
||||
4. Delete `%appdata%\awakened-poe2-trade2`
|
||||
|
||||
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 Awakened PoE Trade.
|
||||
6. Restart Awakened PoE2 Trade2.
|
||||
|
||||
*(don't forget to quit first, otherwise launching second instance will do nothing).*
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ title: Quick Start
|
||||
|
||||
#### First of all, how does it work? {:style="margin-top: 0;"}
|
||||
|
||||
When you press `Ctrl + C` Path of Exile copies the item's text (under cursor, if any) to the clipboard.
|
||||
All that remains is to parse text in Awakened PoE Trade and show to you in a fancy way.
|
||||
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 Awakened PoE2 Trade2 and show to you in a fancy way.
|
||||
|
||||
### Usage
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
publish:
|
||||
- "github"
|
||||
productName: "Awakened PoE Trade"
|
||||
productName: "Awakened PoE2 Trade2"
|
||||
npmRebuild: false
|
||||
files:
|
||||
- "package.json"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "awakened-poe-trade",
|
||||
"version": "3.25.102",
|
||||
"name": "awakened-poe2-trade2",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "node build/script.mjs",
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SnosMe/awakened-poe-trade.git"
|
||||
"url": "https://github.com/Kvan7/awakened-poe2-trade2.git"
|
||||
},
|
||||
"main": "dist/main.js",
|
||||
"dependencies": {
|
||||
@@ -36,4 +36,4 @@
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,70 @@
|
||||
import path from 'path'
|
||||
import { app, Tray, Menu, shell, nativeImage, dialog } from 'electron'
|
||||
import type { ServerEvents } from './server'
|
||||
import path from "path";
|
||||
import { app, Tray, Menu, shell, nativeImage, dialog } from "electron";
|
||||
import type { ServerEvents } from "./server";
|
||||
|
||||
export class AppTray {
|
||||
public overlayKey = 'Shift + Space'
|
||||
private tray: Tray
|
||||
serverPort = 0
|
||||
public overlayKey = "Shift + Space";
|
||||
private tray: Tray;
|
||||
serverPort = 0;
|
||||
|
||||
constructor (server: ServerEvents) {
|
||||
constructor(server: ServerEvents) {
|
||||
let trayImage = nativeImage.createFromPath(
|
||||
path.join(
|
||||
__dirname,
|
||||
process.env.STATIC!,
|
||||
process.platform === "win32" ? "icon.ico" : "icon.png"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
if (process.platform === "darwin") {
|
||||
// Mac image size needs to be smaller, or else it looks huge. Size
|
||||
// guideline is from https://iconhandbook.co.uk/reference/chart/osx/
|
||||
trayImage = trayImage.resize({ width: 22, height: 22 })
|
||||
trayImage = trayImage.resize({ width: 22, height: 22 });
|
||||
}
|
||||
|
||||
this.tray = new Tray(trayImage)
|
||||
this.tray.setToolTip(`Awakened PoE Trade v${app.getVersion()}`)
|
||||
this.rebuildMenu()
|
||||
this.tray = new Tray(trayImage);
|
||||
this.tray.setToolTip(`Awakened PoE2 Trade2 v${app.getVersion()}`);
|
||||
this.rebuildMenu();
|
||||
|
||||
server.onEventAnyClient('CLIENT->MAIN::user-action', ({ action }) => {
|
||||
if (action === 'quit') {
|
||||
app.quit()
|
||||
server.onEventAnyClient("CLIENT->MAIN::user-action", ({ action }) => {
|
||||
if (action === "quit") {
|
||||
app.quit();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
rebuildMenu () {
|
||||
rebuildMenu() {
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'Settings/League',
|
||||
label: "Settings/League",
|
||||
click: () => {
|
||||
dialog.showMessageBox({
|
||||
title: 'Settings',
|
||||
message: `Open Path of Exile and press "${this.overlayKey}". Click on the button with cog icon there.`
|
||||
})
|
||||
}
|
||||
title: "Settings",
|
||||
message: `Open Path of Exile 2 and press "${this.overlayKey}". Click on the button with cog icon there.`,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Open in Browser',
|
||||
label: "Open in Browser",
|
||||
click: () => {
|
||||
shell.openExternal(`http://localhost:${this.serverPort}`)
|
||||
}
|
||||
shell.openExternal(`http://localhost:${this.serverPort}`);
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Open config folder',
|
||||
label: "Open config folder",
|
||||
click: () => {
|
||||
shell.openPath(path.join(app.getPath('userData'), 'apt-data'))
|
||||
}
|
||||
shell.openPath(path.join(app.getPath("userData"), "apt-data"));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
label: "Quit",
|
||||
click: () => {
|
||||
app.quit()
|
||||
}
|
||||
}
|
||||
])
|
||||
app.quit();
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
this.tray.setContextMenu(contextMenu)
|
||||
this.tray.setContextMenu(contextMenu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,100 +1,131 @@
|
||||
import fs from 'fs/promises'
|
||||
import path from 'path'
|
||||
import ini from 'ini'
|
||||
import { app } from 'electron'
|
||||
import { hotkeyToString, CodeToKey } from '../../../ipc/KeyToCode'
|
||||
import { guessFileLocation } from './utils'
|
||||
import type { Logger } from '../RemoteLogger'
|
||||
import type { ServerEvents } from '../server'
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
import ini from "ini";
|
||||
import { app } from "electron";
|
||||
import { hotkeyToString, CodeToKey } from "../../../ipc/KeyToCode";
|
||||
import { guessFileLocation } from "./utils";
|
||||
import type { Logger } from "../RemoteLogger";
|
||||
import type { ServerEvents } from "../server";
|
||||
|
||||
const POSSIBLE_PATH =
|
||||
(process.platform === 'win32') ? [
|
||||
path.join(app.getPath('documents'), 'My Games\\Path of Exile\\production_Config.ini')
|
||||
] : (process.platform === 'linux') ? [
|
||||
path.join(app.getPath('documents'), 'My Games/Path of Exile/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/production_Config.ini')
|
||||
] : (process.platform === 'darwin') ? [
|
||||
path.join(app.getPath('appData'), 'Path of Exile/Preferences/production_Config.ini')
|
||||
] : []
|
||||
process.platform === "win32"
|
||||
? [
|
||||
path.join(
|
||||
app.getPath("documents"),
|
||||
"My Games\\Path of Exile 2\\production_Config.ini"
|
||||
),
|
||||
]
|
||||
: process.platform === "linux"
|
||||
? [
|
||||
path.join(
|
||||
app.getPath("documents"),
|
||||
"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/production_Config.ini"
|
||||
),
|
||||
]
|
||||
: process.platform === "darwin"
|
||||
? [
|
||||
path.join(
|
||||
app.getPath("appData"),
|
||||
"Path of Exile 2/Preferences/production_Config.ini"
|
||||
),
|
||||
]
|
||||
: [];
|
||||
|
||||
export class GameConfig {
|
||||
private _wantedPath: string | null = null
|
||||
private _actualPath: string | null = null
|
||||
get actualPath () { return this._actualPath }
|
||||
private _wantedPath: string | null = null;
|
||||
private _actualPath: string | null = null;
|
||||
get actualPath() {
|
||||
return this._actualPath;
|
||||
}
|
||||
|
||||
private _showModsKey: string | null = null
|
||||
get showModsKeyNullable () { return this._showModsKey }
|
||||
get showModsKey () { return this._showModsKey ?? 'Alt' }
|
||||
private _showModsKey: string | null = null;
|
||||
get showModsKeyNullable() {
|
||||
return this._showModsKey;
|
||||
}
|
||||
get showModsKey() {
|
||||
return this._showModsKey ?? "Alt";
|
||||
}
|
||||
|
||||
constructor (
|
||||
private server: ServerEvents,
|
||||
private logger: Logger
|
||||
) {}
|
||||
constructor(private server: ServerEvents, private logger: Logger) {}
|
||||
|
||||
async readConfig (filePath: string) {
|
||||
async readConfig(filePath: string) {
|
||||
if (this._wantedPath !== filePath) {
|
||||
this._wantedPath = filePath
|
||||
this._actualPath = null
|
||||
this._wantedPath = filePath;
|
||||
this._actualPath = null;
|
||||
} else {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filePath.length) {
|
||||
const guessedPath = await guessFileLocation(POSSIBLE_PATH)
|
||||
const guessedPath = await guessFileLocation(POSSIBLE_PATH);
|
||||
if (guessedPath != null) {
|
||||
filePath = guessedPath
|
||||
filePath = guessedPath;
|
||||
} else {
|
||||
this.logger.write('error [GameConfig] Failed to find game configuration file in the default location.')
|
||||
return
|
||||
this.logger.write(
|
||||
"error [GameConfig] Failed to find game configuration file in the default location."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let contents = await fs.readFile(filePath, { encoding: 'utf-8', flag: 'r' })
|
||||
contents = contents.trimStart() // remove BOM
|
||||
const parsed = ini.parse(contents)
|
||||
let contents = await fs.readFile(filePath, {
|
||||
encoding: "utf-8",
|
||||
flag: "r",
|
||||
});
|
||||
contents = contents.trimStart(); // remove BOM
|
||||
const parsed = ini.parse(contents);
|
||||
|
||||
this._showModsKey = this.parseConfigHotkey(
|
||||
parsed['ACTION_KEYS']?.['show_advanced_item_descriptions'])
|
||||
parsed["ACTION_KEYS"]?.["show_advanced_item_descriptions"]
|
||||
);
|
||||
|
||||
this._actualPath = filePath
|
||||
this._actualPath = filePath;
|
||||
} catch {
|
||||
this.logger.write('error [GameConfig] Failed to read game configuration file.')
|
||||
this.logger.write(
|
||||
"error [GameConfig] Failed to read game configuration file."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private parseConfigHotkey (cfgKey?: string): string | null {
|
||||
if (!cfgKey) return null
|
||||
private parseConfigHotkey(cfgKey?: string): string | null {
|
||||
if (!cfgKey) return null;
|
||||
|
||||
const [keyMain, keyMod] = cfgKey.split(' ')
|
||||
const [keyMain, keyMod] = cfgKey.split(" ");
|
||||
|
||||
let key1: string
|
||||
let key1: string;
|
||||
if (CodeToKey[keyMain]) {
|
||||
key1 = CodeToKey[keyMain]
|
||||
key1 = CodeToKey[keyMain];
|
||||
} else {
|
||||
this.logger.write(`error [GameConfig] Failed to read key: ${cfgKey}.`)
|
||||
return null
|
||||
this.logger.write(`error [GameConfig] Failed to read key: ${cfgKey}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
let key2: string | undefined
|
||||
let key2: string | undefined;
|
||||
if (keyMod) {
|
||||
if (keyMod === '1') {
|
||||
key2 = 'Shift'
|
||||
} else if (keyMod === '2') {
|
||||
key2 = 'Ctrl'
|
||||
} else if (keyMod === '3') {
|
||||
key2 = 'Alt'
|
||||
if (keyMod === "1") {
|
||||
key2 = "Shift";
|
||||
} else if (keyMod === "2") {
|
||||
key2 = "Ctrl";
|
||||
} else if (keyMod === "3") {
|
||||
key2 = "Alt";
|
||||
} else {
|
||||
this.logger.write(`error [GameConfig] Failed to read modifier key: ${cfgKey}.`)
|
||||
return null
|
||||
this.logger.write(
|
||||
`error [GameConfig] Failed to read modifier key: ${cfgKey}.`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return hotkeyToString(
|
||||
[key1],
|
||||
key2 === 'Ctrl',
|
||||
key2 === 'Shift',
|
||||
key2 === 'Alt'
|
||||
)
|
||||
key2 === "Ctrl",
|
||||
key2 === "Shift",
|
||||
key2 === "Alt"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +1,118 @@
|
||||
import { promises as fs, watchFile, unwatchFile } from 'fs'
|
||||
import path from 'path'
|
||||
import { app } from 'electron'
|
||||
import { guessFileLocation } from './utils'
|
||||
import { ServerEvents } from '../server'
|
||||
import { Logger } from '../RemoteLogger'
|
||||
import { promises as fs, watchFile, unwatchFile } from "fs";
|
||||
import path from "path";
|
||||
import { app } from "electron";
|
||||
import { guessFileLocation } from "./utils";
|
||||
import { ServerEvents } from "../server";
|
||||
import { Logger } from "../RemoteLogger";
|
||||
|
||||
const POSSIBLE_PATH =
|
||||
(process.platform === 'win32') ? [
|
||||
'C:\\Program Files (x86)\\Grinding Gear Games\\Path of Exile\\logs\\Client.txt',
|
||||
'C:\\Program Files (x86)\\Steam\\steamapps\\common\\Path of Exile\\logs\\Client.txt'
|
||||
] : (process.platform === 'linux') ? [
|
||||
path.join(app.getPath('home'), '.wine/drive_c/Program Files (x86)/Grinding Gear Games/Path of Exile/logs/Client.txt'),
|
||||
path.join(app.getPath('home'), '.local/share/Steam/steamapps/common/Path of Exile/logs/Client.txt')
|
||||
] : (process.platform === 'darwin') ? [
|
||||
path.join(app.getPath('home'), 'Library/Caches/com.GGG.PathOfExile/Logs/Client.txt')
|
||||
] : []
|
||||
process.platform === "win32"
|
||||
? [
|
||||
"C:\\Program Files (x86)\\Grinding Gear Games\\Path of Exile 2\\logs\\Client.txt",
|
||||
"C:\\Program Files (x86)\\Steam\\steamapps\\common\\Path of Exile 2\\logs\\Client.txt",
|
||||
]
|
||||
: process.platform === "linux"
|
||||
? [
|
||||
path.join(
|
||||
app.getPath("home"),
|
||||
".wine/drive_c/Program Files (x86)/Grinding Gear Games/Path of Exile 2/logs/Client.txt"
|
||||
),
|
||||
path.join(
|
||||
app.getPath("home"),
|
||||
".local/share/Steam/steamapps/common/Path of Exile 2/logs/Client.txt"
|
||||
),
|
||||
]
|
||||
: process.platform === "darwin"
|
||||
? [
|
||||
path.join(
|
||||
app.getPath("home"),
|
||||
"Library/Caches/com.GGG.PathOfExile/Logs/Client.txt"
|
||||
),
|
||||
]
|
||||
: [];
|
||||
|
||||
export class GameLogWatcher {
|
||||
private _wantedPath: string | null = null
|
||||
get actualPath () { return this._state?.path ?? null }
|
||||
private _wantedPath: string | null = null;
|
||||
get actualPath() {
|
||||
return this._state?.path ?? null;
|
||||
}
|
||||
private _state: {
|
||||
offset: number
|
||||
path: string
|
||||
file: fs.FileHandle
|
||||
isReading: boolean
|
||||
readBuff: Buffer
|
||||
} | null = null
|
||||
offset: number;
|
||||
path: string;
|
||||
file: fs.FileHandle;
|
||||
isReading: boolean;
|
||||
readBuff: Buffer;
|
||||
} | null = null;
|
||||
|
||||
constructor (
|
||||
private server: ServerEvents,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
constructor(private server: ServerEvents, private logger: Logger) {}
|
||||
|
||||
async restart (logFile: string) {
|
||||
async restart(logFile: string) {
|
||||
if (this._wantedPath !== logFile) {
|
||||
this._wantedPath = logFile
|
||||
this._wantedPath = logFile;
|
||||
if (this._state) {
|
||||
unwatchFile(this._state.path)
|
||||
await this._state.file.close()
|
||||
this._state = null
|
||||
unwatchFile(this._state.path);
|
||||
await this._state.file.close();
|
||||
this._state = null;
|
||||
}
|
||||
} else {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (!logFile.length) {
|
||||
const guessedPath = await guessFileLocation(POSSIBLE_PATH)
|
||||
const guessedPath = await guessFileLocation(POSSIBLE_PATH);
|
||||
if (guessedPath != null) {
|
||||
logFile = guessedPath
|
||||
logFile = guessedPath;
|
||||
} else {
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const file = await fs.open(logFile, 'r')
|
||||
const stats = await file.stat()
|
||||
watchFile(logFile, { interval: 450 }, this.handleFileChange.bind(this))
|
||||
const file = await fs.open(logFile, "r");
|
||||
const stats = await file.stat();
|
||||
watchFile(logFile, { interval: 450 }, this.handleFileChange.bind(this));
|
||||
this._state = {
|
||||
path: logFile,
|
||||
file: file,
|
||||
offset: stats.size,
|
||||
isReading: false,
|
||||
readBuff: Buffer.allocUnsafe(64 * 1024),
|
||||
}
|
||||
};
|
||||
} catch {
|
||||
this.logger.write('error [GameLogWatcher] Failed to watch file.')
|
||||
this.logger.write("error [GameLogWatcher] Failed to watch file.");
|
||||
}
|
||||
}
|
||||
|
||||
private handleFileChange () {
|
||||
private handleFileChange() {
|
||||
if (this._state && !this._state.isReading) {
|
||||
this._state.isReading = true
|
||||
this.readToEOF()
|
||||
this._state.isReading = true;
|
||||
this.readToEOF();
|
||||
}
|
||||
}
|
||||
|
||||
private async readToEOF () {
|
||||
if (!this._state) return
|
||||
private async readToEOF() {
|
||||
if (!this._state) return;
|
||||
|
||||
const { file, readBuff, offset } = this._state
|
||||
const { bytesRead } = await file.read(readBuff, 0, readBuff.length, offset)
|
||||
const { file, readBuff, offset } = this._state;
|
||||
const { bytesRead } = await file.read(readBuff, 0, readBuff.length, offset);
|
||||
|
||||
if (bytesRead) {
|
||||
const str = readBuff.toString('utf8', 0, bytesRead)
|
||||
const lines = str.split('\n').map(line => line.trim()).filter(line => line.length)
|
||||
this.server.sendEventTo('broadcast', {
|
||||
name: 'MAIN->CLIENT::game-log',
|
||||
payload: { lines }
|
||||
})
|
||||
const str = readBuff.toString("utf8", 0, bytesRead);
|
||||
const lines = str
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length);
|
||||
this.server.sendEventTo("broadcast", {
|
||||
name: "MAIN->CLIENT::game-log",
|
||||
payload: { lines },
|
||||
});
|
||||
}
|
||||
|
||||
if (bytesRead) {
|
||||
this._state.offset += bytesRead
|
||||
this.readToEOF()
|
||||
this._state.offset += bytesRead;
|
||||
this.readToEOF();
|
||||
} else {
|
||||
this._state.isReading = false
|
||||
this._state.isReading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,172 +1,188 @@
|
||||
import path from 'path'
|
||||
import { BrowserWindow, dialog, shell, Menu, WebContents } from 'electron'
|
||||
import { OverlayController, OVERLAY_WINDOW_OPTS } from 'electron-overlay-window'
|
||||
import type { ServerEvents } from '../server'
|
||||
import type { Logger } from '../RemoteLogger'
|
||||
import type { GameWindow } from './GameWindow'
|
||||
import path from "path";
|
||||
import { BrowserWindow, dialog, shell, Menu, WebContents } from "electron";
|
||||
import {
|
||||
OverlayController,
|
||||
OVERLAY_WINDOW_OPTS,
|
||||
} from "electron-overlay-window";
|
||||
import type { ServerEvents } from "../server";
|
||||
import type { Logger } from "../RemoteLogger";
|
||||
import type { GameWindow } from "./GameWindow";
|
||||
|
||||
export class OverlayWindow {
|
||||
public isInteractable = false
|
||||
public wasUsedRecently = true
|
||||
private window?: BrowserWindow
|
||||
private overlayKey: string = 'Shift + Space'
|
||||
private isOverlayKeyUsed = false
|
||||
public isInteractable = false;
|
||||
public wasUsedRecently = true;
|
||||
private window?: BrowserWindow;
|
||||
private overlayKey: string = "Shift + Space";
|
||||
private isOverlayKeyUsed = false;
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private server: ServerEvents,
|
||||
private logger: Logger,
|
||||
private poeWindow: GameWindow,
|
||||
private poeWindow: GameWindow
|
||||
) {
|
||||
this.server.onEventAnyClient('OVERLAY->MAIN::focus-game', this.assertGameActive)
|
||||
this.poeWindow.on('active-change', this.handlePoeWindowActiveChange)
|
||||
this.poeWindow.onAttach(this.handleOverlayAttached)
|
||||
this.server.onEventAnyClient(
|
||||
"OVERLAY->MAIN::focus-game",
|
||||
this.assertGameActive
|
||||
);
|
||||
this.poeWindow.on("active-change", this.handlePoeWindowActiveChange);
|
||||
this.poeWindow.onAttach(this.handleOverlayAttached);
|
||||
|
||||
this.server.onEventAnyClient('CLIENT->MAIN::used-recently', (e) => {
|
||||
this.wasUsedRecently = e.isOverlay
|
||||
})
|
||||
this.server.onEventAnyClient("CLIENT->MAIN::used-recently", (e) => {
|
||||
this.wasUsedRecently = e.isOverlay;
|
||||
});
|
||||
|
||||
if (process.argv.includes('--no-overlay')) return
|
||||
if (process.argv.includes("--no-overlay")) return;
|
||||
|
||||
this.window = new BrowserWindow({
|
||||
icon: path.join(__dirname, process.env.STATIC!, 'icon.png'),
|
||||
icon: path.join(__dirname, process.env.STATIC!, "icon.png"),
|
||||
...OVERLAY_WINDOW_OPTS,
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
allowRunningInsecureContent: false,
|
||||
webviewTag: true,
|
||||
spellcheck: false
|
||||
spellcheck: false,
|
||||
},
|
||||
});
|
||||
|
||||
this.window.setMenu(
|
||||
Menu.buildFromTemplate([
|
||||
{ role: "editMenu" },
|
||||
{ role: "reload" },
|
||||
{ role: "toggleDevTools" },
|
||||
])
|
||||
);
|
||||
|
||||
this.window.webContents.on("before-input-event", this.handleExtraCommands);
|
||||
this.window.webContents.on(
|
||||
"did-attach-webview",
|
||||
(_, webviewWebContents) => {
|
||||
webviewWebContents.on("before-input-event", this.handleExtraCommands);
|
||||
}
|
||||
})
|
||||
|
||||
this.window.setMenu(Menu.buildFromTemplate([
|
||||
{ role: 'editMenu' },
|
||||
{ role: 'reload' },
|
||||
{ role: 'toggleDevTools' }
|
||||
]))
|
||||
|
||||
this.window.webContents.on('before-input-event', this.handleExtraCommands)
|
||||
this.window.webContents.on('did-attach-webview', (_, webviewWebContents) => {
|
||||
webviewWebContents.on('before-input-event', this.handleExtraCommands)
|
||||
})
|
||||
);
|
||||
|
||||
this.window.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
shell.openExternal(details.url);
|
||||
return { action: "deny" };
|
||||
});
|
||||
}
|
||||
|
||||
loadAppPage (port: number) {
|
||||
const url = process.env.VITE_DEV_SERVER_URL ||
|
||||
`http://localhost:${port}/index.html`
|
||||
loadAppPage(port: number) {
|
||||
const url =
|
||||
process.env.VITE_DEV_SERVER_URL || `http://localhost:${port}/index.html`;
|
||||
|
||||
if (!this.window) {
|
||||
shell.openExternal(url)
|
||||
return
|
||||
shell.openExternal(url);
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
this.window.loadURL(url)
|
||||
this.window.webContents.openDevTools({ mode: 'detach', activate: false })
|
||||
this.window.loadURL(url);
|
||||
this.window.webContents.openDevTools({ mode: "detach", activate: false });
|
||||
} else {
|
||||
this.window.loadURL(url)
|
||||
this.window.loadURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
assertOverlayActive = () => {
|
||||
if (!this.isInteractable) {
|
||||
this.isInteractable = true
|
||||
OverlayController.activateOverlay()
|
||||
this.poeWindow.isActive = false
|
||||
this.isInteractable = true;
|
||||
OverlayController.activateOverlay();
|
||||
this.poeWindow.isActive = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
assertGameActive = () => {
|
||||
if (this.isInteractable) {
|
||||
this.isInteractable = false
|
||||
OverlayController.focusTarget()
|
||||
this.poeWindow.isActive = true
|
||||
this.isInteractable = false;
|
||||
OverlayController.focusTarget();
|
||||
this.poeWindow.isActive = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
toggleActiveState = () => {
|
||||
this.isOverlayKeyUsed = true
|
||||
this.isOverlayKeyUsed = true;
|
||||
if (this.isInteractable) {
|
||||
this.assertGameActive()
|
||||
this.assertGameActive();
|
||||
} else {
|
||||
this.assertOverlayActive()
|
||||
this.assertOverlayActive();
|
||||
}
|
||||
};
|
||||
|
||||
updateOpts(overlayKey: string, windowTitle: string) {
|
||||
this.overlayKey = overlayKey;
|
||||
this.poeWindow.attach(this.window, windowTitle);
|
||||
}
|
||||
|
||||
updateOpts (overlayKey: string, windowTitle: string) {
|
||||
this.overlayKey = overlayKey
|
||||
this.poeWindow.attach(this.window, windowTitle)
|
||||
}
|
||||
private handleExtraCommands = (
|
||||
event: Electron.Event,
|
||||
input: Electron.Input
|
||||
) => {
|
||||
if (input.type !== "keyDown") return;
|
||||
|
||||
private handleExtraCommands = (event: Electron.Event, input: Electron.Input) => {
|
||||
if (input.type !== 'keyDown') return
|
||||
let { code, control: ctrlKey, shift: shiftKey, alt: altKey } = input;
|
||||
|
||||
let { code, control: ctrlKey, shift: shiftKey, alt: altKey } = input
|
||||
|
||||
if (code.startsWith('Key')) {
|
||||
code = code.slice('Key'.length)
|
||||
} else if (code.startsWith('Digit')) {
|
||||
code = code.slice('Digit'.length)
|
||||
if (code.startsWith("Key")) {
|
||||
code = code.slice("Key".length);
|
||||
} else if (code.startsWith("Digit")) {
|
||||
code = code.slice("Digit".length);
|
||||
}
|
||||
|
||||
if (shiftKey && altKey) code = `Shift + Alt + ${code}`
|
||||
else if (ctrlKey && shiftKey) code = `Ctrl + Shift + ${code}`
|
||||
else if (ctrlKey && altKey) code = `Ctrl + Alt + ${code}`
|
||||
else if (altKey) code = `Alt + ${code}`
|
||||
else if (ctrlKey) code = `Ctrl + ${code}`
|
||||
else if (shiftKey) code = `Shift + ${code}`
|
||||
if (shiftKey && altKey) code = `Shift + Alt + ${code}`;
|
||||
else if (ctrlKey && shiftKey) code = `Ctrl + Shift + ${code}`;
|
||||
else if (ctrlKey && altKey) code = `Ctrl + Alt + ${code}`;
|
||||
else if (altKey) code = `Alt + ${code}`;
|
||||
else if (ctrlKey) code = `Ctrl + ${code}`;
|
||||
else if (shiftKey) code = `Shift + ${code}`;
|
||||
|
||||
switch (code) {
|
||||
case 'Escape':
|
||||
case 'Ctrl + W': {
|
||||
event.preventDefault()
|
||||
process.nextTick(this.assertGameActive)
|
||||
break
|
||||
case "Escape":
|
||||
case "Ctrl + W": {
|
||||
event.preventDefault();
|
||||
process.nextTick(this.assertGameActive);
|
||||
break;
|
||||
}
|
||||
case this.overlayKey: {
|
||||
event.preventDefault()
|
||||
process.nextTick(this.toggleActiveState)
|
||||
break
|
||||
event.preventDefault();
|
||||
process.nextTick(this.toggleActiveState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private handleOverlayAttached = (hasAccess?: boolean) => {
|
||||
if (hasAccess === false) {
|
||||
this.logger.write('error [Overlay] PoE is running with administrator rights')
|
||||
this.logger.write(
|
||||
"error [Overlay] PoE is running with administrator rights"
|
||||
);
|
||||
|
||||
dialog.showErrorBox(
|
||||
'PoE window - No access',
|
||||
"PoE window - No access",
|
||||
// ----------------------
|
||||
'Path of Exile is running with administrator rights.\n' +
|
||||
'\n' +
|
||||
'You need to restart Awakened PoE Trade with administrator rights.'
|
||||
)
|
||||
"Path of Exile 2 is running with administrator rights.\n" +
|
||||
"\n" +
|
||||
"You need to restart Awakened PoE2 Trade2 with administrator rights."
|
||||
);
|
||||
} else {
|
||||
this.server.sendEventTo('broadcast', {
|
||||
name: 'MAIN->OVERLAY::overlay-attached',
|
||||
payload: undefined
|
||||
})
|
||||
this.server.sendEventTo("broadcast", {
|
||||
name: "MAIN->OVERLAY::overlay-attached",
|
||||
payload: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private handlePoeWindowActiveChange = (isActive: boolean) => {
|
||||
if (isActive && this.isInteractable) {
|
||||
this.isInteractable = false
|
||||
this.isInteractable = false;
|
||||
}
|
||||
this.server.sendEventTo('broadcast', {
|
||||
name: 'MAIN->OVERLAY::focus-change',
|
||||
this.server.sendEventTo("broadcast", {
|
||||
name: "MAIN->OVERLAY::focus-change",
|
||||
payload: {
|
||||
game: isActive,
|
||||
overlay: this.isInteractable,
|
||||
usingHotkey: this.isOverlayKeyUsed
|
||||
}
|
||||
})
|
||||
this.isOverlayKeyUsed = false
|
||||
}
|
||||
usingHotkey: this.isOverlayKeyUsed,
|
||||
},
|
||||
});
|
||||
this.isOverlayKeyUsed = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,56 +1,60 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint'
|
||||
// 'only-warn'
|
||||
],
|
||||
extends: [
|
||||
'plugin:vue/base',
|
||||
'standard-with-typescript'
|
||||
],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'quote-props': ['error', 'consistent-as-needed'],
|
||||
'no-labels': ['error', { allowLoop: true }],
|
||||
'multiline-ternary': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-undef': 'off',
|
||||
'@typescript-eslint/no-unused-vars': ['error'],
|
||||
'@typescript-eslint/strict-boolean-expressions': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/restrict-template-expressions': 'off',
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'off',
|
||||
'@typescript-eslint/prefer-optional-chain': 'off',
|
||||
'@typescript-eslint/prefer-readonly': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'@typescript-eslint/no-misused-promises': 'off',
|
||||
'@typescript-eslint/prefer-reduce-type-parameter': 'off',
|
||||
'@typescript-eslint/no-invalid-void-type': 'off',
|
||||
'@typescript-eslint/consistent-indexed-object-style': 'off',
|
||||
'import/first': 'off',
|
||||
'import/no-duplicates': 'off',
|
||||
'func-call-spacing': 'off',
|
||||
// TODO: refactor IPC and enable
|
||||
'@typescript-eslint/consistent-type-assertions': 'off'
|
||||
},
|
||||
overrides: [{
|
||||
files: ['src/main/**/*'],
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
}
|
||||
}, {
|
||||
files: ['*.ts'],
|
||||
node: true
|
||||
},
|
||||
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',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'quote-props': ['error', 'consistent-as-needed'],
|
||||
'no-labels': ['error', { allowLoop: true }],
|
||||
'multiline-ternary': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-undef': 'off',
|
||||
'@typescript-eslint/no-unused-vars': ['error'],
|
||||
'@typescript-eslint/strict-boolean-expressions': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/restrict-template-expressions': 'off',
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'off',
|
||||
'@typescript-eslint/prefer-optional-chain': 'off',
|
||||
'@typescript-eslint/prefer-readonly': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'@typescript-eslint/no-misused-promises': 'off',
|
||||
'@typescript-eslint/prefer-reduce-type-parameter': 'off',
|
||||
'@typescript-eslint/no-invalid-void-type': 'off',
|
||||
'@typescript-eslint/consistent-indexed-object-style': 'off',
|
||||
'import/first': 'off',
|
||||
'import/no-duplicates': 'off',
|
||||
'func-call-spacing': 'off',
|
||||
// TODO: refactor IPC and enable
|
||||
'@typescript-eslint/consistent-type-assertions': 'off',
|
||||
"indent": ["error", "tab"]
|
||||
},
|
||||
overrides: [{
|
||||
files: ['src/main/**/*'],
|
||||
env: {
|
||||
node: true
|
||||
}
|
||||
}, {
|
||||
files: ['*.ts'],
|
||||
parserOptions: {
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}],
|
||||
parserOptions: {
|
||||
project: './tsconfig.json'
|
||||
parser: '@typescript-eslint/parser',
|
||||
extraFileExtensions: ['.vue']
|
||||
}
|
||||
}],
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
extraFileExtensions: ['.vue']
|
||||
}
|
||||
}
|
||||
|
||||
7
renderer/.prettierrc
Normal file
7
renderer/.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"endOfLine": "lf",
|
||||
"tabWidth": 2,
|
||||
"useTabs": true,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="color-scheme" content="dark">
|
||||
<link rel="icon" href="/icon.ico">
|
||||
<title>Awakened PoE Trade</title>
|
||||
<title>Awakened PoE Trade2</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
318
renderer/package-lock.json
generated
318
renderer/package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "awakened-poe-trade",
|
||||
"name": "awakened-poe2-trade2",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "awakened-poe-trade",
|
||||
"name": "awakened-poe2-trade2",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "6.x.x",
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "awakened-poe-trade",
|
||||
"version": "0.0.0",
|
||||
"name": "awakened-poe2-trade2",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -34,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"
|
||||
@@ -59,4 +62,4 @@
|
||||
"browserslist": [
|
||||
"chrome >= 101"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
"league": "League",
|
||||
"realm": "Realm",
|
||||
"realm_intl": "International",
|
||||
|
||||
"app": {
|
||||
"leagues_loading": "Loading leagues\u2026",
|
||||
"leagues_failed": "Failed to load leagues",
|
||||
@@ -21,12 +20,10 @@
|
||||
"report_bug": "Report a bug on GitHub",
|
||||
"quit": "Quit"
|
||||
},
|
||||
|
||||
"map.mods.heist": "heist",
|
||||
"map.mods.uber": "T17",
|
||||
"map.mods.outdated": "outdated",
|
||||
"Support development on": "Support development\u00A0on",
|
||||
|
||||
"Blighted": "Blighted",
|
||||
"Blight-ravaged": "Blight-ravaged",
|
||||
"Magic": "Magic",
|
||||
@@ -40,7 +37,6 @@
|
||||
"Anomalous": "Anomalous",
|
||||
"Divergent": "Divergent",
|
||||
"Phantasmal": "Phantasmal",
|
||||
|
||||
"item": {
|
||||
"prop_quality": "Q {0}%",
|
||||
"base_percentile": "Base Percentile: {0}%",
|
||||
@@ -153,7 +149,6 @@
|
||||
"hide_anointment": "Buyer will likely change anointment",
|
||||
"hide_for_crafting": "Select only if price-checking as base item for crafting",
|
||||
"hide_empty_mod": "Select only if item has 6 modifiers (1 of which is crafted) or if it has 5 modifiers",
|
||||
|
||||
"tag_implicit": "implicit",
|
||||
"tag_fractured": "fractured",
|
||||
"tag_crafted": "crafted",
|
||||
@@ -254,15 +249,15 @@
|
||||
"new_mods_icon": "Show icon for new mods"
|
||||
},
|
||||
"trade_result": {
|
||||
"error" :"Trade site request failed",
|
||||
"matched" :"Matched: {0}",
|
||||
"trade" :"Trade",
|
||||
"price" :"Price",
|
||||
"bulk" :"bulk",
|
||||
"stock" :"Stock",
|
||||
"fulfill" :"Fulfill",
|
||||
"listed" :"Listed",
|
||||
"seller" :"Seller",
|
||||
"error": "Trade site request failed",
|
||||
"matched": "Matched: {0}",
|
||||
"trade": "Trade",
|
||||
"price": "Price",
|
||||
"bulk": "bulk",
|
||||
"stock": "Stock",
|
||||
"fulfill": "Fulfill",
|
||||
"listed": "Listed",
|
||||
"seller": "Seller",
|
||||
"item_level": "iLvl",
|
||||
"gem_level": "Level",
|
||||
"quality": "Quality",
|
||||
@@ -274,7 +269,7 @@
|
||||
"stack": "Stack"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings - Awakened PoE Trade",
|
||||
"title": "Settings - Awakened PoE2 Trade2",
|
||||
"language": "Language",
|
||||
"private_league": "or Private League",
|
||||
"account_name": "Account name",
|
||||
@@ -283,9 +278,9 @@
|
||||
"chat_cmd_send": "press Enter",
|
||||
"no_key": "Not Set",
|
||||
"clear_hotkey": "You can clear hotkey by pressing Backspace",
|
||||
"overlay" :"Overlay",
|
||||
"stash_scroll" :"Stash tab scrolling",
|
||||
"delve_grid" :"Grid for Delve Chart",
|
||||
"overlay": "Overlay",
|
||||
"stash_scroll": "Stash tab scrolling",
|
||||
"delve_grid": "Grid for Delve Chart",
|
||||
"window_title": "PoE window title",
|
||||
"thank_you": "App development continues thanks to:",
|
||||
"hotkeys": "Hotkeys",
|
||||
@@ -293,20 +288,20 @@
|
||||
"general": "General",
|
||||
"debug": "Debug",
|
||||
"about": "About",
|
||||
"font_size" :"Font size",
|
||||
"overlay_bg" :"Background when the Overlay is clickable",
|
||||
"overlay_bg_none" :"Transparent",
|
||||
"overlay_bg_focus_game" :"Clicking on the background focuses the game",
|
||||
"poe_log_file" :"PoE log file",
|
||||
"poe_cfg_file" :"PoE config file",
|
||||
"restore_clipboard" :"Restore clipboard",
|
||||
"show_overlay_ready" :"Show a notification when the Overlay detects a PoE window",
|
||||
"font_size": "Font size",
|
||||
"overlay_bg": "Background when the Overlay is clickable",
|
||||
"overlay_bg_none": "Transparent",
|
||||
"overlay_bg_focus_game": "Clicking on the background focuses the game",
|
||||
"poe_log_file": "PoE log file",
|
||||
"poe_cfg_file": "PoE config file",
|
||||
"restore_clipboard": "Restore clipboard",
|
||||
"show_overlay_ready": "Show a notification when the Overlay detects a PoE window",
|
||||
"debug_hotkeys": "Record all key presses"
|
||||
},
|
||||
"price_check": {
|
||||
"name": "Price check",
|
||||
"hotkey" :"Auto-hide Mode",
|
||||
"hotkey_locked" :"Open without auto-hide",
|
||||
"hotkey": "Auto-hide Mode",
|
||||
"hotkey_locked": "Open without auto-hide",
|
||||
"enable_browser": "Enable builtin browser",
|
||||
"builtin_browser_warning": "I am aware that future releases can potentially contain malicious code that can steal my POESESSID.",
|
||||
"highlight_hint": "Your items will be highlighted even if this setting is off",
|
||||
@@ -322,4 +317,4 @@
|
||||
"show_prediction": "Show price prediction",
|
||||
"remember_currency": "Remember the Buyout Currency filter"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
"reopen_settings": "{0}을 눌러서 편집을 계속하세요.",
|
||||
"seconds": "초",
|
||||
"league": "리그",
|
||||
|
||||
"app": {
|
||||
"leagues_loading": "리그를 불러오는 중\u2026",
|
||||
"leagues_failed": "리그 불러오기를 실패하였습니다",
|
||||
@@ -19,11 +18,9 @@
|
||||
"report_bug": "버그 발생 시 GitHub에 보고해주세요",
|
||||
"quit": "종료"
|
||||
},
|
||||
|
||||
"map.mods.heist": "강탈",
|
||||
"map.mods.outdated": "사용X",
|
||||
"Support development on": "개발을 지원하세요",
|
||||
|
||||
"Blighted": "역병 걸린",
|
||||
"Blight-ravaged": "역병에 유린당한",
|
||||
"Magic": "매직",
|
||||
@@ -37,7 +34,6 @@
|
||||
"Anomalous": "기묘한",
|
||||
"Divergent": "상이한",
|
||||
"Phantasmal": "몽환적인",
|
||||
|
||||
"item": {
|
||||
"prop_quality": "{0}% 퀄리티",
|
||||
"base_percentile": "기본 백분위수: {0}%",
|
||||
@@ -150,7 +146,6 @@
|
||||
"hide_anointment": "Buyer will likely change anointment",
|
||||
"hide_for_crafting": "Select only if price-checking as base item for crafting",
|
||||
"hide_empty_mod": "Select only if item has 6 modifiers (1 of which is crafted) or if it has 5 modifiers",
|
||||
|
||||
"tag_implicit": "고정 속성",
|
||||
"tag_fractured": "분열된",
|
||||
"tag_crafted": "제작된",
|
||||
@@ -271,7 +266,7 @@
|
||||
"stack": "스택"
|
||||
},
|
||||
"settings": {
|
||||
"title": "세팅 - Awakened PoE Trade",
|
||||
"title": "세팅 - Awakened PoE2 Trade2",
|
||||
"language": "언어",
|
||||
"private_league": "개인리그",
|
||||
"account_name": "계정명",
|
||||
@@ -302,8 +297,8 @@
|
||||
},
|
||||
"price_check": {
|
||||
"name": "Price check",
|
||||
"hotkey" :"Auto-hide Mode",
|
||||
"hotkey_locked" :"Open without auto-hide",
|
||||
"hotkey": "Auto-hide Mode",
|
||||
"hotkey_locked": "Open without auto-hide",
|
||||
"enable_browser": "Enable builtin browser",
|
||||
"builtin_browser_warning": "I am aware that future releases can potentially contain malicious code that can steal my POESESSID.",
|
||||
"highlight_hint": "Your items will be highlighted even if this setting is off",
|
||||
|
||||
@@ -19,14 +19,12 @@
|
||||
"Select": "Выбрать",
|
||||
"Not recognized modifier": "Нераспознанное свойство",
|
||||
"Refresh": "Обновить",
|
||||
|
||||
"please_wait": "Пожалуйста, подождите\u2026",
|
||||
"choose_file": "Выберите файл",
|
||||
"app_is_ready": "Запущен и работает в фоновом режиме",
|
||||
"reopen_settings": "Нажмите {0} чтобы продолжить редактирование.",
|
||||
"seconds": "секунды",
|
||||
"league": "Лига",
|
||||
|
||||
"app": {
|
||||
"leagues_loading": "Загрузка лиг\u2026",
|
||||
"leagues_failed": "Не удалось загрузить лиги",
|
||||
@@ -40,11 +38,9 @@
|
||||
"report_bug": "Сообщить о баге на GitHub",
|
||||
"quit": "Выход"
|
||||
},
|
||||
|
||||
"map.mods.heist": "кража",
|
||||
"map.mods.outdated": "устарело",
|
||||
"Support development on": "Поддержите разработку\u00A0на",
|
||||
|
||||
"Blighted": "Заражённая",
|
||||
"Blight-ravaged": "Разорённая Скверной",
|
||||
"Shaper": "Создатель",
|
||||
@@ -57,7 +53,6 @@
|
||||
"Anomalous": "Аномальный",
|
||||
"Divergent": "Искривлённый",
|
||||
"Phantasmal": "Фантомный",
|
||||
|
||||
"item": {
|
||||
"prop_quality": "К-во: {0}%",
|
||||
"base_percentile": "Ролл значений базы: {0}%",
|
||||
@@ -168,7 +163,6 @@
|
||||
"hide_anointment": "Покупатель, скорее всего, поменяет зачарование",
|
||||
"hide_for_crafting": "Отмечайте, если проверяете цену в качестве базового предмета для крафта",
|
||||
"hide_empty_mod": "Выбирайте, только если у предмета 6 свойств (1 из которых ремесленное) или если у него 5 свойств",
|
||||
|
||||
"tag_crafted": "мастер",
|
||||
"tag_fractured": "расколотый",
|
||||
"tag_scourge": "преображен",
|
||||
@@ -268,15 +262,15 @@
|
||||
"new_mods_icon": "Иконка у новых модов"
|
||||
},
|
||||
"trade_result": {
|
||||
"error" :"Запрос к сайту не удался",
|
||||
"matched" :"Найдено: {0}",
|
||||
"trade" :"Трейд",
|
||||
"price" :"Цена",
|
||||
"bulk" :"опт",
|
||||
"stock" :"Запас",
|
||||
"fulfill" :"Сделки",
|
||||
"listed" :"Выставлен",
|
||||
"seller" :"Продавец",
|
||||
"error": "Запрос к сайту не удался",
|
||||
"matched": "Найдено: {0}",
|
||||
"trade": "Трейд",
|
||||
"price": "Цена",
|
||||
"bulk": "опт",
|
||||
"stock": "Запас",
|
||||
"fulfill": "Сделки",
|
||||
"listed": "Выставлен",
|
||||
"seller": "Продавец",
|
||||
"item_level": "Ур.",
|
||||
"gem_level": "Уровень",
|
||||
"quality": "К-во",
|
||||
@@ -288,7 +282,7 @@
|
||||
"stack": "Стак"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки - Awakened PoE Trade",
|
||||
"title": "Настройки - Awakened PoE2 Trade2",
|
||||
"language": "Язык",
|
||||
"private_league": "или Приватная лига",
|
||||
"account_name": "Имя учетной записи",
|
||||
@@ -297,9 +291,9 @@
|
||||
"chat_cmd_send": "нажимать Enter",
|
||||
"no_key": "Не назначено",
|
||||
"clear_hotkey": "Вы можете отключить сочетание, нажав клавишу Backspace",
|
||||
"overlay" :"Оверлей",
|
||||
"stash_scroll" :"Прокрутка вкладок тайника",
|
||||
"delve_grid" :"Сетка для \"Спуска\"",
|
||||
"overlay": "Оверлей",
|
||||
"stash_scroll": "Прокрутка вкладок тайника",
|
||||
"delve_grid": "Сетка для \"Спуска\"",
|
||||
"window_title": "Заголовок окна игры",
|
||||
"thank_you": "Разработка приложения продолжается благодаря:",
|
||||
"hotkeys": "Быстрые клавиши",
|
||||
@@ -307,20 +301,20 @@
|
||||
"general": "Общие",
|
||||
"debug": "Debug",
|
||||
"about": "О программе",
|
||||
"font_size" :"Размер шрифта",
|
||||
"overlay_bg" :"Фон, когда окно APT кликабельно",
|
||||
"overlay_bg_none" :"Прозрачный",
|
||||
"overlay_bg_focus_game" :"Нажатие по фону активирует окно игры",
|
||||
"poe_log_file" :"Файл логов PoE",
|
||||
"poe_cfg_file" :"Файл настроек PoE",
|
||||
"restore_clipboard" :"Восстанавливать буфер обмена",
|
||||
"show_overlay_ready" :"Показывать уведомление при открытии PoE",
|
||||
"font_size": "Размер шрифта",
|
||||
"overlay_bg": "Фон, когда окно APT кликабельно",
|
||||
"overlay_bg_none": "Прозрачный",
|
||||
"overlay_bg_focus_game": "Нажатие по фону активирует окно игры",
|
||||
"poe_log_file": "Файл логов PoE",
|
||||
"poe_cfg_file": "Файл настроек PoE",
|
||||
"restore_clipboard": "Восстанавливать буфер обмена",
|
||||
"show_overlay_ready": "Показывать уведомление при открытии PoE",
|
||||
"debug_hotkeys": "Запись всех нажатий клавиш"
|
||||
},
|
||||
"price_check": {
|
||||
"name": "Прайс-чек",
|
||||
"hotkey" :"Режим авто-скрытия",
|
||||
"hotkey_locked" :"Открыть без авто-скрытия",
|
||||
"hotkey": "Режим авто-скрытия",
|
||||
"hotkey_locked": "Открыть без авто-скрытия",
|
||||
"enable_browser": "Включить встроенный браузер",
|
||||
"builtin_browser_warning": "Я осознаю, что в будущие релизы могут потенциально содержать вредоносный код, который может украсть мой POESESSID.",
|
||||
"highlight_hint": "Ваши предметы будут подсвечены, даже если эта настройка выключена",
|
||||
@@ -336,4 +330,4 @@
|
||||
"show_prediction": "Показывать приблизительную цену",
|
||||
"remember_currency": "Запоминать фильтр \"Валюты выкупа\""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +1,97 @@
|
||||
export enum ItemCategory {
|
||||
Map = 'Map',
|
||||
CapturedBeast = 'Captured Beast',
|
||||
MetamorphSample = 'Metamorph Sample',
|
||||
Helmet = 'Helmet',
|
||||
BodyArmour = 'Body Armour',
|
||||
Gloves = 'Gloves',
|
||||
Boots = 'Boots',
|
||||
Shield = 'Shield',
|
||||
Amulet = 'Amulet',
|
||||
Belt = 'Belt',
|
||||
Ring = 'Ring',
|
||||
Flask = 'Flask',
|
||||
AbyssJewel = 'Abyss Jewel',
|
||||
Jewel = 'Jewel',
|
||||
Quiver = 'Quiver',
|
||||
Claw = 'Claw',
|
||||
Bow = 'Bow',
|
||||
Sceptre = 'Sceptre',
|
||||
Wand = 'Wand',
|
||||
FishingRod = 'Fishing Rod',
|
||||
Staff = 'Staff',
|
||||
Warstaff = 'Warstaff',
|
||||
Dagger = 'Dagger',
|
||||
RuneDagger = 'Rune Dagger',
|
||||
OneHandedAxe = 'One-Handed Axe',
|
||||
TwoHandedAxe = 'Two-Handed Axe',
|
||||
OneHandedMace = 'One-Handed Mace',
|
||||
TwoHandedMace = 'Two-Handed Mace',
|
||||
OneHandedSword = 'One-Handed Sword',
|
||||
TwoHandedSword = 'Two-Handed Sword',
|
||||
ClusterJewel = 'Cluster Jewel',
|
||||
HeistBlueprint = 'Heist Blueprint',
|
||||
HeistContract = 'Heist Contract',
|
||||
HeistTool = 'Heist Tool',
|
||||
HeistBrooch = 'Heist Brooch',
|
||||
HeistGear = 'Heist Gear',
|
||||
HeistCloak = 'Heist Cloak',
|
||||
Trinket = 'Trinket',
|
||||
Invitation = 'Invitation',
|
||||
Gem = 'Gem',
|
||||
Currency = 'Currency',
|
||||
DivinationCard = 'Divination Card',
|
||||
Voidstone = 'Voidstone',
|
||||
Sentinel = 'Sentinel',
|
||||
MemoryLine = 'Memory Line',
|
||||
SanctumRelic = 'Sanctum Relic',
|
||||
Tincture = 'Tincture',
|
||||
Charm = 'Charm',
|
||||
Map = 'Map',
|
||||
CapturedBeast = 'Captured Beast',
|
||||
MetamorphSample = 'Metamorph Sample',
|
||||
Helmet = 'Helmet',
|
||||
BodyArmour = 'Body Armour',
|
||||
Gloves = 'Gloves',
|
||||
Boots = 'Boots',
|
||||
Shield = 'Shield',
|
||||
Amulet = 'Amulet',
|
||||
Belt = 'Belt',
|
||||
Ring = 'Ring',
|
||||
Flask = 'Flask',
|
||||
AbyssJewel = 'Abyss Jewel',
|
||||
Jewel = 'Jewel',
|
||||
Quiver = 'Quiver',
|
||||
Claw = 'Claw',
|
||||
Bow = 'Bow',
|
||||
Sceptre = 'Sceptre',
|
||||
Wand = 'Wand',
|
||||
FishingRod = 'Fishing Rod',
|
||||
Staff = 'Staff',
|
||||
Warstaff = 'Warstaff',
|
||||
Dagger = 'Dagger',
|
||||
RuneDagger = 'Rune Dagger',
|
||||
OneHandedAxe = 'One-Handed Axe',
|
||||
TwoHandedAxe = 'Two-Handed Axe',
|
||||
OneHandedMace = 'One-Handed Mace',
|
||||
TwoHandedMace = 'Two-Handed Mace',
|
||||
OneHandedSword = 'One-Handed Sword',
|
||||
TwoHandedSword = 'Two-Handed Sword',
|
||||
ClusterJewel = 'Cluster Jewel',
|
||||
HeistBlueprint = 'Heist Blueprint',
|
||||
HeistContract = 'Heist Contract',
|
||||
HeistTool = 'Heist Tool',
|
||||
HeistBrooch = 'Heist Brooch',
|
||||
HeistGear = 'Heist Gear',
|
||||
HeistCloak = 'Heist Cloak',
|
||||
Trinket = 'Trinket',
|
||||
Invitation = 'Invitation',
|
||||
Gem = 'Gem',
|
||||
Currency = 'Currency',
|
||||
DivinationCard = 'Divination Card',
|
||||
Voidstone = 'Voidstone',
|
||||
Sentinel = 'Sentinel',
|
||||
MemoryLine = 'Memory Line',
|
||||
SanctumRelic = 'Sanctum Relic',
|
||||
Tincture = 'Tincture',
|
||||
Charm = 'Charm',
|
||||
Crossbow = 'Crossbow',
|
||||
}
|
||||
|
||||
export const WEAPON_ONE_HANDED_MELEE = new Set([
|
||||
ItemCategory.OneHandedAxe,
|
||||
ItemCategory.OneHandedMace,
|
||||
ItemCategory.OneHandedSword,
|
||||
ItemCategory.Claw,
|
||||
ItemCategory.Dagger,
|
||||
ItemCategory.RuneDagger,
|
||||
ItemCategory.Sceptre
|
||||
])
|
||||
ItemCategory.OneHandedAxe,
|
||||
ItemCategory.OneHandedMace,
|
||||
ItemCategory.OneHandedSword,
|
||||
ItemCategory.Claw,
|
||||
ItemCategory.Dagger,
|
||||
ItemCategory.RuneDagger,
|
||||
ItemCategory.Sceptre,
|
||||
]);
|
||||
|
||||
export const WEAPON_ONE_HANDED = new Set([
|
||||
ItemCategory.Wand,
|
||||
...WEAPON_ONE_HANDED_MELEE
|
||||
])
|
||||
ItemCategory.Wand,
|
||||
...WEAPON_ONE_HANDED_MELEE,
|
||||
]);
|
||||
|
||||
export const WEAPONE_TWO_HANDED_MELEE = new Set([
|
||||
ItemCategory.TwoHandedAxe,
|
||||
ItemCategory.TwoHandedMace,
|
||||
ItemCategory.TwoHandedSword,
|
||||
ItemCategory.Staff,
|
||||
ItemCategory.Warstaff
|
||||
])
|
||||
ItemCategory.TwoHandedAxe,
|
||||
ItemCategory.TwoHandedMace,
|
||||
ItemCategory.TwoHandedSword,
|
||||
ItemCategory.Staff,
|
||||
ItemCategory.Warstaff,
|
||||
]);
|
||||
|
||||
export const WEAPON = new Set([
|
||||
ItemCategory.FishingRod,
|
||||
ItemCategory.Bow,
|
||||
...WEAPON_ONE_HANDED,
|
||||
...WEAPONE_TWO_HANDED_MELEE
|
||||
])
|
||||
ItemCategory.FishingRod,
|
||||
ItemCategory.Bow,
|
||||
...WEAPON_ONE_HANDED,
|
||||
...WEAPONE_TWO_HANDED_MELEE,
|
||||
]);
|
||||
|
||||
export const ARMOUR = new Set([
|
||||
ItemCategory.BodyArmour,
|
||||
ItemCategory.Boots,
|
||||
ItemCategory.Gloves,
|
||||
ItemCategory.Helmet,
|
||||
ItemCategory.Shield
|
||||
])
|
||||
ItemCategory.BodyArmour,
|
||||
ItemCategory.Boots,
|
||||
ItemCategory.Gloves,
|
||||
ItemCategory.Helmet,
|
||||
ItemCategory.Shield,
|
||||
]);
|
||||
|
||||
export const ACCESSORY = new Set([
|
||||
ItemCategory.Amulet,
|
||||
ItemCategory.Belt,
|
||||
ItemCategory.Ring,
|
||||
ItemCategory.Trinket
|
||||
// ItemCategory.Quiver
|
||||
])
|
||||
ItemCategory.Amulet,
|
||||
ItemCategory.Belt,
|
||||
ItemCategory.Ring,
|
||||
ItemCategory.Trinket,
|
||||
// ItemCategory.Quiver
|
||||
]);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +1,118 @@
|
||||
import { computed, shallowRef, readonly } from 'vue'
|
||||
import { createGlobalState } from '@vueuse/core'
|
||||
import { AppConfig, poeWebApi } from '@/web/Config'
|
||||
import { Host } from './IPC'
|
||||
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 }>;
|
||||
}
|
||||
|
||||
const DEFAULT_POE2_LEAGUES: ApiLeague[] = [
|
||||
{ id: 'Standard', rules: [] },
|
||||
{
|
||||
id: 'Hardcore',
|
||||
rules: [
|
||||
{
|
||||
id: 'Hardcore',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
interface League {
|
||||
id: string
|
||||
isPopular: boolean
|
||||
id: string;
|
||||
isPopular: boolean;
|
||||
}
|
||||
|
||||
export const useLeagues = createGlobalState(() => {
|
||||
const isLoading = shallowRef(false)
|
||||
const error = shallowRef<string | null>(null)
|
||||
const tradeLeagues = shallowRef<League[]>([])
|
||||
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
|
||||
},
|
||||
set (id) {
|
||||
AppConfig().leagueId = id
|
||||
}
|
||||
})
|
||||
const selectedId = computed<string | undefined>({
|
||||
get() {
|
||||
return tradeLeagues.value.length ? AppConfig().leagueId : undefined;
|
||||
},
|
||||
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)
|
||||
return {
|
||||
id: leagueId,
|
||||
realm: AppConfig().realm,
|
||||
isPopular: !isPrivateLeague(leagueId) && Boolean(listed?.isPopular)
|
||||
}
|
||||
})
|
||||
const selected = computed(() => {
|
||||
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),
|
||||
};
|
||||
});
|
||||
|
||||
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 leagues: ApiLeague[] = await response.json()
|
||||
tradeLeagues.value = leagues
|
||||
.filter(league =>
|
||||
!PERMANENT_HC.includes(league.id) &&
|
||||
!league.rules.some(rule => rule.id === 'NoParties' ||
|
||||
(rule.id === 'HardMode' && !league.event)))
|
||||
.map(league => {
|
||||
return { id: league.id, isPopular: true }
|
||||
})
|
||||
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 leagues: ApiLeague[] = await response.json();
|
||||
const leagues: ApiLeague[] = DEFAULT_POE2_LEAGUES;
|
||||
tradeLeagues.value = leagues
|
||||
.filter(
|
||||
(league) =>
|
||||
!PERMANENT_HC.includes(league.id) &&
|
||||
!league.rules.some(
|
||||
(rule) =>
|
||||
rule.id === 'NoParties' ||
|
||||
(rule.id === 'HardMode' && !league.event)
|
||||
)
|
||||
)
|
||||
.map((league) => {
|
||||
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
|
||||
} else {
|
||||
const STANDARD = 0
|
||||
selectedId.value = tradeLeagues.value[STANDARD].id
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = (e as Error).message
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
const STANDARD = 0;
|
||||
selectedId.value = tradeLeagues.value[STANDARD].id;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = (e as Error).message;
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
error,
|
||||
selectedId,
|
||||
selected,
|
||||
list: readonly(tradeLeagues),
|
||||
load
|
||||
}
|
||||
})
|
||||
return {
|
||||
isLoading,
|
||||
error,
|
||||
selectedId,
|
||||
selected,
|
||||
list: readonly(tradeLeagues),
|
||||
load,
|
||||
};
|
||||
});
|
||||
|
||||
function isPrivateLeague (id: string) {
|
||||
if (id.includes('Ruthless')) {
|
||||
return true
|
||||
}
|
||||
return /\(PL\d+\)$/.test(id)
|
||||
function isPrivateLeague(id: string) {
|
||||
if (id.includes('Ruthless')) {
|
||||
return true;
|
||||
}
|
||||
return /\(PL\d+\)$/.test(id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="bg-orange-400 text-gray-900 text-center text-sm font-bold text-shadow-lg">
|
||||
This is in BETA for POE2, things do not work as expected. Please report any issues.
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
|
||||
})
|
||||
</script>
|
||||
@@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<Widget :config="{ ...config, anchor }" move-handles="none" :removable="false" :inline-edit="false">
|
||||
<template v-if="item">
|
||||
<MapCheck v-if="isMapLike"
|
||||
:item="item" :config="config.maps" />
|
||||
<ItemInfo v-else
|
||||
:item="item" />
|
||||
<ConversionWarningBanner />
|
||||
<MapCheck v-if="isMapLike" :item="item" :config="config.maps" />
|
||||
<ItemInfo v-else :item="item" />
|
||||
</template>
|
||||
</Widget>
|
||||
</template>
|
||||
@@ -20,6 +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";
|
||||
|
||||
const props = defineProps<{
|
||||
config: ItemCheckWidget
|
||||
|
||||
@@ -1,42 +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 () {
|
||||
Host.onEvent('MAIN->CLIENT::item-text', (e) => {
|
||||
if (!['open-wiki', 'open-craft-of-exile', 'open-poedb', 'search-similar'].includes(e.target)) return
|
||||
const parsed = parseClipboard(e.clipboard)
|
||||
if (!parsed.isOk()) return
|
||||
export function registerActions() {
|
||||
Host.onEvent('MAIN->CLIENT::item-text', (e) => {
|
||||
if (
|
||||
![
|
||||
'open-wiki',
|
||||
'open-craft-of-exile',
|
||||
'open-poedb',
|
||||
'search-similar',
|
||||
].includes(e.target)
|
||||
)
|
||||
return;
|
||||
const parsed = parseClipboard(e.clipboard);
|
||||
if (!parsed.isOk()) return;
|
||||
|
||||
if (e.target === 'open-wiki') {
|
||||
openWiki(parsed.value)
|
||||
} else if (e.target === 'open-craft-of-exile') {
|
||||
openCoE(parsed.value)
|
||||
} else if (e.target === 'open-poedb') {
|
||||
openPoedb(parsed.value)
|
||||
} else if (e.target === 'search-similar') {
|
||||
findSimilarItems(parsed.value)
|
||||
}
|
||||
})
|
||||
if (e.target === 'open-wiki') {
|
||||
openWiki(parsed.value);
|
||||
} else if (e.target === 'open-craft-of-exile') {
|
||||
openCoE(parsed.value);
|
||||
} else if (e.target === 'open-poedb') {
|
||||
openPoedb(parsed.value);
|
||||
} else if (e.target === 'search-similar') {
|
||||
findSimilarItems(parsed.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function openWiki (item: ParsedItem) {
|
||||
window.open(`https://www.poewiki.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) {
|
||||
window.open(`https://poedb.tw/${POEDB_LANGS[AppConfig().language]}/search?q=${item.info.refName}`)
|
||||
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)
|
||||
window.open(`https://craftofexile.com/?eimport=${encodedClipboard}`)
|
||||
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)
|
||||
Host.sendEvent({
|
||||
name: 'CLIENT->MAIN::user-action',
|
||||
payload: { action: 'stash-search', text }
|
||||
})
|
||||
export function findSimilarItems(item: ParsedItem) {
|
||||
const text = JSON.stringify(item.info.name);
|
||||
Host.sendEvent({
|
||||
name: 'CLIENT->MAIN::user-action',
|
||||
payload: { action: 'stash-search', text },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
<div class="flex-1 text-center">{{ mapName }}</div>
|
||||
<div class="ml-8 text-gray-400">{{ t('map_check.profile') }}</div>
|
||||
<div class="flex gap-0.5">
|
||||
<button
|
||||
v-for="profile in profiles" :key="profile.text"
|
||||
@click="profile.select"
|
||||
:class="{ 'border border-gray-600': profile.active }"
|
||||
class="w-6 bg-gray-800"
|
||||
>{{ profile.text }}</button>
|
||||
<button v-for="profile in profiles" :key="profile.text" @click="profile.select"
|
||||
:class="{ 'border border-gray-600': profile.active }" class="w-6 bg-gray-800">{{ profile.text }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<FullscreenImage v-if="image" :src="image" style="height: auto;" />
|
||||
@@ -18,10 +14,8 @@
|
||||
{{ t('map_check.no_mods') }}
|
||||
</div>
|
||||
<div v-else class="py-2 flex flex-col">
|
||||
<MapStatButton v-for="stat in mapStats" :key="stat.matcher"
|
||||
:stat="stat" :config="config" />
|
||||
<div v-for="stat of item.unknownModifiers" :key="stat.type + '/' + stat.text"
|
||||
class="py-1 px-8">
|
||||
<MapStatButton v-for="stat in mapStats" :key="stat.matcher" :stat="stat" :config="config" />
|
||||
<div v-for="stat of item.unknownModifiers" :key="stat.type + '/' + stat.text" class="py-1 px-8">
|
||||
<span class="text-orange-400">{{ t('Not recognized modifier') }} —</span> {{ stat.text }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<template>
|
||||
<transition
|
||||
enter-active-class="animate__animated animate__fadeIn"
|
||||
<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">Awakened PoE Trade</div>
|
||||
<div class="text-base">Awakened PoE2 Trade2</div>
|
||||
<p>{{ t('app_is_ready') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<widget :config="config" :hideable="false" :removable="false" move-handles="corners" v-slot="{ isEditing }">
|
||||
<div class="widget-default-style">
|
||||
<ConversionWarningBanner />
|
||||
<div class="p-1 flex gap-1 items-center text-base">
|
||||
<template v-for="widget in widgets" :key="widget.wmId">
|
||||
<button @click="toggle(widget)"
|
||||
:class="widget.wmWants === 'show' ? 'border-gray-500' : 'border-gray-800'"
|
||||
class="bg-gray-800 rounded text-gray-100 p-2 leading-none whitespace-nowrap border"
|
||||
>
|
||||
<button @click="toggle(widget)" :class="widget.wmWants === 'show' ? 'border-gray-500' : 'border-gray-800'"
|
||||
class="bg-gray-800 rounded text-gray-100 p-2 leading-none whitespace-nowrap border">
|
||||
<i v-if="widget.wmType === 'settings'" class="fas fa-cog align-bottom" />
|
||||
<i v-else-if="widget.wmType === 'item-search'" class="fas fa-search align-bottom" />
|
||||
<template v-else>{{ widget.wmTitle || `#${widget.wmId}` }}</template>
|
||||
@@ -22,9 +21,12 @@
|
||||
<!-- <button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap">Screen saver</button> -->
|
||||
<!-- add widget -->
|
||||
<div class="text-gray-600 text-sm px-1 select-none whitespace-nowrap">{{ t(':add') }}</div>
|
||||
<button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap" @click="createOfType('timer')">{{ t('stopwatch.name') }}</button>
|
||||
<button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap" @click="createOfType('stash-search')">{{ t('stash_search.name') }}</button>
|
||||
<button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap" @click="createOfType('image-strip')">{{ t('image_strip.name') }}</button>
|
||||
<button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap"
|
||||
@click="createOfType('timer')">{{ t('stopwatch.name') }}</button>
|
||||
<button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap"
|
||||
@click="createOfType('stash-search')">{{ t('stash_search.name') }}</button>
|
||||
<button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap"
|
||||
@click="createOfType('image-strip')">{{ t('image_strip.name') }}</button>
|
||||
<!-- <button class="text-left hover:bg-gray-400 rounded px-1 whitespace-nowrap" @click="createOfType('TODO')">Image</button> -->
|
||||
</div>
|
||||
</template>
|
||||
@@ -34,8 +36,7 @@
|
||||
<ui-toggle v-model="config.alwaysShow">{{ t(':always_show') }}</ui-toggle>
|
||||
</div>
|
||||
<div v-else class="px-1 pb-1">
|
||||
<textarea class="px-2 py-1.5 bg-gray-700 rounded resize-none block"
|
||||
rows="1" spellcheck="false"
|
||||
<textarea class="px-2 py-1.5 bg-gray-700 rounded resize-none block" rows="1" spellcheck="false"
|
||||
:placeholder="t(':price_check')" @input="handleItemPaste"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,16 +51,17 @@ import { Widget as IWidget, WidgetManager, WidgetMenu } from './interfaces'
|
||||
import { Host } from '@/web/background/IPC'
|
||||
import Widget from './Widget.vue'
|
||||
import { useI18nNs } from '@/web/i18n'
|
||||
import ConversionWarningBanner from '../conversion-warn-banner/ConversionWarningBanner.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: { Widget, UiToggle, UiPopover },
|
||||
components: { Widget, UiToggle, UiPopover, ConversionWarningBanner },
|
||||
props: {
|
||||
config: {
|
||||
type: Object as PropType<WidgetMenu>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const wm = inject<WidgetManager>('wm')!
|
||||
|
||||
const widgets = computed(() => {
|
||||
@@ -77,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({
|
||||
|
||||
@@ -1,42 +1,24 @@
|
||||
<template>
|
||||
<div v-if="show" class="p-4 layout-column min-h-0">
|
||||
<filter-name
|
||||
:filters="itemFilters"
|
||||
:item="item" />
|
||||
<price-prediction v-if="showPredictedPrice" class="mb-4"
|
||||
:item="item" />
|
||||
<price-trend v-else
|
||||
:item="item"
|
||||
:filters="itemFilters" />
|
||||
<filters-block
|
||||
ref="filtersComponent"
|
||||
:filters="itemFilters"
|
||||
:stats="itemStats"
|
||||
:item="item"
|
||||
:presets="presets"
|
||||
@preset="selectPreset"
|
||||
@submit="doSearch = true" />
|
||||
<trade-listing
|
||||
v-if="tradeAPI === 'trade' && doSearch"
|
||||
ref="tradeService"
|
||||
:filters="itemFilters"
|
||||
:stats="itemStats"
|
||||
:item="item" />
|
||||
<trade-bulk
|
||||
v-if="tradeAPI === 'bulk' && doSearch"
|
||||
ref="tradeService"
|
||||
:filters="itemFilters"
|
||||
<filter-name :filters="itemFilters" :item="item" />
|
||||
<price-prediction v-if="showPredictedPrice" class="mb-4" :item="item" />
|
||||
<price-trend v-else :item="item" :filters="itemFilters" />
|
||||
<filters-block ref="filtersComponent" :filters="itemFilters" :stats="itemStats" :item="item" :presets="presets"
|
||||
@preset="selectPreset" @submit="doSearch = true" />
|
||||
<trade-listing v-if="tradeAPI === 'trade' && doSearch" ref="tradeService" :filters="itemFilters" :stats="itemStats"
|
||||
:item="item" />
|
||||
<trade-bulk v-if="tradeAPI === 'bulk' && doSearch" ref="tradeService" :filters="itemFilters" :item="item" />
|
||||
<div v-if="!doSearch" class="flex justify-between items-center">
|
||||
<div class="flex w-40" @mouseenter="handleSearchMouseenter">
|
||||
<button class="btn" @click="doSearch = true" style="min-width: 5rem;">{{ t('Search') }}</button>
|
||||
</div>
|
||||
<trade-links v-if="tradeAPI === 'trade'"
|
||||
:get-link="makeTradeLink" />
|
||||
<trade-links v-if="tradeAPI === 'trade'" :get-link="makeTradeLink" />
|
||||
</div>
|
||||
<stack-value :filters="itemFilters" :item="item"/>
|
||||
<stack-value :filters="itemFilters" :item="item" />
|
||||
<div v-if="showSupportLinks" class="mt-auto border border-dashed p-2">
|
||||
<div class="mb-1">{{ t('Support development on') }} <a href="https://patreon.com/awakened_poe_trade" class="inline-flex align-middle animate__animated animate__fadeInRight" target="_blank"><img class="inline h-5" src="/images/Patreon.svg"></a></div>
|
||||
<div class="mb-1">{{ t('Support development on') }} <a href="https://patreon.com/awakened_poe_trade"
|
||||
class="inline-flex align-middle animate__animated animate__fadeInRight" target="_blank"><img
|
||||
class="inline h-5" src="/images/Patreon.svg"></a></div>
|
||||
<i18n-t keypath="app.thanks_3rd_party" tag="div">
|
||||
<a href="https://poeprices.info" target="_blank" class="bg-gray-900 px-1 rounded">poeprices.info</a>
|
||||
<a href="https://poe.ninja/support" target="_blank" class="bg-gray-900 px-1 rounded">poe.ninja</a>
|
||||
@@ -89,7 +71,7 @@ export default defineComponent({
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const widget = computed(() => AppConfig<PriceCheckWidget>('price-check')!)
|
||||
const leagues = useLeagues()
|
||||
|
||||
@@ -120,7 +102,7 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
if ((!props.advancedCheck && !widget.value.smartInitialSearch) ||
|
||||
(props.advancedCheck && !widget.value.lockedInitialSearch)) {
|
||||
(props.advancedCheck && !widget.value.lockedInitialSearch)) {
|
||||
doSearch.value = false
|
||||
} else {
|
||||
doSearch.value = Boolean(
|
||||
@@ -174,8 +156,8 @@ export default defineComponent({
|
||||
|
||||
const showPredictedPrice = computed(() => {
|
||||
if (!widget.value.requestPricePrediction ||
|
||||
AppConfig().language !== 'en' ||
|
||||
!leagues.selected.value!.isPopular) return false
|
||||
AppConfig().language !== 'en' ||
|
||||
!leagues.selected.value!.isPopular) return false
|
||||
|
||||
if (presets.value.active === 'filters.preset_base_item') return false
|
||||
|
||||
@@ -195,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
|
||||
|
||||
@@ -234,11 +216,11 @@ 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 () {
|
||||
return `https://${getTradeEndpoint()}/trade/search/${itemFilters.value.trade.league}?q=${JSON.stringify(createTradeRequest(itemFilters.value, itemStats.value, props.item))}`
|
||||
makeTradeLink() {
|
||||
return `https://${getTradeEndpoint()}/trade2/search/poe2/${itemFilters.value.trade.league}?q=${JSON.stringify(createTradeRequest(itemFilters.value, itemStats.value, props.item))}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
<template>
|
||||
<div
|
||||
style="top: 0; left: 0; height: 100%; width: 100%; position: absolute;"
|
||||
<div style="top: 0; left: 0; height: 100%; width: 100%; position: absolute;"
|
||||
class="flex grow h-full pointer-events-none" :class="{
|
||||
'flex-row': clickPosition === 'stash',
|
||||
'flex-row-reverse': clickPosition === 'inventory',
|
||||
}">
|
||||
<div v-if="!isBrowserShown" class="layout-column shrink-0"
|
||||
style="width: var(--game-panel);">
|
||||
'flex-row': clickPosition === 'stash',
|
||||
'flex-row-reverse': clickPosition === 'inventory',
|
||||
}">
|
||||
<div v-if="!isBrowserShown" class="layout-column shrink-0" style="width: var(--game-panel);">
|
||||
</div>
|
||||
<div id="price-window" class="layout-column shrink-0 text-gray-200 pointer-events-auto" style="width: 28.75rem;">
|
||||
<ConversionWarningBanner />
|
||||
<AppTitleBar @close="closePriceCheck" @click="openLeagueSelection" :title="title">
|
||||
<ui-popover v-if="stableOrbCost" trigger="click" boundary="#price-window">
|
||||
<template #target>
|
||||
<button><i class="fas fa-exchange-alt" /> {{ stableOrbCost }}</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<item-quick-price class="text-base"
|
||||
:price="{ min: stableOrbCost, max: stableOrbCost, currency: 'chaos' }"
|
||||
item-img="/images/divine.png"
|
||||
/>
|
||||
<item-quick-price class="text-base" :price="{ min: stableOrbCost, max: stableOrbCost, currency: 'chaos' }"
|
||||
item-img="/images/divine.png" />
|
||||
<div v-for="i in 9" :key="i">
|
||||
<div class="pl-1">{{ i / 10 }} div ⇒ {{ Math.round(stableOrbCost * i / 10) }} c</div>
|
||||
</div>
|
||||
@@ -29,8 +26,7 @@
|
||||
</AppTitleBar>
|
||||
<div class="grow layout-column min-h-0 bg-gray-800">
|
||||
<background-info />
|
||||
<check-position-circle v-if="showCheckPos"
|
||||
:position="checkPosition" style="z-index: -1;" />
|
||||
<check-position-circle v-if="showCheckPos" :position="checkPosition" style="z-index: -1;" />
|
||||
<template v-if="item?.isErr()">
|
||||
<ui-error-box class="m-4">
|
||||
<template #name>{{ t(item.error.name) }}</template>
|
||||
@@ -40,8 +36,7 @@
|
||||
</template>
|
||||
<template v-else-if="item?.isOk()">
|
||||
<unidentified-resolver :item="item.value" @identify="handleIdentification($event)" />
|
||||
<checked-item v-if="isLeagueSelected"
|
||||
:item="item.value" :advanced-check="advancedCheck" />
|
||||
<checked-item v-if="isLeagueSelected" :item="item.value" :advanced-check="advancedCheck" />
|
||||
</template>
|
||||
<div v-if="isBrowserShown" class="bg-gray-900 px-6 py-2 truncate">
|
||||
<i18n-t keypath="app.toggle_browser_hint" tag="div">
|
||||
@@ -50,16 +45,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<webview v-if="isBrowserShown" ref="iframeEl"
|
||||
class="pointer-events-auto flex-1"
|
||||
width="100%" height="100%" />
|
||||
<webview v-if="isBrowserShown" ref="iframeEl" class="pointer-events-auto flex-1" width="100%" height="100%" />
|
||||
<div v-else class="layout-column flex-1 min-w-0">
|
||||
<div class="flex" :class="{
|
||||
'flex-row': clickPosition === 'stash',
|
||||
'flex-row-reverse': clickPosition === 'inventory'
|
||||
}">
|
||||
<related-items v-if="item?.isOk()" class="pointer-events-auto"
|
||||
:item="item.value" :click-position="clickPosition" />
|
||||
<related-items v-if="item?.isOk()" class="pointer-events-auto" :item="item.value"
|
||||
:click-position="clickPosition" />
|
||||
<rate-limiter-state class="pointer-events-auto" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -86,6 +79,7 @@ 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; message: string; rawText: ParsedItem['rawText'] }
|
||||
|
||||
@@ -100,7 +94,8 @@ export default defineComponent({
|
||||
CheckPositionCircle,
|
||||
ItemQuickPrice,
|
||||
UiErrorBox,
|
||||
UiPopover
|
||||
UiPopover,
|
||||
ConversionWarningBanner
|
||||
},
|
||||
props: {
|
||||
config: {
|
||||
@@ -108,7 +103,7 @@ export default defineComponent({
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const wm = inject<WidgetManager>('wm')!
|
||||
const { xchgRate, initialLoading: xchgRateLoading, queuePricesFetch } = usePoeninja()
|
||||
|
||||
@@ -168,7 +163,7 @@ export default defineComponent({
|
||||
}
|
||||
})
|
||||
|
||||
function handleIdentification (identified: ParsedItem) {
|
||||
function handleIdentification(identified: ParsedItem) {
|
||||
item.value = ok(identified)
|
||||
}
|
||||
|
||||
@@ -183,7 +178,7 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
const leagues = useLeagues()
|
||||
const title = computed(() => leagues.selectedId.value || 'Awakened PoE Trade')
|
||||
const title = computed(() => leagues.selectedId.value || 'Awakened PoE2 Trade2')
|
||||
const stableOrbCost = computed(() => (xchgRate.value) ? Math.round(xchgRate.value) : null)
|
||||
const isBrowserShown = computed(() => props.config.wmFlags.includes('has-browser'))
|
||||
const overlayKey = computed(() => AppConfig().overlayKey)
|
||||
@@ -196,7 +191,7 @@ export default defineComponent({
|
||||
return checkPosition.value.x > (window.screenX + window.innerWidth / 2)
|
||||
? 'inventory'
|
||||
: 'stash'
|
||||
// or {chat, vendor, center of screen}
|
||||
// or {chat, vendor, center of screen}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -210,7 +205,7 @@ export default defineComponent({
|
||||
}
|
||||
})
|
||||
|
||||
function closePriceCheck () {
|
||||
function closePriceCheck() {
|
||||
if (isBrowserShown.value || !Host.isElectron) {
|
||||
wm.hide(props.config.wmId)
|
||||
} else {
|
||||
@@ -218,7 +213,7 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
function openLeagueSelection () {
|
||||
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)
|
||||
@@ -226,14 +221,14 @@ export default defineComponent({
|
||||
|
||||
const iframeEl = shallowRef<HTMLIFrameElement | null>(null)
|
||||
|
||||
function showBrowser (url: string) {
|
||||
function showBrowser(url: string) {
|
||||
wm.setFlag(props.config.wmId, 'has-browser', true)
|
||||
nextTick(() => {
|
||||
iframeEl.value!.src = url
|
||||
})
|
||||
}
|
||||
|
||||
function closeBrowser () {
|
||||
function closeBrowser() {
|
||||
wm.setFlag(props.config.wmId, 'has-browser', false)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,133 +1,144 @@
|
||||
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]>
|
||||
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]>;
|
||||
}
|
||||
|
||||
export interface RareItemPrice {
|
||||
max: number
|
||||
min: number
|
||||
confidence: number
|
||||
currency: 'chaos' | 'div'
|
||||
explanation: Array<{
|
||||
name: string
|
||||
contrib: number
|
||||
}>
|
||||
max: number;
|
||||
min: number;
|
||||
confidence: number;
|
||||
currency: 'chaos' | 'div';
|
||||
explanation: Array<{
|
||||
name: string;
|
||||
contrib: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
export async function requestPoeprices (item: ParsedItem): Promise<RareItemPrice> {
|
||||
const query = querystring({
|
||||
i: utf8ToBase64(transformItemText(item.rawText)),
|
||||
l: useLeagues().selectedId.value,
|
||||
s: 'awakened-poe-trade'
|
||||
})
|
||||
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
|
||||
});
|
||||
|
||||
let data = cache.get<PoepricesApiResponse>(query)
|
||||
if (!data) {
|
||||
const response = await Host.proxy(`www.poeprices.info/api?${query}`)
|
||||
try {
|
||||
data = await response.json() as PoepricesApiResponse
|
||||
} catch (e) {
|
||||
throw new Error(`${response.status}, poeprices.info API is under load or down.`)
|
||||
}
|
||||
let data = cache.get<PoepricesApiResponse>(query);
|
||||
if (!data) {
|
||||
const response = await Host.proxy(`www.poeprices.info/api?${query}`);
|
||||
try {
|
||||
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)
|
||||
}
|
||||
if (data.error !== 0) {
|
||||
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 xchgExalted = findPriceByQuery({ ns: 'ITEM', name: 'Exalted Orb', variant: undefined })
|
||||
if (!xchgExalted) {
|
||||
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'
|
||||
} else if (data.currency !== 'divine' && data.currency !== 'chaos') {
|
||||
throw new Error('poeprices.info gave the price in unknown currency.')
|
||||
}
|
||||
if (data.currency === 'exalt') {
|
||||
const { findPriceByQuery, autoCurrency } = usePoeninja();
|
||||
const xchgExalted = findPriceByQuery({
|
||||
ns: 'ITEM',
|
||||
name: 'Exalted Orb',
|
||||
variant: undefined,
|
||||
});
|
||||
if (!xchgExalted) {
|
||||
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';
|
||||
} else if (data.currency !== 'divine' && data.currency !== 'chaos') {
|
||||
throw new Error('poeprices.info gave the price in unknown currency.');
|
||||
}
|
||||
|
||||
return {
|
||||
currency: (data.currency === 'divine') ? 'div' : 'chaos',
|
||||
min: data.min,
|
||||
max: data.max,
|
||||
confidence: Math.round(data.pred_confidence_score),
|
||||
explanation: data.pred_explanation.map(expl => ({
|
||||
name: expl[0],
|
||||
contrib: Math.round(expl[1] * 100)
|
||||
}))
|
||||
}
|
||||
return {
|
||||
currency: data.currency === 'divine' ? 'div' : 'chaos',
|
||||
min: data.min,
|
||||
max: data.max,
|
||||
confidence: Math.round(data.pred_confidence_score),
|
||||
explanation: data.pred_explanation.map((expl) => ({
|
||||
name: expl[0],
|
||||
contrib: Math.round(expl[1] * 100),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
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}`
|
||||
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}`;
|
||||
}
|
||||
|
||||
export async function sendFeedback (
|
||||
feedback: { text: string, option: 'fair' | 'low' | 'high' },
|
||||
prediction: Pick<PoepricesApiResponse, 'min' | 'max' | 'currency'>,
|
||||
item: ParsedItem
|
||||
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!)
|
||||
// body.append('debug', String(1))
|
||||
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
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const text = await response.text()
|
||||
// console.assert(text === `"${feedback.option}"`)
|
||||
const response = await Host.proxy('www.poeprices.info/send_feedback', {
|
||||
method: 'POST',
|
||||
body,
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
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>) {
|
||||
return Object.entries(q)
|
||||
.map(pair => pair.map(encodeURIComponent).join('='))
|
||||
.join('&')
|
||||
function querystring(q: Record<string, any>) {
|
||||
return Object.entries(q)
|
||||
.map((pair) => pair.map(encodeURIComponent).join('='))
|
||||
.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO blocked by poeprices.info not supporting advanced text
|
||||
*/
|
||||
function transformItemText (rawText: string) {
|
||||
// this may not account for all cases
|
||||
return rawText
|
||||
.replace(/(?<=\d)(\([^)]+\))/gm, '')
|
||||
.replace(/^\{.+\}$\n/gm, '')
|
||||
function transformItemText(rawText: string) {
|
||||
// this may not account for all cases
|
||||
return rawText
|
||||
.replace(/(?<=\d)(\([^)]+\))/gm, '')
|
||||
.replace(/^\{.+\}$\n/gm, '');
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
<span class="mr-1">{{ t(':matched') }}</span>
|
||||
<span v-if="!result" class="text-gray-600">...</span>
|
||||
<div v-else class="flex items-center">
|
||||
<button class="btn flex items-center mr-1" :style="{ background: selectedCurr !== 'xchgChaos' ? 'transparent' : undefined }"
|
||||
<button class="btn flex items-center mr-1"
|
||||
:style="{ background: selectedCurr !== 'xchgChaos' ? 'transparent' : undefined }"
|
||||
@click="selectedCurr = 'xchgChaos'">
|
||||
<img src="/images/chaos.png" class="trade-bulk-currency-icon">
|
||||
<span>{{ result.xchgChaos.listed.value?.total ?? '?' }}</span>
|
||||
</button>
|
||||
<button class="btn flex items-center mr-1" :style="{ background: selectedCurr !== 'xchgStable' ? 'transparent' : undefined }"
|
||||
<button class="btn flex items-center mr-1"
|
||||
:style="{ background: selectedCurr !== 'xchgStable' ? 'transparent' : undefined }"
|
||||
@click="selectedCurr = 'xchgStable'">
|
||||
<img src="/images/divine.png" class="trade-bulk-currency-icon">
|
||||
<span>{{ result.xchgStable.listed.value?.total ?? '?' }}</span>
|
||||
@@ -19,8 +21,7 @@
|
||||
<span class="ml-1"><online-filter :filters="filters" /></span>
|
||||
</div>
|
||||
</div>
|
||||
<trade-links v-if="result"
|
||||
:get-link="makeTradeLink" />
|
||||
<trade-links v-if="result" :get-link="makeTradeLink" />
|
||||
</div>
|
||||
<div class="layout-column overflow-y-auto overflow-x-hidden">
|
||||
<table class="table-stripped w-full">
|
||||
@@ -30,7 +31,10 @@
|
||||
<div class="px-2">{{ t(':price') }}</div>
|
||||
</th>
|
||||
<th class="trade-table-heading">
|
||||
<div class="pl-1 pr-2 flex text-xs" style="line-height: 1.3125rem;"><span class="w-8 inline-block text-right -ml-px mr-px">{{ (selectedCurr === 'xchgChaos') ? 'chaos' : 'div' }}</span><span>{{ '\u2009' }}/{{ '\u2009' }}</span><span class="w-8 inline-block">{{ t(':bulk') }}</span></div>
|
||||
<div class="pl-1 pr-2 flex text-xs" style="line-height: 1.3125rem;"><span
|
||||
class="w-8 inline-block text-right -ml-px mr-px">{{ (selectedCurr === 'xchgChaos') ? 'chaos' : 'div'
|
||||
}}</span><span>{{ '\u2009' }}/{{ '\u2009' }}</span><span class="w-8 inline-block">{{ t(':bulk')
|
||||
}}</span></div>
|
||||
</th>
|
||||
<th class="trade-table-heading">
|
||||
<div class="px-1">{{ t(':stock') }}</div>
|
||||
@@ -55,19 +59,25 @@
|
||||
</tr>
|
||||
<tr v-else :key="result.id">
|
||||
<td class="px-2">{{ Number((result.exchangeAmount / result.itemAmount).toFixed(4)) }}</td>
|
||||
<td class="pl-1 whitespace-nowrap"><span class="w-8 inline-block text-right">{{ result.exchangeAmount }}</span><span>{{ '\u2009' }}/{{ '\u2009' }}</span><span class="w-8 inline-block">{{ result.itemAmount }}</span></td>
|
||||
<td class="pl-1 whitespace-nowrap"><span class="w-8 inline-block text-right">{{ result.exchangeAmount
|
||||
}}</span><span>{{ '\u2009' }}/{{ '\u2009' }}</span><span class="w-8 inline-block">{{ result.itemAmount
|
||||
}}</span></td>
|
||||
<td class="px-1 text-right">{{ result.stock }}</td>
|
||||
<td class="px-1 text-right"><i v-if="result.stock < result.itemAmount" class="fas fa-exclamation-triangle mr-1 text-gray-500"></i>{{ Math.floor(result.stock / result.itemAmount) }}</td>
|
||||
<td class="px-1 text-right"><i v-if="result.stock < result.itemAmount"
|
||||
class="fas fa-exclamation-triangle mr-1 text-gray-500"></i>{{ Math.floor(result.stock /
|
||||
result.itemAmount) }}</td>
|
||||
<td class="pr-2 pl-4 whitespace-nowrap">
|
||||
<div class="inline-flex items-center">
|
||||
<div class="account-status" :class="result.accountStatus"></div>
|
||||
<div class="ml-1 font-sans text-xs">{{ result.relativeDate }}</div>
|
||||
</div>
|
||||
<span v-if="!showSeller && result.isMine" class="rounded px-1 text-gray-800 bg-gray-400 ml-1">{{ t('You') }}</span>
|
||||
<span v-if="!showSeller && result.isMine" class="rounded px-1 text-gray-800 bg-gray-400 ml-1">{{
|
||||
t('You') }}</span>
|
||||
</td>
|
||||
<td v-if="showSeller" class="px-2 whitespace-nowrap">
|
||||
<span v-if="result.isMine" class="rounded px-1 text-gray-800 bg-gray-400">{{ t('You') }}</span>
|
||||
<span v-else class="font-sans text-xs">{{ showSeller === 'ign' ? result.ign : result.accountName }}</span>
|
||||
<span v-else class="font-sans text-xs">{{ showSeller === 'ign' ? result.ign : result.accountName
|
||||
}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -101,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[]>
|
||||
@@ -111,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
|
||||
@@ -123,8 +133,8 @@ function useBulkApi () {
|
||||
const have = (item.info.refName === 'Chaos Orb')
|
||||
? ['divine']
|
||||
: (item.info.refName === 'Divine Orb')
|
||||
? ['chaos']
|
||||
: ['divine', 'chaos']
|
||||
? ['chaos']
|
||||
: ['divine', 'chaos']
|
||||
|
||||
const optimisticSearch = await execBulkSearch(
|
||||
item, filters, have, { accountName: AppConfig().accountName })
|
||||
@@ -139,7 +149,7 @@ function useBulkApi () {
|
||||
}
|
||||
}
|
||||
|
||||
function getResultsByHave (
|
||||
function getResultsByHave(
|
||||
item: ParsedItem,
|
||||
filters: ItemFilters,
|
||||
preloaded: Array<BulkSearch | null>,
|
||||
@@ -154,7 +164,7 @@ function useBulkApi () {
|
||||
|
||||
const listedLazy = computed(() => {
|
||||
if (!requested) {
|
||||
;(async function () {
|
||||
; (async function () {
|
||||
try {
|
||||
requested = true
|
||||
_result.value = shallowReactive((await execBulkSearch(
|
||||
@@ -193,7 +203,7 @@ export default defineComponent({
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const widget = computed(() => AppConfig<PriceCheckWidget>('price-check')!)
|
||||
const { error, result, search } = useBulkApi()
|
||||
|
||||
@@ -226,11 +236,11 @@ 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 }
|
||||
return `https://${getTradeEndpoint()}/trade/exchange/${props.filters.trade.league}?q=${JSON.stringify(httpGetQuery)}`
|
||||
return `https://${getTradeEndpoint()}/trade2/exchange/poe2/${props.filters.trade.league}?q=${JSON.stringify(httpGetQuery)}`
|
||||
}
|
||||
|
||||
const { t } = useI18nNs('trade_result')
|
||||
@@ -244,7 +254,7 @@ export default defineComponent({
|
||||
execSearch: () => { search(props.item, props.filters) },
|
||||
showSeller: computed(() => widget.value.showSeller),
|
||||
makeTradeLink,
|
||||
openTradeLink () {
|
||||
openTradeLink() {
|
||||
showBrowser(makeTradeLink(['mirror']))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
</div>
|
||||
<online-filter v-if="list" :by-time="true" :filters="filters" />
|
||||
<div class="flex-1"></div>
|
||||
<trade-links v-if="list"
|
||||
:get-link="makeTradeLink" />
|
||||
<trade-links v-if="list" :get-link="makeTradeLink" />
|
||||
</div>
|
||||
<div class="layout-column overflow-y-auto overflow-x-hidden">
|
||||
<table class="table-stripped w-full">
|
||||
@@ -46,21 +45,28 @@
|
||||
<td colspan="100" class="text-transparent">***</td>
|
||||
</tr>
|
||||
<tr v-else :key="result.id">
|
||||
<td class="px-2 whitespace-nowrap"><span :class="{ 'line-through': result.priceCurrency === 'exalted' }">{{ result.priceAmount }} {{ result.priceCurrency }}</span> <span v-if="result.listedTimes > 2" class="rounded px-1 text-gray-800 bg-gray-400 -mr-2"><span class="font-sans">×</span> {{ result.listedTimes }}</span><i v-else-if="!result.hasNote" class="fas fa-question" /></td>
|
||||
<td class="px-2 whitespace-nowrap"><span
|
||||
:class="{ 'line-through': result.priceCurrency === 'exalted' }">{{ result.priceAmount }} {{
|
||||
result.priceCurrency }}</span> <span v-if="result.listedTimes > 2"
|
||||
class="rounded px-1 text-gray-800 bg-gray-400 -mr-2"><span class="font-sans">×</span> {{
|
||||
result.listedTimes }}</span><i v-else-if="!result.hasNote" class="fas fa-question" /></td>
|
||||
<td v-if="item.stackSize" class="px-2 text-right">{{ result.stackSize }}</td>
|
||||
<td v-if="filters.itemLevel" class="px-2 whitespace-nowrap text-right">{{ result.itemLevel }}</td>
|
||||
<td v-if="item.category === 'Gem'" class="pl-2 whitespace-nowrap">{{ result.level }}</td>
|
||||
<td v-if="filters.quality || item.category === 'Gem'" class="px-2 whitespace-nowrap text-blue-400 text-right">{{ result.quality }}</td>
|
||||
<td v-if="filters.quality || item.category === 'Gem'"
|
||||
class="px-2 whitespace-nowrap text-blue-400 text-right">{{ result.quality }}</td>
|
||||
<td class="pr-2 pl-4 whitespace-nowrap">
|
||||
<div class="inline-flex items-center">
|
||||
<div class="account-status" :class="result.accountStatus"></div>
|
||||
<div class="ml-1 font-sans text-xs">{{ result.relativeDate }}</div>
|
||||
</div>
|
||||
<span v-if="!showSeller && result.isMine" class="rounded px-1 text-gray-800 bg-gray-400 ml-1">{{ t('You') }}</span>
|
||||
<span v-if="!showSeller && result.isMine" class="rounded px-1 text-gray-800 bg-gray-400 ml-1">{{
|
||||
t('You') }}</span>
|
||||
</td>
|
||||
<td v-if="showSeller" class="px-2 whitespace-nowrap">
|
||||
<span v-if="result.isMine" class="rounded px-1 text-gray-800 bg-gray-400">{{ t('You') }}</span>
|
||||
<span v-else class="font-sans text-xs">{{ showSeller === 'ign' ? result.ign : result.accountName }}</span>
|
||||
<span v-else class="font-sans text-xs">{{ showSeller === 'ign' ? result.ign : result.accountName
|
||||
}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -99,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)
|
||||
@@ -137,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
|
||||
@@ -168,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) =>
|
||||
@@ -209,7 +215,7 @@ export default defineComponent({
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const widget = computed(() => AppConfig<PriceCheckWidget>('price-check')!)
|
||||
|
||||
watch(() => props.item, (item) => {
|
||||
@@ -220,10 +226,10 @@ export default defineComponent({
|
||||
|
||||
const showBrowser = inject<(url: string) => void>('builtin-browser')!
|
||||
|
||||
function makeTradeLink () {
|
||||
function makeTradeLink() {
|
||||
return (searchResult.value)
|
||||
? `https://${getTradeEndpoint()}/trade/search/${props.filters.trade.league}/${searchResult.value.id}`
|
||||
: `https://${getTradeEndpoint()}/trade/search/${props.filters.trade.league}?q=${JSON.stringify(createTradeRequest(props.filters, props.stats, props.item))}`
|
||||
? `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))}`
|
||||
}
|
||||
|
||||
const { t } = useI18nNs('trade_result')
|
||||
@@ -247,7 +253,7 @@ export default defineComponent({
|
||||
error,
|
||||
showSeller: computed(() => widget.value.showSeller),
|
||||
makeTradeLink,
|
||||
openTradeLink () {
|
||||
openTradeLink() {
|
||||
showBrowser(makeTradeLink())
|
||||
}
|
||||
}
|
||||
@@ -261,7 +267,7 @@ export default defineComponent({
|
||||
@apply bg-gray-800;
|
||||
@apply p-0 m-0;
|
||||
|
||||
& > div {
|
||||
&>div {
|
||||
@apply border-b border-gray-700;
|
||||
}
|
||||
}
|
||||
@@ -271,10 +277,14 @@ export default defineComponent({
|
||||
height: 0.375rem;
|
||||
border-radius: 100%;
|
||||
|
||||
&.online { /* */ }
|
||||
&.online {
|
||||
/* */
|
||||
}
|
||||
|
||||
&.offline {
|
||||
@apply bg-red-600;
|
||||
}
|
||||
|
||||
&.afk {
|
||||
@apply bg-orange-500;
|
||||
}
|
||||
|
||||
@@ -1,190 +1,225 @@
|
||||
import { DateTime } from 'luxon'
|
||||
import { Host } from '@/web/background/IPC'
|
||||
import { TradeResponse, Account, getTradeEndpoint, 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'
|
||||
import { DateTime } from 'luxon';
|
||||
import { Host } from '@/web/background/IPC';
|
||||
import {
|
||||
TradeResponse,
|
||||
Account,
|
||||
getTradeEndpoint,
|
||||
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';
|
||||
|
||||
interface TradeRequest { /* eslint-disable camelcase */
|
||||
engine: 'new'
|
||||
query: {
|
||||
status: { option: 'online' | 'onlineleague' | 'any' }
|
||||
have: string[]
|
||||
want: string[]
|
||||
minimum?: number
|
||||
fulfillable?: null
|
||||
}
|
||||
sort: { have: 'asc' }
|
||||
interface TradeRequest {
|
||||
/* eslint-disable camelcase */ engine: 'new';
|
||||
query: {
|
||||
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
|
||||
listing: {
|
||||
indexed: string
|
||||
offers: Array<{
|
||||
exchange: {
|
||||
currency: string
|
||||
amount: number
|
||||
}
|
||||
item: {
|
||||
amount: number
|
||||
stock: number
|
||||
}
|
||||
}>
|
||||
account: Account
|
||||
}
|
||||
id: string;
|
||||
listing: {
|
||||
indexed: string;
|
||||
offers: Array<{
|
||||
exchange: {
|
||||
currency: string;
|
||||
amount: number;
|
||||
};
|
||||
item: {
|
||||
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 (body: TradeRequest, leagueId: string): Promise<SearchResult> {
|
||||
let data = cache.get<SearchResult>([body, leagueId])
|
||||
async function requestTradeResultList(
|
||||
body: TradeRequest,
|
||||
leagueId: string
|
||||
): Promise<SearchResult> {
|
||||
let data = cache.get<SearchResult>([body, leagueId]);
|
||||
|
||||
if (!data) {
|
||||
preventQueueCreation([
|
||||
{ count: 1, limiters: RATE_LIMIT_RULES.EXCHANGE }
|
||||
])
|
||||
if (!data) {
|
||||
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/trade/exchange/${leagueId}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
adjustRateLimits(RATE_LIMIT_RULES.EXCHANGE, response.headers)
|
||||
const response = await Host.proxy(
|
||||
`${getTradeEndpoint()}/api/trade2/exchange/${leagueId}`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
);
|
||||
adjustRateLimits(RATE_LIMIT_RULES.EXCHANGE, response.headers);
|
||||
|
||||
const _data = await response.json() as TradeResponse<SearchResult>
|
||||
if (_data.error) {
|
||||
throw new Error(_data.error.message)
|
||||
} else {
|
||||
data = _data
|
||||
}
|
||||
const _data = (await response.json()) as TradeResponse<SearchResult>;
|
||||
if (_data.error) {
|
||||
throw new Error(_data.error.message);
|
||||
} else {
|
||||
data = _data;
|
||||
}
|
||||
|
||||
cache.set<SearchResult>([body, leagueId], data, Cache.deriveTtl(...RATE_LIMIT_RULES.EXCHANGE))
|
||||
}
|
||||
cache.set<SearchResult>(
|
||||
[body, leagueId],
|
||||
data,
|
||||
Cache.deriveTtl(...RATE_LIMIT_RULES.EXCHANGE)
|
||||
);
|
||||
}
|
||||
|
||||
return data
|
||||
return data;
|
||||
}
|
||||
|
||||
function toPricingResult (
|
||||
result: FetchResult,
|
||||
opts: { accountName: string },
|
||||
offer: number
|
||||
function toPricingResult(
|
||||
result: FetchResult,
|
||||
opts: { accountName: string },
|
||||
offer: number
|
||||
): PricingResult {
|
||||
return {
|
||||
id: result.id,
|
||||
relativeDate: DateTime.fromISO(result.listing.indexed).toRelative({ style: 'short' }) ?? '',
|
||||
exchangeAmount: result.listing.offers[offer].exchange.amount,
|
||||
itemAmount: result.listing.offers[offer].item.amount,
|
||||
stock: result.listing.offers[offer].item.stock,
|
||||
isMine: (result.listing.account.name === opts.accountName),
|
||||
ign: result.listing.account.lastCharacterName,
|
||||
accountName: result.listing.account.name,
|
||||
accountStatus: result.listing.account.online
|
||||
? (result.listing.account.online.status === 'afk' ? 'afk' : 'online')
|
||||
: 'offline'
|
||||
}
|
||||
return {
|
||||
id: result.id,
|
||||
relativeDate:
|
||||
DateTime.fromISO(result.listing.indexed).toRelative({ style: 'short' }) ??
|
||||
'',
|
||||
exchangeAmount: result.listing.offers[offer].exchange.amount,
|
||||
itemAmount: result.listing.offers[offer].item.amount,
|
||||
stock: result.listing.offers[offer].item.stock,
|
||||
isMine: result.listing.account.name === opts.accountName,
|
||||
ign: result.listing.account.lastCharacterName,
|
||||
accountName: result.listing.account.name,
|
||||
accountStatus: result.listing.account.online
|
||||
? result.listing.account.online.status === 'afk'
|
||||
? 'afk'
|
||||
: 'online'
|
||||
: 'offline',
|
||||
};
|
||||
}
|
||||
|
||||
export interface BulkSearch {
|
||||
queryId: string
|
||||
haveTag: string
|
||||
total: number
|
||||
listed: PricingResult[]
|
||||
queryId: string;
|
||||
haveTag: string;
|
||||
total: number;
|
||||
listed: PricingResult[];
|
||||
}
|
||||
|
||||
export function createTradeRequest (filters: ItemFilters, item: ParsedItem, have: string[]): TradeRequest {
|
||||
return {
|
||||
engine: 'new',
|
||||
query: {
|
||||
have: have,
|
||||
want: [tradeTag(item)!],
|
||||
status: {
|
||||
option: filters.trade.offline
|
||||
? 'any'
|
||||
: (filters.trade.onlineInLeague ? 'onlineleague' : 'online')
|
||||
},
|
||||
minimum: (filters.stackSize && !filters.stackSize.disabled) ? filters.stackSize.value : undefined
|
||||
// fulfillable: null
|
||||
},
|
||||
sort: { have: 'asc' }
|
||||
}
|
||||
export function createTradeRequest(
|
||||
filters: ItemFilters,
|
||||
item: ParsedItem,
|
||||
have: string[]
|
||||
): TradeRequest {
|
||||
return {
|
||||
engine: 'new',
|
||||
query: {
|
||||
have: have,
|
||||
want: [tradeTag(item)!],
|
||||
status: {
|
||||
option: filters.trade.offline
|
||||
? 'any'
|
||||
: filters.trade.onlineInLeague
|
||||
? 'onlineleague'
|
||||
: 'online',
|
||||
},
|
||||
minimum:
|
||||
filters.stackSize && !filters.stackSize.disabled
|
||||
? filters.stackSize.value
|
||||
: undefined,
|
||||
// fulfillable: null
|
||||
},
|
||||
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 (
|
||||
item: ParsedItem,
|
||||
filters: ItemFilters,
|
||||
have: string[],
|
||||
opts: { accountName: string }
|
||||
export async function execBulkSearch(
|
||||
item: ParsedItem,
|
||||
filters: ItemFilters,
|
||||
have: string[],
|
||||
opts: { accountName: string }
|
||||
): Promise<Array<BulkSearch | null>> {
|
||||
const query = await requestTradeResultList(
|
||||
createTradeRequest(filters, item, have),
|
||||
filters.trade.league
|
||||
)
|
||||
const query = await requestTradeResultList(
|
||||
createTradeRequest(filters, item, have),
|
||||
filters.trade.league
|
||||
);
|
||||
|
||||
const offer = 0
|
||||
const results = Object.values(query.result)
|
||||
.filter(result => result.listing.offers.length === 1)
|
||||
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 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
|
||||
const loadedOnDemand =
|
||||
tradeTag === 'chaos' &&
|
||||
resultsTag.length < SHOW_RESULTS &&
|
||||
query.total > API_FETCH_LIMIT;
|
||||
if (loadedOnDemand) return null;
|
||||
|
||||
const listed = resultsTag
|
||||
.sort((a, b) =>
|
||||
(a.listing.offers[offer].exchange.amount / a.listing.offers[offer].item.amount) -
|
||||
(b.listing.offers[offer].exchange.amount / b.listing.offers[offer].item.amount))
|
||||
.slice(0, SHOW_RESULTS)
|
||||
.map(result => toPricingResult(result, opts, offer))
|
||||
const listed = resultsTag
|
||||
.sort(
|
||||
(a, b) =>
|
||||
a.listing.offers[offer].exchange.amount /
|
||||
a.listing.offers[offer].item.amount -
|
||||
b.listing.offers[offer].exchange.amount /
|
||||
b.listing.offers[offer].item.amount
|
||||
)
|
||||
.slice(0, SHOW_RESULTS)
|
||||
.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)
|
||||
)
|
||||
const chaosIsLoaded =
|
||||
tradeTag === 'divine' &&
|
||||
resultsTag.length < results.length &&
|
||||
(results.length - resultsTag.length >= SHOW_RESULTS ||
|
||||
query.total <= API_FETCH_LIMIT);
|
||||
|
||||
return {
|
||||
queryId: query.id,
|
||||
haveTag: tradeTag,
|
||||
// this is a best guess when making request with multiple `have` currencies
|
||||
total: (chaosIsLoaded)
|
||||
? resultsTag.length
|
||||
: (query.total - (results.length - resultsTag.length)),
|
||||
listed: listed
|
||||
}
|
||||
})
|
||||
return {
|
||||
queryId: query.id,
|
||||
haveTag: tradeTag,
|
||||
// this is a best guess when making request with multiple `have` currencies
|
||||
total: chaosIsLoaded
|
||||
? resultsTag.length
|
||||
: query.total - (results.length - resultsTag.length),
|
||||
listed: listed,
|
||||
};
|
||||
});
|
||||
|
||||
return resultByHave
|
||||
return resultByHave;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,7 +55,7 @@ export default defineComponent({
|
||||
!props.item.info.unique
|
||||
})
|
||||
|
||||
function select (info: BaseType) {
|
||||
function select(info: BaseType) {
|
||||
const newItem: ParsedItem = {
|
||||
...props.item!,
|
||||
info: info
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :class="$style.podium" v-if="podiumVisible">
|
||||
<div v-for="i in [2, 4, 5, 3, 1]">
|
||||
<div v-for="patron in patrons[i - 1]" :key="patron.from"
|
||||
:class="[$style.rating, $style[`rating-${patron.style}`]]"
|
||||
>{{ patron.from }}{{ (patron.months > 1) ? ` x${patron.months}` : null }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[$style.patronsHorizontal, { 'invisible': podiumVisible }]" :onMouseenter="showPodium">
|
||||
<div class="bg-gray-800 rounded p-1 justify-center text-center w-44 shrink-0 flex items-center">
|
||||
{{ t('settings.thank_you') }}
|
||||
</div>
|
||||
<div class="overflow-x-hidden whitespace-nowrap p-1 text-base">
|
||||
<span :class="$style.patronsLine">{{ patronsString[0] }}</span><br>
|
||||
<span :class="$style.patronsLine">{{ patronsString[1] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.window" class="grow layout-column" :onMouseenter="hidePodium">
|
||||
<AppTitleBar @close="cancel" :title="t('settings.title')" />
|
||||
<div class="flex grow min-h-0">
|
||||
<div class="pl-2 pt-2 bg-gray-900 flex flex-col gap-1" style="min-width: 10rem;">
|
||||
<template v-for="item of menuItems">
|
||||
<button v-if="item.type === 'menu-item'"
|
||||
@click="item.select" :class="[$style['menu-item'], { [$style['active']]: item.isSelected }]">{{ item.name }}</button>
|
||||
<div v-else
|
||||
class="border-b mx-2 border-gray-800" />
|
||||
</template>
|
||||
<button v-if="menuItems.length >= 4"
|
||||
:class="$style['quit-btn']" @click="quit">{{ t('app.quit') }}</button>
|
||||
<div class="text-gray-400 text-center mt-auto pr-3 pt-4 pb-12" style="max-width: fit-content; min-width: 100%;">
|
||||
<img class="mx-auto mb-1" src="/images/peepoLove2x.webp">
|
||||
{{ t('Support development on') }}<br> <a href="https://patreon.com/awakened_poe_trade" class="inline-flex mt-1" target="_blank"><img class="inline h-5" src="/images/Patreon.svg"></a>
|
||||
</div>
|
||||
<div>
|
||||
<div :class="$style.podium" v-if="podiumVisible">
|
||||
<div v-for="i in [2, 4, 5, 3, 1]">
|
||||
<div v-for="patron in patrons[i - 1]" :key="patron.from"
|
||||
:class="[$style.rating, $style[`rating-${patron.style}`]]">{{ patron.from }}{{ (patron.months > 1) ? `
|
||||
x${patron.months}` : null }}</div>
|
||||
</div>
|
||||
<div class="text-gray-100 grow layout-column bg-gray-900">
|
||||
<div class="grow overflow-y-auto bg-gray-800 rounded-tl">
|
||||
<component v-if="configClone"
|
||||
:is="selectedComponent" :config="configClone" :configWidget="configWidget" />
|
||||
</div>
|
||||
<div :class="[$style.patronsHorizontal, { 'invisible': podiumVisible }]" :onMouseenter="showPodium">
|
||||
<div class="bg-gray-800 rounded p-1 justify-center text-center w-44 shrink-0 flex items-center">
|
||||
{{ t('settings.thank_you') }}
|
||||
</div>
|
||||
<div class="overflow-x-hidden whitespace-nowrap p-1 text-base">
|
||||
<span :class="$style.patronsLine">{{ patronsString[0] }}</span><br>
|
||||
<span :class="$style.patronsLine">{{ patronsString[1] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.window" class="grow layout-column" :onMouseenter="hidePodium">
|
||||
<ConversionWarningBanner />
|
||||
<AppTitleBar @close="cancel" :title="t('settings.title')" />
|
||||
<div class="flex grow min-h-0">
|
||||
<div class="pl-2 pt-2 bg-gray-900 flex flex-col gap-1" style="min-width: 10rem;">
|
||||
<template v-for="item of menuItems">
|
||||
<button v-if="item.type === 'menu-item'" @click="item.select"
|
||||
:class="[$style['menu-item'], { [$style['active']]: item.isSelected }]">{{ item.name }}</button>
|
||||
<div v-else class="border-b mx-2 border-gray-800" />
|
||||
</template>
|
||||
<button v-if="menuItems.length >= 4" :class="$style['quit-btn']" @click="quit">{{ t('app.quit') }}</button>
|
||||
<div class="text-gray-400 text-center mt-auto pr-3 pt-4 pb-12"
|
||||
style="max-width: fit-content; min-width: 100%;">
|
||||
<img class="mx-auto mb-1" src="/images/peepoLove2x.webp">
|
||||
{{ t('Support development on') }}<br> <a href="https://patreon.com/awakened_poe_trade"
|
||||
class="inline-flex mt-1" target="_blank"><img class="inline h-5" src="/images/Patreon.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t bg-gray-900 border-gray-600 p-2 flex justify-end gap-x-2">
|
||||
<button @click="save" class="px-3 bg-gray-800 rounded">{{ t('Save') }}</button>
|
||||
<button @click="cancel" class="px-3">{{ t('Cancel') }}</button>
|
||||
<div class="text-gray-100 grow layout-column bg-gray-900">
|
||||
<div class="grow overflow-y-auto bg-gray-800 rounded-tl">
|
||||
<component v-if="configClone" :is="selectedComponent" :config="configClone" :configWidget="configWidget" />
|
||||
</div>
|
||||
<div class="border-t bg-gray-900 border-gray-600 p-2 flex justify-end gap-x-2">
|
||||
<button @click="save" class="px-3 bg-gray-800 rounded">{{ t('Save') }}</button>
|
||||
<button @click="cancel" class="px-3">{{ t('Cancel') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -67,8 +67,9 @@ import SettingsMaps from '../map-check/settings-maps.vue'
|
||||
import SettingsStashSearch from '../stash-search/stash-search-editor.vue'
|
||||
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)
|
||||
@@ -79,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' }
|
||||
@@ -87,14 +88,14 @@ function quit () {
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: { AppTitleBar },
|
||||
components: { AppTitleBar, ConversionWarningBanner },
|
||||
props: {
|
||||
config: {
|
||||
type: Object as PropType<Widget>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const wm = inject<WidgetManager>('wm')!
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -142,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
|
||||
}))),
|
||||
@@ -151,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,
|
||||
@@ -177,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]]
|
||||
@@ -205,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)
|
||||
@@ -218,13 +219,17 @@ function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
|
||||
<style lang="postcss" module>
|
||||
.window {
|
||||
position: absolute;
|
||||
top: 0; bottom: 0; left: 0; right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
max-width: 50rem;
|
||||
max-height: 38rem;
|
||||
overflow: hidden;
|
||||
@apply bg-gray-800;
|
||||
@apply rounded-b;
|
||||
|
||||
&:global {
|
||||
animation-name: slideInDown;
|
||||
animation-duration: 1s;
|
||||
@@ -262,10 +267,13 @@ function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
|
||||
.patronsHorizontal {
|
||||
@apply bg-gray-900 p-1 rounded gap-1;
|
||||
position: absolute;
|
||||
top: 40rem; left: 0; right: 0;
|
||||
top: 40rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
max-width: 50rem;
|
||||
display: flex;
|
||||
|
||||
&:global {
|
||||
animation-name: slideInDown;
|
||||
animation-duration: 1s;
|
||||
@@ -273,10 +281,19 @@ function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
|
||||
}
|
||||
|
||||
@keyframes slide {
|
||||
0% { transform: translate(0%, 0); }
|
||||
4% { transform: translate(0%, 0); }
|
||||
100% { transform: translate(-99%, 0); }
|
||||
0% {
|
||||
transform: translate(0%, 0);
|
||||
}
|
||||
|
||||
4% {
|
||||
transform: translate(0%, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-99%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.patronsLine {
|
||||
display: inline-block;
|
||||
animation: slide 64s linear infinite;
|
||||
@@ -291,22 +308,40 @@ function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
@apply gap-4 p-4;
|
||||
|
||||
&:global {
|
||||
animation-name: fadeIn;
|
||||
animation-duration: 1.5s;
|
||||
}
|
||||
}
|
||||
.podium > div {
|
||||
|
||||
.podium>div {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
min-width: min-content;
|
||||
}
|
||||
.podium > div:nth-child(1) { max-width: 18rem; }
|
||||
.podium > div:nth-child(2) { max-width: 16rem; }
|
||||
.podium > div:nth-child(3) { flex-direction: column; align-items: center; }
|
||||
.podium > div:nth-child(4) { max-width: 24rem; }
|
||||
.podium > div:nth-child(5) { max-width: 18rem; }
|
||||
|
||||
.podium>div:nth-child(1) {
|
||||
max-width: 18rem;
|
||||
}
|
||||
|
||||
.podium>div:nth-child(2) {
|
||||
max-width: 16rem;
|
||||
}
|
||||
|
||||
.podium>div:nth-child(3) {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.podium>div:nth-child(4) {
|
||||
max-width: 24rem;
|
||||
}
|
||||
|
||||
.podium>div:nth-child(5) {
|
||||
max-width: 18rem;
|
||||
}
|
||||
|
||||
.rating {
|
||||
min-width: 3rem;
|
||||
@@ -314,30 +349,35 @@ function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
|
||||
white-space: nowrap;
|
||||
@apply px-1 border;
|
||||
}
|
||||
|
||||
.rating-1 {
|
||||
background-color: rgb(0, 0, 0);
|
||||
color: rgb(190, 178, 135);
|
||||
border-color: currentColor;
|
||||
@apply text-base;
|
||||
}
|
||||
|
||||
.rating-2 {
|
||||
background-color: rgb(210, 178, 135);
|
||||
color: rgb(0, 0, 0);
|
||||
border-color: currentColor;
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
.rating-3 {
|
||||
background-color: rgb(213, 159, 0);
|
||||
color: rgb(0, 0, 0);
|
||||
border-color: currentColor;
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
.rating-4 {
|
||||
background-color: rgb(240, 90, 35);
|
||||
color: rgb(255, 255, 255);
|
||||
border-color: currentColor;
|
||||
@apply text-xl;
|
||||
}
|
||||
|
||||
.rating-5 {
|
||||
background-color: rgb(255, 255, 255);
|
||||
color: rgb(255, 0, 0);
|
||||
|
||||
@@ -2,24 +2,28 @@
|
||||
<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">Awakened PoE Trade</p>
|
||||
<p class="text-base">Awakened PoE2 Trade2</p>
|
||||
<p class="">{{ t('app.version', [version]) }}</p>
|
||||
<div class="flex gap-2">
|
||||
<a class="border-b" href="https://github.com/SnosMe/awakened-poe-trade/releases" target="_blank">{{ t('app.release_notes') }}</a>
|
||||
<a class="border-b" href="https://github.com/SnosMe/awakened-poe-trade/issues" target="_blank">{{ t('app.report_bug') }}</a>
|
||||
<a class="border-b" href="https://github.com/Kvan7/awakened-poe2-trade2/releases" target="_blank">{{
|
||||
t('app.release_notes') }}</a>
|
||||
<a class="border-b" href="https://github.com/Kvan7/awakened-poe2-trade2/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">
|
||||
<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"><@295216259795124225></span></p>
|
||||
<p>{{ t('app.contact_me') }} <br><span
|
||||
class="font-sans text-gray-500 select-all"><@295216259795124225></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>
|
||||
@@ -31,32 +35,32 @@ 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' }
|
||||
})
|
||||
}
|
||||
|
||||
function openDownloadPage () {
|
||||
function openDownloadPage() {
|
||||
window.open('https://snosme.github.io/awakened-poe-trade/download')
|
||||
}
|
||||
|
||||
function quitAndInstall () {
|
||||
function quitAndInstall() {
|
||||
Host.sendEvent({
|
||||
name: 'CLIENT->MAIN::user-action',
|
||||
payload: { action: 'update-and-restart' }
|
||||
})
|
||||
}
|
||||
|
||||
function fmtTime (millis: number) {
|
||||
function fmtTime(millis: number) {
|
||||
return DateTime.fromMillis(millis).toRelative({ style: 'long' }) ?? 'n/a'
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'settings.about',
|
||||
inheritAttrs: false,
|
||||
setup () {
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
|
||||
const info = computed(() => {
|
||||
|
||||
@@ -28,12 +28,12 @@
|
||||
<div class="mb-2">
|
||||
<div class="flex-1 mb-1">{{ t(':poe_log_file') }}</div>
|
||||
<input v-model.trim="clientLog"
|
||||
class="rounded bg-gray-900 px-1 block w-full font-sans" placeholder="...?/Grinding Gear Games/Path of Exile/logs/Client.txt">
|
||||
class="rounded bg-gray-900 px-1 block w-full font-sans" placeholder="...?/Grinding Gear Games/Path of Exile 2/logs/Client.txt">
|
||||
</div>
|
||||
<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/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">
|
||||
|
||||
3267
renderer/yarn.lock
Normal file
3267
renderer/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user