LGTM
This commit is contained in:
@@ -14,22 +14,24 @@ jobs:
|
|||||||
- name: Verify Node.js
|
- name: Verify Node.js
|
||||||
run: node -v
|
run: node -v
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install electron-app dependencies
|
||||||
working-directory: electron-app
|
working-directory: electron-app
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Build Windows executable
|
- name: Create production .env file
|
||||||
working-directory: electron-app
|
working-directory: electron-app
|
||||||
env:
|
run: |
|
||||||
WS_URL: ${{ secrets.WS_URL }}
|
echo "WS_URL=${{ secrets.WS_URL }}" > .env
|
||||||
API_URL: ${{ secrets.API_URL }}
|
echo "API_URL=${{ secrets.API_URL }}" >> .env
|
||||||
RELEASE_URL: ${{ secrets.RELEASE_URL }}
|
echo "NODE_ENV=production" >> .env
|
||||||
NODE_ENV: production
|
|
||||||
run: npm run electron:build -- --win
|
|
||||||
|
|
||||||
- name: Upload Windows artifact
|
- name: Build Windows portable executable
|
||||||
|
working-directory: electron-app
|
||||||
|
run: npm run build:portable
|
||||||
|
|
||||||
|
- name: Upload Windows portable artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-exe
|
name: rmtPocketWatcher-Windows-Portable
|
||||||
path: electron-app/release/*.exe
|
path: electron-app/release/rmtPocketWatcher-*.exe
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# WebSocket connection URL
|
# WebSocket connection URL
|
||||||
WS_URL=ws://localhost:3000/ws
|
WS_URL=ws://localhost:3000/ws
|
||||||
|
|
||||||
|
# API URL
|
||||||
|
API_URL=http://localhost:3000
|
||||||
|
|
||||||
# Development mode
|
# Development mode
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
|
|||||||
209
electron-app/package-lock.json
generated
209
electron-app/package-lock.json
generated
@@ -27,6 +27,7 @@
|
|||||||
"electron-rebuild": "^3.2.9",
|
"electron-rebuild": "^3.2.9",
|
||||||
"react": "^19.2.1",
|
"react": "^19.2.1",
|
||||||
"react-dom": "^19.2.1",
|
"react-dom": "^19.2.1",
|
||||||
|
"rimraf": "^6.1.2",
|
||||||
"typescript": "^5.3.0",
|
"typescript": "^5.3.0",
|
||||||
"vite": "^5.0.0",
|
"vite": "^5.0.0",
|
||||||
"wait-on": "^7.2.0"
|
"wait-on": "^7.2.0"
|
||||||
@@ -1054,6 +1055,29 @@
|
|||||||
"@hapi/hoek": "^9.0.0"
|
"@hapi/hoek": "^9.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@isaacs/balanced-match": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@isaacs/brace-expansion": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/balanced-match": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@isaacs/cliui": {
|
"node_modules/@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
@@ -1327,6 +1351,23 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@npmcli/move-file/node_modules/rimraf": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"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",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rimraf": "bin.js"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@pkgjs/parseargs": {
|
"node_modules/@pkgjs/parseargs": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||||
@@ -2744,6 +2785,17 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cacache/node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cacache/node_modules/glob": {
|
"node_modules/cacache/node_modules/glob": {
|
||||||
"version": "8.1.0",
|
"version": "8.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||||
@@ -2788,6 +2840,58 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cacache/node_modules/rimraf": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"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",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rimraf": "bin.js"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cacache/node_modules/rimraf/node_modules/glob": {
|
||||||
|
"version": "7.2.3",
|
||||||
|
"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",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.1.1",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cacache/node_modules/rimraf/node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cacheable-lookup": {
|
"node_modules/cacheable-lookup": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||||
@@ -5943,6 +6047,23 @@
|
|||||||
"node-gyp-build-test": "build-test.js"
|
"node-gyp-build-test": "build-test.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-gyp/node_modules/rimraf": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"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",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rimraf": "bin.js"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-gyp/node_modules/semver": {
|
"node_modules/node-gyp/node_modules/semver": {
|
||||||
"version": "7.7.3",
|
"version": "7.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||||
@@ -6562,17 +6683,91 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rimraf": {
|
"node_modules/rimraf": {
|
||||||
"version": "3.0.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz",
|
||||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
"integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==",
|
||||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "BlueOak-1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^13.0.0",
|
||||||
|
"package-json-from-dist": "^1.0.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"rimraf": "bin.js"
|
"rimraf": "dist/esm/bin.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rimraf/node_modules/glob": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"minimatch": "^10.1.1",
|
||||||
|
"minipass": "^7.1.2",
|
||||||
|
"path-scurry": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rimraf/node_modules/lru-cache": {
|
||||||
|
"version": "11.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz",
|
||||||
|
"integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rimraf/node_modules/minimatch": {
|
||||||
|
"version": "10.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||||
|
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/brace-expansion": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rimraf/node_modules/minipass": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rimraf/node_modules/path-scurry": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^11.0.0",
|
||||||
|
"minipass": "^7.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
"build:main": "npx tsc --project tsconfig.main.json && npx tsc --project tsconfig.preload.json",
|
"build:main": "npx tsc --project tsconfig.main.json && npx tsc --project tsconfig.preload.json",
|
||||||
"build:renderer": "npx vite build",
|
"build:renderer": "npx vite build",
|
||||||
"build": "npm run build:main && npm run build:renderer",
|
"build": "npm run build:main && npm run build:renderer",
|
||||||
|
"build:portable": "npm run build && npx electron-builder --win portable",
|
||||||
|
"clean": "rimraf dist",
|
||||||
|
"clean:dev": "npm run clean && npm run build:main && concurrently \"npm run dev\" \"wait-on http://localhost:5173 && cross-env NODE_ENV=development electron dist/main/index.js\"",
|
||||||
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && cross-env NODE_ENV=development electron dist/main/index.js\"",
|
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && cross-env NODE_ENV=development electron dist/main/index.js\"",
|
||||||
"electron:build": "npm run build && electron-builder",
|
"electron:build": "npm run build && electron-builder",
|
||||||
"publish": "npm run build && electron-builder --publish always",
|
"publish": "npm run build && electron-builder --publish always",
|
||||||
"rebuild": "electron-rebuild",
|
"rebuild": "electron-rebuild",
|
||||||
|
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -36,6 +38,7 @@
|
|||||||
"electron-rebuild": "^3.2.9",
|
"electron-rebuild": "^3.2.9",
|
||||||
"react": "^19.2.1",
|
"react": "^19.2.1",
|
||||||
"react-dom": "^19.2.1",
|
"react-dom": "^19.2.1",
|
||||||
|
"rimraf": "^6.1.2",
|
||||||
"typescript": "^5.3.0",
|
"typescript": "^5.3.0",
|
||||||
"vite": "^5.0.0",
|
"vite": "^5.0.0",
|
||||||
"wait-on": "^7.2.0"
|
"wait-on": "^7.2.0"
|
||||||
|
|||||||
@@ -33,6 +33,14 @@ export function initDatabase() {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
// Create settings table for custom AUEC amount
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS settings (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
console.log('Database initialized at:', dbPath);
|
console.log('Database initialized at:', dbPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +88,26 @@ export function deleteAlert(id: string): void {
|
|||||||
stmt.run(id);
|
stmt.run(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCustomAuecAmount(): number | null {
|
||||||
|
if (!db) throw new Error('Database not initialized');
|
||||||
|
|
||||||
|
const stmt = db.prepare('SELECT value FROM settings WHERE key = ?');
|
||||||
|
const row = stmt.get('customAuecAmount') as any;
|
||||||
|
|
||||||
|
return row ? parseFloat(row.value) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCustomAuecAmount(amount: number): void {
|
||||||
|
if (!db) throw new Error('Database not initialized');
|
||||||
|
|
||||||
|
const stmt = db.prepare(`
|
||||||
|
INSERT OR REPLACE INTO settings (key, value)
|
||||||
|
VALUES (?, ?)
|
||||||
|
`);
|
||||||
|
|
||||||
|
stmt.run('customAuecAmount', amount.toString());
|
||||||
|
}
|
||||||
|
|
||||||
export function closeDatabase(): void {
|
export function closeDatabase(): void {
|
||||||
if (db) {
|
if (db) {
|
||||||
db.close();
|
db.close();
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
|
|||||||
try { ipcMain.removeHandler('alerts:add'); } catch (e) { /* ignore */ }
|
try { ipcMain.removeHandler('alerts:add'); } catch (e) { /* ignore */ }
|
||||||
try { ipcMain.removeHandler('alerts:update'); } catch (e) { /* ignore */ }
|
try { ipcMain.removeHandler('alerts:update'); } catch (e) { /* ignore */ }
|
||||||
try { ipcMain.removeHandler('alerts:delete'); } catch (e) { /* ignore */ }
|
try { ipcMain.removeHandler('alerts:delete'); } catch (e) { /* ignore */ }
|
||||||
|
try { ipcMain.removeHandler('settings:getCustomAuecAmount'); } catch (e) { /* ignore */ }
|
||||||
|
try { ipcMain.removeHandler('settings:setCustomAuecAmount'); } catch (e) { /* ignore */ }
|
||||||
|
|
||||||
// IPC handlers for renderer requests
|
// IPC handlers for renderer requests
|
||||||
ipcMain.handle('ws:connect', async () => {
|
ipcMain.handle('ws:connect', async () => {
|
||||||
@@ -155,6 +157,26 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Custom AUEC amount handlers
|
||||||
|
ipcMain.handle('settings:getCustomAuecAmount', async () => {
|
||||||
|
try {
|
||||||
|
return db.getCustomAuecAmount();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to get custom AUEC amount:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('settings:setCustomAuecAmount', async (_event, amount: number) => {
|
||||||
|
try {
|
||||||
|
db.setCustomAuecAmount(amount);
|
||||||
|
return { success: true };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set custom AUEC amount:', error);
|
||||||
|
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Auto-connect on startup
|
// Auto-connect on startup
|
||||||
wsClient.connect();
|
wsClient.connect();
|
||||||
}
|
}
|
||||||
@@ -181,6 +203,8 @@ export function cleanupIpcHandlers(): void {
|
|||||||
ipcMain.removeHandler('alerts:add');
|
ipcMain.removeHandler('alerts:add');
|
||||||
ipcMain.removeHandler('alerts:update');
|
ipcMain.removeHandler('alerts:update');
|
||||||
ipcMain.removeHandler('alerts:delete');
|
ipcMain.removeHandler('alerts:delete');
|
||||||
|
ipcMain.removeHandler('settings:getCustomAuecAmount');
|
||||||
|
ipcMain.removeHandler('settings:setCustomAuecAmount');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handlers may not exist, ignore
|
// Handlers may not exist, ignore
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ export function App() {
|
|||||||
const [alertNotification, setAlertNotification] = useState<AlertNotification | null>(null);
|
const [alertNotification, setAlertNotification] = useState<AlertNotification | null>(null);
|
||||||
const alertAudioRef = useRef<HTMLAudioElement | null>(null);
|
const alertAudioRef = useRef<HTMLAudioElement | null>(null);
|
||||||
|
|
||||||
|
// Custom AUEC Amount State
|
||||||
|
const [customAuecAmount, setCustomAuecAmount] = useState<number | null>(null);
|
||||||
|
const [customAuecInput, setCustomAuecInput] = useState('');
|
||||||
|
|
||||||
// Load alerts from database on mount
|
// Load alerts from database on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadAlerts = async () => {
|
const loadAlerts = async () => {
|
||||||
@@ -65,6 +69,22 @@ export function App() {
|
|||||||
loadAlerts();
|
loadAlerts();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Load custom AUEC amount from database on mount
|
||||||
|
useEffect(() => {
|
||||||
|
const loadCustomAmount = async () => {
|
||||||
|
try {
|
||||||
|
const amount = await window.electron.ipcRenderer.invoke('settings:getCustomAuecAmount');
|
||||||
|
if (amount) {
|
||||||
|
setCustomAuecAmount(amount);
|
||||||
|
setCustomAuecInput(amount.toString());
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load custom AUEC amount:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadCustomAmount();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Fetch initial data on mount
|
// Fetch initial data on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchInitialData();
|
fetchInitialData();
|
||||||
@@ -374,6 +394,21 @@ export function App() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const saveCustomAuecAmount = async () => {
|
||||||
|
const amount = parseFloat(customAuecInput);
|
||||||
|
if (isNaN(amount) || amount <= 0) {
|
||||||
|
alert('Please enter a valid AUEC amount');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await window.electron.ipcRenderer.invoke('settings:setCustomAuecAmount', amount);
|
||||||
|
setCustomAuecAmount(amount);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save custom AUEC amount:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const dismissNotification = () => {
|
const dismissNotification = () => {
|
||||||
setAlertNotification(null);
|
setAlertNotification(null);
|
||||||
};
|
};
|
||||||
@@ -769,7 +804,41 @@ export function App() {
|
|||||||
|
|
||||||
{latestPrice && (
|
{latestPrice && (
|
||||||
<div style={{ backgroundColor: '#1a1f3a', padding: '20px', borderRadius: '8px' }}>
|
<div style={{ backgroundColor: '#1a1f3a', padding: '20px', borderRadius: '8px' }}>
|
||||||
<h2 style={{ margin: '0 0 15px 0' }}>Current Listings ({latestPrice.allPrices.length})</h2>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '15px' }}>
|
||||||
|
<h2 style={{ margin: 0 }}>Current Listings ({latestPrice.allPrices.length})</h2>
|
||||||
|
<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
placeholder="Enter AUEC amount"
|
||||||
|
value={customAuecInput}
|
||||||
|
onChange={(e) => setCustomAuecInput(e.target.value)}
|
||||||
|
style={{
|
||||||
|
padding: '8px 12px',
|
||||||
|
backgroundColor: '#0a0e27',
|
||||||
|
border: '1px solid #2a2f4a',
|
||||||
|
borderRadius: '4px',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: '14px',
|
||||||
|
width: '180px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={saveCustomAuecAmount}
|
||||||
|
style={{
|
||||||
|
padding: '8px 16px',
|
||||||
|
backgroundColor: '#50e3c2',
|
||||||
|
color: '#0a0e27',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '4px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: '14px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Set Amount
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
overflowX: 'auto',
|
overflowX: 'auto',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
@@ -783,18 +852,30 @@ export function App() {
|
|||||||
<th style={{ textAlign: 'left', padding: '12px', color: '#888', fontWeight: 'normal' }}>Platform</th>
|
<th style={{ textAlign: 'left', padding: '12px', color: '#888', fontWeight: 'normal' }}>Platform</th>
|
||||||
<th style={{ textAlign: 'left', padding: '12px', color: '#888', fontWeight: 'normal' }}>Seller</th>
|
<th style={{ textAlign: 'left', padding: '12px', color: '#888', fontWeight: 'normal' }}>Seller</th>
|
||||||
<th style={{ textAlign: 'right', padding: '12px', color: '#888', fontWeight: 'normal' }}>Price/1M AUEC</th>
|
<th style={{ textAlign: 'right', padding: '12px', color: '#888', fontWeight: 'normal' }}>Price/1M AUEC</th>
|
||||||
|
{customAuecAmount && (
|
||||||
|
<th style={{ textAlign: 'right', padding: '12px', color: '#888', fontWeight: 'normal' }}>
|
||||||
|
Price for {(customAuecAmount / 1000000).toLocaleString()}M AUEC
|
||||||
|
</th>
|
||||||
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{latestPrice.allPrices.map((price) => (
|
{[...latestPrice.allPrices]
|
||||||
<tr key={price.id} style={{ borderBottom: '1px solid #2a2f4a' }}>
|
.sort((a, b) => a.pricePerMillion - b.pricePerMillion)
|
||||||
<td style={{ padding: '12px' }}>{price.platform}</td>
|
.map((price) => (
|
||||||
<td style={{ padding: '12px' }}>{price.sellerName}</td>
|
<tr key={price.id} style={{ borderBottom: '1px solid #2a2f4a' }}>
|
||||||
<td style={{ textAlign: 'right', padding: '12px', color: '#50e3c2', fontWeight: 'bold' }}>
|
<td style={{ padding: '12px' }}>{price.platform}</td>
|
||||||
${price.pricePerMillion.toFixed(9)}
|
<td style={{ padding: '12px' }}>{price.sellerName}</td>
|
||||||
</td>
|
<td style={{ textAlign: 'right', padding: '12px', color: '#50e3c2', fontWeight: 'bold' }}>
|
||||||
</tr>
|
${price.pricePerMillion.toFixed(9)}
|
||||||
))}
|
</td>
|
||||||
|
{customAuecAmount && (
|
||||||
|
<td style={{ textAlign: 'right', padding: '12px', color: '#50e3c2', fontWeight: 'bold' }}>
|
||||||
|
${((price.pricePerMillion * customAuecAmount) / 1000000).toFixed(2)}
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user