Socket Setup
This commit is contained in:
parent
d42a26ad8e
commit
aa00c75edf
|
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^2.10.1",
|
"@reduxjs/toolkit": "^2.10.1",
|
||||||
"@tailwindcss/vite": "^4.1.16",
|
"@tailwindcss/vite": "^4.1.16",
|
||||||
|
"active-win": "^7.2.0",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"electron-store": "^11.0.2",
|
"electron-store": "^11.0.2",
|
||||||
|
|
@ -22,11 +23,13 @@
|
||||||
"react-router-dom": "^7.9.5",
|
"react-router-dom": "^7.9.5",
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"sharp": "^0.34.4",
|
"sharp": "^0.34.4",
|
||||||
"tailwindcss": "^4.1.16"
|
"socket.io-client": "^4.8.1",
|
||||||
|
"tailwindcss": "^4.1.16",
|
||||||
|
"windowmanager": "^0.14.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.47.2",
|
"@playwright/test": "^1.47.2",
|
||||||
"@types/node": "^22.5.5",
|
"@types/node": "^22.19.0",
|
||||||
"@types/os-utils": "^0.0.4",
|
"@types/os-utils": "^0.0.4",
|
||||||
"@types/react": "^18.3.8",
|
"@types/react": "^18.3.8",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
|
|
@ -2300,6 +2303,12 @@
|
||||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@standard-schema/spec": {
|
"node_modules/@standard-schema/spec": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
||||||
|
|
@ -2758,14 +2767,22 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.5.5",
|
"version": "22.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.0.tgz",
|
||||||
"integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==",
|
"integrity": "sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.19.2"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node/node_modules/undici-types": {
|
||||||
|
"version": "6.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/os-utils": {
|
"node_modules/@types/os-utils": {
|
||||||
"version": "0.0.4",
|
"version": "0.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/os-utils/-/os-utils-0.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/os-utils/-/os-utils-0.0.4.tgz",
|
||||||
|
|
@ -2987,6 +3004,24 @@
|
||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/active-win": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/active-win/-/active-win-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-36fAH3MZinQ4dHQVa607P2woABkhgVxvSLBVGI7eK/M4Tx8LS+Gc+5fyx78MkAlM+RGV7wV9YnIx0lEuHERVZA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"ffi-napi": "^4.0.3",
|
||||||
|
"ref-napi": "^3.0.2",
|
||||||
|
"ref-struct-napi": "^1.1.1",
|
||||||
|
"ref-wchar-napi": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
|
@ -4526,7 +4561,6 @@
|
||||||
"version": "4.3.6",
|
"version": "4.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
|
||||||
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
|
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
|
||||||
"devOptional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
},
|
},
|
||||||
|
|
@ -5257,6 +5291,28 @@
|
||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/engine.io-client": {
|
||||||
|
"version": "6.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
|
||||||
|
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.2.1",
|
||||||
|
"ws": "~8.17.1",
|
||||||
|
"xmlhttprequest-ssl": "~2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io-parser": {
|
||||||
|
"version": "5.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
|
||||||
|
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.18.3",
|
"version": "5.18.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||||
|
|
@ -5572,6 +5628,32 @@
|
||||||
"pend": "~1.2.0"
|
"pend": "~1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ffi-napi": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ffi-napi/-/ffi-napi-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-PMdLCIvDY9mS32RxZ0XGb95sonPRal8aqRhLbeEtWKZTe2A87qRFG9HjOhvG8EX2UmQw5XNRMIOT+1MYlWmdeg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"get-uv-event-loop-napi-h": "^1.0.5",
|
||||||
|
"node-addon-api": "^3.0.0",
|
||||||
|
"node-gyp-build": "^4.2.1",
|
||||||
|
"ref-napi": "^2.0.1 || ^3.0.2",
|
||||||
|
"ref-struct-di": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ffi-napi/node_modules/node-addon-api": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/filelist": {
|
"node_modules/filelist": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
||||||
|
|
@ -5869,6 +5951,23 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-symbol-from-current-process-h": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-symbol-from-current-process-h/-/get-symbol-from-current-process-h-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-syloC6fsCt62ELLrr1VKBM1ggOpMdetX9hTrdW77UQdcApPHLmf7CI7OKcN1c9kYuNxKcDe4iJ4FY9sX3aw2xw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/get-uv-event-loop-napi-h": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-uv-event-loop-napi-h/-/get-uv-event-loop-napi-h-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-t5c9VNR84nRoF+eLiz6wFrEp1SE2Acg0wS+Ysa2zF0eROes+LzOfuTaVHxGy8AbS8rq7FHEJzjnCZo1BupwdJg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"get-symbol-from-current-process-h": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-windows": {
|
"node_modules/get-windows": {
|
||||||
"version": "9.2.3",
|
"version": "9.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/get-windows/-/get-windows-9.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/get-windows/-/get-windows-9.2.3.tgz",
|
||||||
|
|
@ -6528,6 +6627,21 @@
|
||||||
"ms": "^2.0.0"
|
"ms": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/iconv": {
|
||||||
|
"version": "2.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv/-/iconv-2.3.5.tgz",
|
||||||
|
"integrity": "sha512-U5ajDbtDfadp7pvUMC0F2XbkP5vQn9Xrwa6UptePl+cK8EILxapAt3sXers9B3Gxagk+zVjL2ELKuzQvyqOwug==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "^2.14.0",
|
||||||
|
"safer-buffer": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/iconv-corefoundation": {
|
"node_modules/iconv-corefoundation": {
|
||||||
"version": "1.1.7",
|
"version": "1.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
|
||||||
|
|
@ -7981,8 +8095,14 @@
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
"devOptional": true
|
},
|
||||||
|
"node_modules/nan": {
|
||||||
|
"version": "2.23.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.1.tgz",
|
||||||
|
"integrity": "sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.7",
|
"version": "3.3.7",
|
||||||
|
|
@ -8114,6 +8234,18 @@
|
||||||
"node": "^12.13 || ^14.13 || >=16"
|
"node": "^12.13 || ^14.13 || >=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-gyp-build": {
|
||||||
|
"version": "4.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||||
|
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"node-gyp-build": "bin.js",
|
||||||
|
"node-gyp-build-optional": "optional.js",
|
||||||
|
"node-gyp-build-test": "build-test.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-gyp/node_modules/semver": {
|
"node_modules/node-gyp/node_modules/semver": {
|
||||||
"version": "7.6.3",
|
"version": "7.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||||
|
|
@ -9134,6 +9266,129 @@
|
||||||
"redux": "^5.0.0"
|
"redux": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ref-napi": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ref-napi/-/ref-napi-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-LiMq/XDGcgodTYOMppikEtJelWsKQERbLQsYm0IOOnzhwE9xYZC7x8txNnFC9wJNOkPferQI4vD4ZkC0mDyrOA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"get-symbol-from-current-process-h": "^1.0.2",
|
||||||
|
"node-addon-api": "^3.0.0",
|
||||||
|
"node-gyp-build": "^4.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-napi/node_modules/node-addon-api": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-di": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ref-struct-di/-/ref-struct-di-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-2Xyn/0Qgz89VT+++WP0sTosdm9oeowLP23wRJYhG4BFdMUrLj3jhwHZNEytYNYgtPKLNTP3KJX4HEgBvM1/Y2g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-di/node_modules/debug": {
|
||||||
|
"version": "3.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ref-struct-napi/-/ref-struct-napi-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-YgS5/d7+kT5zgtySYI5ieH0hREdv+DabgDvoczxsui0f9VLm0rrDcWEj4DHKehsH+tJnVMsLwuyctWgvdEcVRw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "2",
|
||||||
|
"ref-napi": "^1.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi/node_modules/debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi/node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi/node_modules/node-addon-api": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi/node_modules/ref-napi": {
|
||||||
|
"version": "1.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ref-napi/-/ref-napi-1.5.2.tgz",
|
||||||
|
"integrity": "sha512-hwyNmWpUkt1bDWDW4aiwCoC+SJfJO69UIdjqssNqdaS0sYJpgqzosGg/rLtk69UoQ8drZdI9yyQefM7eEMM3Gw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^3.1.0",
|
||||||
|
"node-addon-api": "^2.0.0",
|
||||||
|
"node-gyp-build": "^4.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi/node_modules/ref-napi/node_modules/debug": {
|
||||||
|
"version": "3.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ref-struct-napi/node_modules/ref-napi/node_modules/ms": {
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"node_modules/ref-wchar-napi": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ref-wchar-napi/-/ref-wchar-napi-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-rx8b0pVfz/jShQPS288Rox/A0DQkcw6La+4YC3FgV4F9KUQ/VTxFrVpKOKGuj5yBvVoHdejbX6/BlHSkKHj9Lg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"iconv": "2",
|
||||||
|
"ref-napi": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
|
|
@ -9388,7 +9643,7 @@
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/sanitize-filename": {
|
"node_modules/sanitize-filename": {
|
||||||
"version": "1.6.3",
|
"version": "1.6.3",
|
||||||
|
|
@ -9688,6 +9943,34 @@
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/socket.io-client": {
|
||||||
|
"version": "4.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
|
||||||
|
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io-client": "~6.6.1",
|
||||||
|
"socket.io-parser": "~4.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io-parser": {
|
||||||
|
"version": "4.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||||
|
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/socks": {
|
"node_modules/socks": {
|
||||||
"version": "2.8.3",
|
"version": "2.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
|
||||||
|
|
@ -10354,7 +10637,7 @@
|
||||||
"version": "6.19.8",
|
"version": "6.19.8",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||||
"devOptional": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/unique-filename": {
|
"node_modules/unique-filename": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
|
|
@ -10746,6 +11029,12 @@
|
||||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/windowmanager": {
|
||||||
|
"version": "0.14.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/windowmanager/-/windowmanager-0.14.8.tgz",
|
||||||
|
"integrity": "sha512-USYABhvy9hce52h9p6h+8LSGhA0ypm/wuydnUm0nAaukPnWyfGByZs+eJAzfE4udVLDykIdZX3YzMk/lTHkgKw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/wrap-ansi": {
|
"node_modules/wrap-ansi": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||||
|
|
@ -10853,6 +11142,27 @@
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||||
|
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xmlbuilder": {
|
"node_modules/xmlbuilder": {
|
||||||
"version": "15.1.1",
|
"version": "15.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||||
|
|
@ -10862,6 +11172,14 @@
|
||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xmlhttprequest-ssl": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^2.10.1",
|
"@reduxjs/toolkit": "^2.10.1",
|
||||||
"@tailwindcss/vite": "^4.1.16",
|
"@tailwindcss/vite": "^4.1.16",
|
||||||
|
"active-win": "^7.2.0",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"electron-store": "^11.0.2",
|
"electron-store": "^11.0.2",
|
||||||
|
|
@ -32,11 +33,13 @@
|
||||||
"react-router-dom": "^7.9.5",
|
"react-router-dom": "^7.9.5",
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"sharp": "^0.34.4",
|
"sharp": "^0.34.4",
|
||||||
"tailwindcss": "^4.1.16"
|
"socket.io-client": "^4.8.1",
|
||||||
|
"tailwindcss": "^4.1.16",
|
||||||
|
"windowmanager": "^0.14.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.47.2",
|
"@playwright/test": "^1.47.2",
|
||||||
"@types/node": "^22.5.5",
|
"@types/node": "^22.19.0",
|
||||||
"@types/os-utils": "^0.0.4",
|
"@types/os-utils": "^0.0.4",
|
||||||
"@types/react": "^18.3.8",
|
"@types/react": "^18.3.8",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import { ipcMain, BrowserWindow } from "electron";
|
import { ipcMain, BrowserWindow } from "electron";
|
||||||
import { getToken, saveToken, clearToken } from "../utils/tokenHelper.js";
|
import { getToken, saveToken, clearToken } from "../utils/tokenHelper.js";
|
||||||
import { getActiveApp, handleLogin, takeScreenshot, startWindowPolling } from "../utils/utilityFunctions.js";
|
import { getActiveApp, handleLogin, takeScreenshot, startWindowPolling, getRunningAppsList, captureSpecificApp } from "../utils/utilityFunctions.js";
|
||||||
import api from "../api/axiosClient.js";
|
import api from "../api/axiosClient.js";
|
||||||
import { getMainWindow } from '../main.js';
|
import { getMainWindow } from '../main.js';
|
||||||
import { exec } from 'child_process';
|
|
||||||
|
|
||||||
export const registerIPCHandlers = (mainWindow: BrowserWindow) => {
|
export const registerIPCHandlers = (mainWindow: BrowserWindow) => {
|
||||||
console.log("⚙️ Registering IPC Handlers...");
|
console.log("⚙️ Registering IPC Handlers...");
|
||||||
|
|
||||||
|
|
@ -53,18 +51,25 @@ export const registerIPCHandlers = (mainWindow: BrowserWindow) => {
|
||||||
const mainWindow = getMainWindow()
|
const mainWindow = getMainWindow()
|
||||||
console.log("toggle-close-btn Called", mainWindow)
|
console.log("toggle-close-btn Called", mainWindow)
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
mainWindow.setClosable(shouldEnable);
|
mainWindow.setClosable(shouldEnable);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('resize-window', (event, width: number, height: number) => {
|
ipcMain.handle('resize-window', (event, width: number, height: number) => {
|
||||||
const mainWindow = getMainWindow()
|
const mainWindow = getMainWindow()
|
||||||
console.log("toggle-close-btn Called", mainWindow)
|
console.log("toggle-close-btn Called", mainWindow)
|
||||||
// if (mainWindow && !mainWindow.isDestroyed()) {
|
// if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
mainWindow.setSize(width, height);
|
mainWindow.setSize(width, height);
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
// ✅ Start background polling when main window is ready
|
|
||||||
};
|
};
|
||||||
// startWindowPolling(mainWindow);
|
|
||||||
|
ipcMain.handle('get-running-apps', async () => {
|
||||||
|
return await getRunningAppsList()
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('capture-specific-window', async (event, appTitle: string) => {
|
||||||
|
console.log(appTitle, "IPC HANDLE")
|
||||||
|
return await captureSpecificApp(appTitle)
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@ import { registerIPCHandlers } from './ipc/ipcHandler.js';
|
||||||
|
|
||||||
let mainWindow:any = null;
|
let mainWindow:any = null;
|
||||||
|
|
||||||
|
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
||||||
|
// Prevent the default behavior of showing a certificate error dialog
|
||||||
|
event.preventDefault();
|
||||||
|
// Allow the certificate, effectively ignoring the error
|
||||||
|
callback(true);
|
||||||
|
});
|
||||||
|
|
||||||
app.on('ready', async () => {
|
app.on('ready', async () => {
|
||||||
console.log("ready");
|
console.log("ready");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ contextBridge.exposeInMainWorld('electron', {
|
||||||
getActiveAppDetails: () => ipcRenderer.invoke('get-active-app'),
|
getActiveAppDetails: () => ipcRenderer.invoke('get-active-app'),
|
||||||
toggleCloseBtn: (shouldEnable: boolean) => ipcRenderer.invoke('toggle-close-btn', shouldEnable),
|
toggleCloseBtn: (shouldEnable: boolean) => ipcRenderer.invoke('toggle-close-btn', shouldEnable),
|
||||||
resizeWindow: (width: number, height: number) => ipcRenderer.invoke('resize-window', width, height),
|
resizeWindow: (width: number, height: number) => ipcRenderer.invoke('resize-window', width, height),
|
||||||
|
getRunningApps: () => ipcRenderer.invoke('get-running-apps'),
|
||||||
|
captureAppScreenShot: (appTitle: string) : Promise<string> => ipcRenderer.invoke('capture-specific-window', appTitle),
|
||||||
onWindowUpdate: (callback) =>
|
onWindowUpdate: (callback) =>
|
||||||
ipcRenderer.on("window:updated", (_, data) => callback(data)),
|
ipcRenderer.on("window:updated", (_, data) => callback(data)),
|
||||||
} satisfies Window['electron']);
|
} satisfies Window['electron']);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import axios from 'axios';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import { saveToken } from "./tokenHelper.js";
|
import { saveToken } from "./tokenHelper.js";
|
||||||
import { activeWindow } from "get-windows";
|
import { activeWindow } from "get-windows";
|
||||||
|
import { exec } from "child_process";
|
||||||
|
|
||||||
// Blur using an offscreen canvas
|
// Blur using an offscreen canvas
|
||||||
async function blurAndCompressBase64Image(base64: string): Promise<Buffer> {
|
async function blurAndCompressBase64Image(base64: string): Promise<Buffer> {
|
||||||
|
|
@ -97,21 +98,81 @@ export const handleLogin = async (credentials: { email: string, password: string
|
||||||
|
|
||||||
// Get active window info with timestamp
|
// Get active window info with timestamp
|
||||||
export const getActiveApp = async () => {
|
export const getActiveApp = async () => {
|
||||||
const result = await activeWindow();
|
const result = await activeWindow();
|
||||||
const dataWithTime = { ...result, timestamp: new Date().toISOString() };
|
const dataWithTime = { ...result, timestamp: new Date().toISOString() };
|
||||||
// console.log("🪟 Active Window with Time:", dataWithTime);
|
// console.log("🪟 Active Window with Time:", dataWithTime);
|
||||||
return dataWithTime;
|
return dataWithTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Periodically send active window updates
|
// Periodically send active window updates
|
||||||
export const startWindowPolling = (win: BrowserWindow) => {
|
export const startWindowPolling = (win: BrowserWindow) => {
|
||||||
console.log("⏱️ Started active window polling (every 5s)");
|
console.log("⏱️ Started active window polling (every 5s)");
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
|
try {
|
||||||
|
const app = await getActiveApp();
|
||||||
|
if (app) win.webContents.send("window:updated", app);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ Polling error:", err);
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const getRunningAppsList = async () => {
|
||||||
try {
|
try {
|
||||||
const app = await getActiveApp();
|
// PowerShell command: Get only apps with visible windows (non-background)
|
||||||
if (app) win.webContents.send("window:updated", app);
|
const sources = await desktopCapturer.getSources({
|
||||||
} catch (err) {
|
types: ['window', 'screen'],
|
||||||
console.error("❌ Polling error:", err);
|
thumbnailSize: { width: 150, height: 150 } // Optional: set thumbnail size
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = sources.map(source => ({
|
||||||
|
name: source.name,
|
||||||
|
pid: source.id,
|
||||||
|
// thumbnail: source.thumbnail // Can be used as screenshot
|
||||||
|
}));
|
||||||
|
return app
|
||||||
|
} catch (error) {
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
}, 5000);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
export const captureSpecificApp = async (windowTitle: string) : Promise<string> => {
|
||||||
|
try {
|
||||||
|
const sources = await desktopCapturer.getSources({
|
||||||
|
types: ['window', 'screen'],
|
||||||
|
thumbnailSize: { width: 650, height: 430 }
|
||||||
|
});
|
||||||
|
const targetSource = sources.find(source => source.name === windowTitle);
|
||||||
|
if (targetSource) {
|
||||||
|
|
||||||
|
let image = targetSource.thumbnail.toDataURL();
|
||||||
|
const blurredBuffer = await blurAndCompressBase64Image(image);
|
||||||
|
|
||||||
|
// Convert buffer → base64 string
|
||||||
|
const base64String = `data:image/png;base64,${blurredBuffer.toString('base64')}`;
|
||||||
|
|
||||||
|
// ✅ Return the processed base64 instead of saving
|
||||||
|
return base64String;
|
||||||
|
|
||||||
|
// const folderPath = "C:\\Users\\Public\\vatracker\\screenshots";
|
||||||
|
|
||||||
|
// // Ensure directory exists
|
||||||
|
// if (!fs.existsSync(folderPath)) {
|
||||||
|
// fs.mkdirSync(folderPath, { recursive: true });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const filePath = path.join(folderPath, `screenshot-${Date.now()}.png`);
|
||||||
|
// fs.writeFileSync(filePath, blurredBuffer);
|
||||||
|
|
||||||
|
// console.log(`Screenshot saved to ${filePath}`);
|
||||||
|
} else {
|
||||||
|
console.log(`Window with title "${windowTitle}" not found.`);
|
||||||
|
return "Not Found"
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error capturing screenshot:', error);
|
||||||
|
return 'Failed to capture screenshot.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
|
import io, { Socket } from 'socket.io-client';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Outlet,
|
Outlet,
|
||||||
NavLink,
|
NavLink,
|
||||||
|
|
@ -93,6 +95,11 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
|
|
||||||
useActiveAppTracker(isTracking, selectedProject?.id, selectedProject?.projectName);
|
useActiveAppTracker(isTracking, selectedProject?.id, selectedProject?.projectName);
|
||||||
|
|
||||||
|
const socketRef = useRef<Socket | null>(null);
|
||||||
|
const intervalRef = useRef<number | null>(null);
|
||||||
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
|
// const [seclectedScreen, setSelectedScreen] = useState<string | null>(null)
|
||||||
|
|
||||||
const [projectsData, setProjectsData] = useState<Project[]>([
|
const [projectsData, setProjectsData] = useState<Project[]>([
|
||||||
{ id: 1, projectName: "CRM Redesign", clientName: "Salesforce" },
|
{ id: 1, projectName: "CRM Redesign", clientName: "Salesforce" },
|
||||||
{ id: 2, projectName: "AI Assistant", clientName: "OpenAI" },
|
{ id: 2, projectName: "AI Assistant", clientName: "OpenAI" },
|
||||||
|
|
@ -116,6 +123,77 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Connect and start sending
|
||||||
|
const handleConnect = () => {
|
||||||
|
if (socketRef.current) {
|
||||||
|
console.warn("Already connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!selectedProject?.id) return
|
||||||
|
|
||||||
|
console.log(selectedProject?.id, "SelectedProject ID")
|
||||||
|
socketRef.current = io("http://localhost:3000", {
|
||||||
|
transports: ["websocket"],
|
||||||
|
auth: {
|
||||||
|
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY5MGIzMjhkMDkxMDFmNzRjZjUyNGMwNyIsImVtYWlsIjoiYmhhZ3dhbi5yQGhpY2dsb2JhbHNvbHV0aW9ucy5jb20iLCJuYW1lIjoiUm9oaXQiLCJpYXQiOjE3NjI4NTgxOTMsImV4cCI6MTc2Mjk0NDU5M30.UlHy3RU9W5LOid7smG7WzyNT7dnqhQT4qqzRrN1axmU",
|
||||||
|
projectId: selectedProject?.id,
|
||||||
|
userType: "va"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
socketRef.current.on("connect", () => {
|
||||||
|
console.log("🟢 Connected:", socketRef.current?.id);
|
||||||
|
setIsConnected(true);
|
||||||
|
|
||||||
|
// Start sending every 5 seconds
|
||||||
|
intervalRef.current = setInterval(async () => {
|
||||||
|
const apps = await window.electron.getRunningApps()
|
||||||
|
socketRef.current?.emit("getVisibleApps", { token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY5MGIzMjhkMDkxMDFmNzRjZjUyNGMwNyIsImVtYWlsIjoiYmhhZ3dhbi5yQGhpY2dsb2JhbHNvbHV0aW9ucy5jb20iLCJuYW1lIjoiUm9oaXQiLCJpYXQiOjE3NjI4NTgxOTMsImV4cCI6MTc2Mjk0NDU5M30.UlHy3RU9W5LOid7smG7WzyNT7dnqhQT4qqzRrN1axmU", apps });
|
||||||
|
|
||||||
|
// const base64String = await window.electron.captureAppScreenShot("Screen 1");
|
||||||
|
// if (base64String) {
|
||||||
|
// socketRef.current?.emit("sendImage", {token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY5MGIzMjhkMDkxMDFmNzRjZjUyNGMwNyIsImVtYWlsIjoiYmhhZ3dhbi5yQGhpY2dsb2JhbHNvbHV0aW9ucy5jb20iLCJuYW1lIjoiUm9oaXQiLCJpYXQiOjE3NjI4NTgxOTMsImV4cCI6MTc2Mjk0NDU5M30.UlHy3RU9W5LOid7smG7WzyNT7dnqhQT4qqzRrN1axmU", image: base64String, title: "Screen 1"});
|
||||||
|
// }
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
socketRef.current.on("appToCapture", async ({ appTitle }) => {
|
||||||
|
console.log("📸 Capture requested for:", appTitle);
|
||||||
|
|
||||||
|
const base64String = await window.electron.captureAppScreenShot(appTitle);
|
||||||
|
if (base64String && socketRef.current) {
|
||||||
|
socketRef.current.emit("sendImage", {
|
||||||
|
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY5MGIzMjhkMDkxMDFmNzRjZjUyNGMwNyIsImVtYWlsIjoiYmhhZ3dhbi5yQGhpY2dsb2JhbHNvbHV0aW9ucy5jb20iLCJuYW1lIjoiUm9oaXQiLCJpYXQiOjE3NjI4NTgxOTMsImV4cCI6MTc2Mjk0NDU5M30.UlHy3RU9W5LOid7smG7WzyNT7dnqhQT4qqzRrN1axmU",
|
||||||
|
image: base64String,
|
||||||
|
title: appTitle
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socketRef.current.on("disconnect", () => {
|
||||||
|
console.log("🔴 Disconnected");
|
||||||
|
setIsConnected(false);
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
intervalRef.current = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDisconnect = () => {
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
intervalRef.current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socketRef.current) {
|
||||||
|
socketRef.current.disconnect();
|
||||||
|
socketRef.current = null;
|
||||||
|
setIsConnected(false);
|
||||||
|
console.log("🔌 Disconnected manually");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{ label: "Dashboard", path: "/dashboard", icon: <Home size={18} />, exact: true },
|
{ label: "Dashboard", path: "/dashboard", icon: <Home size={18} />, exact: true },
|
||||||
|
|
@ -154,7 +232,6 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
const currentSessionTime = Math.floor((now - startTimestamp) / 1000);
|
const currentSessionTime = Math.floor((now - startTimestamp) / 1000);
|
||||||
const totalPausedTime = current.totalPausedTime || 0;
|
const totalPausedTime = current.totalPausedTime || 0;
|
||||||
|
|
||||||
// FIX: Add accumulated time from previous sessions
|
|
||||||
const calculatedElapsed =
|
const calculatedElapsed =
|
||||||
(current.accumulatedTime || 0) + currentSessionTime - totalPausedTime;
|
(current.accumulatedTime || 0) + currentSessionTime - totalPausedTime;
|
||||||
|
|
||||||
|
|
@ -276,7 +353,6 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
const current = updated.get(selectedProject.id);
|
const current = updated.get(selectedProject.id);
|
||||||
if (!current) return updated;
|
if (!current) return updated;
|
||||||
|
|
||||||
// FIX: Store current elapsed time as accumulated time
|
|
||||||
current.accumulatedTime = current.elapsedTime;
|
current.accumulatedTime = current.elapsedTime;
|
||||||
current.isTracking = false;
|
current.isTracking = false;
|
||||||
current.isPaused = false;
|
current.isPaused = false;
|
||||||
|
|
@ -359,6 +435,21 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<header className="w-full flex justify-between items-center h-12 px-6 bg-base-100 border-b border-base-300 sticky top-0 z-30">
|
<header className="w-full flex justify-between items-center h-12 px-6 bg-base-100 border-b border-base-300 sticky top-0 z-30">
|
||||||
{/* Left Section */}
|
{/* Left Section */}
|
||||||
|
{!isConnected ? (
|
||||||
|
<button
|
||||||
|
onClick={handleConnect}
|
||||||
|
className="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded"
|
||||||
|
>
|
||||||
|
Connect
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
onClick={handleDisconnect}
|
||||||
|
className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded"
|
||||||
|
>
|
||||||
|
Disconnect
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
{selectedProject ? (
|
{selectedProject ? (
|
||||||
isTracking ? (
|
isTracking ? (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useRef } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { Clock, TrendingUp, Play, Square, ProjectorIcon, Pause } from "lucide-react";
|
import { Clock, TrendingUp, Play, Square, ProjectorIcon, Pause } from "lucide-react";
|
||||||
import { useOutletContext } from "react-router-dom";
|
import { useOutletContext } from "react-router-dom";
|
||||||
|
|
||||||
|
|
@ -87,12 +87,33 @@ const Dashboard: React.FC = () => {
|
||||||
projectsData,
|
projectsData,
|
||||||
} = useOutletContext<TrackingState>();
|
} = useOutletContext<TrackingState>();
|
||||||
|
|
||||||
|
// interface AppsListInt {
|
||||||
|
// name: string;
|
||||||
|
// pid: string;
|
||||||
|
// title: string;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const [runningApps, setRunningApps] = useState<AppsListInt[]>([]);
|
||||||
|
|
||||||
const selectedData = selectedProject
|
const selectedData = selectedProject
|
||||||
? projectTrackingMap.get(selectedProject.id)
|
? projectTrackingMap.get(selectedProject.id)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|
||||||
|
// const getRunningApps = async () => {
|
||||||
|
// const res = await window.electron.getRunningApps()
|
||||||
|
// const appsList: AppsListInt[] = Array.isArray(res) ? res : [];
|
||||||
|
// setRunningApps(appsList)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// setInterval(() => {
|
||||||
|
// getRunningApps();
|
||||||
|
// }, 5000)
|
||||||
|
// }, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="flex-1 overflow-y-auto no-scrollbar">
|
<main className="flex-1 overflow-y-auto no-scrollbar">
|
||||||
|
|
@ -107,6 +128,32 @@ const Dashboard: React.FC = () => {
|
||||||
>
|
>
|
||||||
Screenshot Test
|
Screenshot Test
|
||||||
</button>
|
</button>
|
||||||
|
{/* {
|
||||||
|
runningApps && runningApps.map((obj) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={obj.pid}
|
||||||
|
onClick={async () => {
|
||||||
|
console.log("Call ", obj.name)
|
||||||
|
await window.electron.captureAppScreenShot(obj.name)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{obj.name}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} */}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Widgets */}
|
{/* Widgets */}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ interface Window {
|
||||||
getActiveAppDetails: () => {};
|
getActiveAppDetails: () => {};
|
||||||
toggleCloseBtn: (shouldEnable: boolean) => {},
|
toggleCloseBtn: (shouldEnable: boolean) => {},
|
||||||
resizeWindow: (width: number, height: number) => {},
|
resizeWindow: (width: number, height: number) => {},
|
||||||
|
getRunningApps: () => {},
|
||||||
|
captureAppScreenShot: (appTitle: string) => Promise<string>,
|
||||||
onWindowUpdate: (callback: (data: any) => void) => void;
|
onWindowUpdate: (callback: (data: any) => void) => void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue