diff --git a/backend/forge.config.ts b/backend/forge.config.ts index 77b92dc..93729e7 100644 --- a/backend/forge.config.ts +++ b/backend/forge.config.ts @@ -33,15 +33,15 @@ const config: ForgeConfig = { // Linux new MakerRpm({ - "options": { - "name": "quick-finder", - "genericName": "QuickFinder", + options: { + name: "quick-finder", + genericName: "QuickFinder" } }), new MakerDeb({ - "options": { - "name": "quick-finder", - "genericName": "QuickFinder", + options: { + name: "quick-finder", + genericName: "QuickFinder" } }) ], @@ -55,11 +55,19 @@ const config: ForgeConfig = { entryPoints: [ { name: "main_window", - html: "./src/out/index.html", + html: "./src/out/spotter.html", js: "./src/renderer.ts", preload: { js: "./src/preload.ts" } + }, + { + name: "overlay_window", + html: "./src/out/overlay.html", + js: "./src/windows/overlay/renderer.ts", + preload: { + js: "./src/windows/overlay/preload.ts" + } } ] } diff --git a/backend/package-lock.json b/backend/package-lock.json index f0f67d0..cac4828 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1,17 +1,16 @@ { "name": "quick-finder", - "version": "1.0.0", + "version": "0.0.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "quick-finder", - "version": "1.0.0", + "version": "0.0.8", "license": "MIT", "dependencies": { "@electron-forge/maker-dmg": "^7.6.0", "@expo/plist": "^0.2.0", - "electron-acrylic-window": "^0.5.11", "electron-squirrel-startup": "^1.0.1" }, "devDependencies": { @@ -1211,21 +1210,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@seorii/win32-displayconfig": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@seorii/win32-displayconfig/-/win32-displayconfig-0.1.1.tgz", - "integrity": "sha512-8sA/MVp2zq9+D8zwOMHH/JarUy7MMkmZ0wMew1Zbuv9ELXG6tH3or7WLoVVZGAd+evxkQVOITF+rlxpSjW9Uxg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^4.0.0", - "node-gyp": "^8.1.0" - }, - "engines": { - "node": ">=10.16 <11 || >= 11.8" - } - }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -2443,26 +2427,6 @@ "which": "bin/which" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2745,15 +2709,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -3373,15 +3328,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -3481,12 +3427,6 @@ "node": ">=0.8" } }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC" - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -4005,12 +3945,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4231,22 +4165,6 @@ "node": ">= 12.20.55" } }, - "node_modules/electron-acrylic-window": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/electron-acrylic-window/-/electron-acrylic-window-0.5.11.tgz", - "integrity": "sha512-M2fKzMoMhKBj2oFU4iyPWQiqK5NJVp/q2vjEdllTnPwNfAtJC52O3mLoKu3YDAuatx8Bd8Y5uG57s5oLprW1eg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@seorii/win32-displayconfig": "^0.1.1", - "bindings": "^1.5.0", - "node-addon-api": "^4.2.0", - "node-gyp": "^8.4.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/electron-installer-common": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/electron-installer-common/-/electron-installer-common-0.10.3.tgz", @@ -5734,12 +5652,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" - }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -6112,55 +6024,6 @@ "license": "MIT", "optional": true }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -6591,12 +6454,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC" - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -8546,12 +8403,6 @@ "dev": true, "license": "MIT" }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "license": "MIT" - }, "node_modules/node-api-version": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz", @@ -8592,221 +8443,6 @@ "node": ">= 6.13.0" } }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-gyp/node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/node-gyp/node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/node-gyp/node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "license": "MIT", - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/node-gyp/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "license": "MIT", - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/node-gyp/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/node-gyp/node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/node-gyp/node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "license": "ISC", - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/node-gyp/node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, "node_modules/node-loader": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-loader/-/node-loader-2.1.0.tgz", @@ -8905,22 +8541,6 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -10690,12 +10310,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -12597,44 +12211,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", diff --git a/backend/package.json b/backend/package.json index 8245db5..a9949d1 100644 --- a/backend/package.json +++ b/backend/package.json @@ -45,7 +45,6 @@ "dependencies": { "@electron-forge/maker-dmg": "^7.6.0", "@expo/plist": "^0.2.0", - "electron-acrylic-window": "^0.5.11", "electron-squirrel-startup": "^1.0.1" } } diff --git a/backend/src/index.ts b/backend/src/index.ts index d7964e5..aafcccd 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -1,5 +1,7 @@ import { app, BrowserWindow, globalShortcut, ipcMain } from "electron"; import ipc from "./ipc"; +import { createOverlayWindow } from "./windows/overlay"; +import { getFocusedDisplayBounds } from "./utils"; // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack // plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on @@ -42,6 +44,7 @@ const createSpotterWindow = (): void => { transparent: true, frame: false, resizable: false, + show: false, vibrancy: "fullscreen-ui", // on MacOS backgroundMaterial: "acrylic" // on Windows 11 }); @@ -60,7 +63,13 @@ const createSpotterWindow = (): void => { mainWindow.hide(); } function showMainWindow() { + const { x, y, width, height } = getFocusedDisplayBounds(); + const windowBounds = mainWindow.getBounds(); mainWindow.show(); + + const xOffset = Math.round((width - windowBounds.width) / 2); + const yOffset = Math.round((height - windowBounds.height) / 2); + mainWindow.setPosition(x + xOffset, y + yOffset); mainWindow.focus(); } @@ -89,8 +98,6 @@ ipcMain.handle("close-spotter", () => spotterWindow?.hide()); // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on("ready", () => { - createSpotterWindow(); - globalShortcut.register("CommandOrControl+Space", () => { if (!spotterWindow) { return createSpotterWindow(); @@ -102,6 +109,9 @@ app.on("ready", () => { spotterWindow.show(); } }); + + createSpotterWindow(); + createOverlayWindow(); }); app.on("activate", () => { diff --git a/backend/src/preload.ts b/backend/src/preload.ts index ab4e357..377f241 100644 --- a/backend/src/preload.ts +++ b/backend/src/preload.ts @@ -26,5 +26,9 @@ contextBridge.exposeInMainWorld("spotter", { }, quit: () => { return ipcRenderer.invoke("quit-app"); + }, + + launchConfetti: () => { + return ipcRenderer.invoke("launch-confetti"); } }); diff --git a/backend/src/utils.ts b/backend/src/utils.ts new file mode 100644 index 0000000..34355fe --- /dev/null +++ b/backend/src/utils.ts @@ -0,0 +1,12 @@ +import { screen } from "electron"; + +export function getFocusedDisplay() { + const point = screen.getCursorScreenPoint(); + return screen.getDisplayNearestPoint(point); +} + +export function getFocusedDisplayBounds() { + const display = getFocusedDisplay(); + const workArea = display.workArea; + return workArea; +} diff --git a/backend/src/windows/overlay/index.ts b/backend/src/windows/overlay/index.ts new file mode 100644 index 0000000..a8b7382 --- /dev/null +++ b/backend/src/windows/overlay/index.ts @@ -0,0 +1,77 @@ +import { app, BrowserWindow, ipcMain } from "electron"; +import { getFocusedDisplayBounds } from "../../utils"; + +declare const OVERLAY_WINDOW_WEBPACK_ENTRY: string; +declare const OVERLAY_WINDOW_PRELOAD_WEBPACK_ENTRY: string; + +type WindowType = { + window: BrowserWindow; + show: () => void; + hide: () => void; +}; +let overlayWindow: WindowType | null = null; + +export const createOverlayWindow = (): void => { + if (overlayWindow) { + overlayWindow.show(); + return; + } + + // Create the browser window. + const packaged = app.isPackaged; + const devMode = !packaged; + + const window = new BrowserWindow({ + height: 500, + width: 800, + webPreferences: { + preload: OVERLAY_WINDOW_PRELOAD_WEBPACK_ENTRY, + webSecurity: false, + devTools: devMode + }, + movable: true, + transparent: true, + frame: false, + resizable: false, + alwaysOnTop: true, + show: false + }); + + // Load the page + window.loadURL(OVERLAY_WINDOW_WEBPACK_ENTRY); + window.setIgnoreMouseEvents(true, { forward: true }); + window.maximize(); + + // Open the DevTools. + if (devMode) { + window.webContents.openDevTools({ + mode: "detach" + }); + } + + function hideOverlayWindow() { + window.hide(); + } + function showOverlayWindow() { + const bounds = getFocusedDisplayBounds(); + window.setBounds(bounds); + window.show(); + window.focus(); + } + + // Set shortcut + showOverlayWindow(); + + overlayWindow = { + window: window, + show: showOverlayWindow, + hide: hideOverlayWindow + }; +}; + +ipcMain.handle("launch-confetti", () => { + createOverlayWindow(); + if (overlayWindow) { + overlayWindow.window.webContents.send("launch-confetti"); + } +}); diff --git a/backend/src/windows/overlay/preload.ts b/backend/src/windows/overlay/preload.ts new file mode 100644 index 0000000..057db26 --- /dev/null +++ b/backend/src/windows/overlay/preload.ts @@ -0,0 +1,8 @@ +// See the Electron documentation for details on how to use preload scripts: +// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts + +import { contextBridge, ipcRenderer } from "electron"; + +contextBridge.exposeInMainWorld("overlay", { + onConfetti: (callback: () => void) => ipcRenderer.on("launch-confetti", () => callback()) +}); diff --git a/backend/src/windows/overlay/renderer.ts b/backend/src/windows/overlay/renderer.ts new file mode 100644 index 0000000..93252d4 --- /dev/null +++ b/backend/src/windows/overlay/renderer.ts @@ -0,0 +1,31 @@ +/** + * This file will automatically be loaded by webpack and run in the "renderer" context. + * To learn more about the differences between the "main" and the "renderer" context in + * Electron, visit: + * + * https://electronjs.org/docs/latest/tutorial/process-model + * + * By default, Node.js integration in this file is disabled. When enabling Node.js integration + * in a renderer process, please be aware of potential security implications. You can read + * more about security risks here: + * + * https://electronjs.org/docs/tutorial/security + * + * To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration` + * flag: + * + * ``` + * // Create the browser window. + * mainWindow = new BrowserWindow({ + * width: 800, + * height: 600, + * webPreferences: { + * nodeIntegration: true + * } + * }); + * ``` + */ + +console.log( + '👋 This message is being logged by "renderer.js", included via webpack' +); diff --git a/backend/webpack.renderer.config.ts b/backend/webpack.renderer.config.ts index ba982df..c1d647b 100644 --- a/backend/webpack.renderer.config.ts +++ b/backend/webpack.renderer.config.ts @@ -17,12 +17,29 @@ export const rendererConfig: Configuration = { plugins: [ new CopyPlugin({ patterns: [ + // main (dev) { from: "src/out", to: ".", globOptions: { ignore: ["**/index.html"] } + }, + // spotter window (prod) + { + from: "src/out", + to: "./main_window", + globOptions: { + ignore: ["**/index.html"] + } + }, + // overlay window (prod) + { + from: "src/out", + to: "./overlay_window", + globOptions: { + ignore: ["**/index.html"] + } } ], options: { diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 9e96f58..ae8ea2f 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,15 +1,4 @@ -import type { Metadata } from "next"; import "./globals.css"; -import { ThemeProvider } from "@/components/theme/theme-provider"; -import { RouterProvider } from "@/lib/stack-router"; -import SpotterError from "@/components/spotter/pages/error"; -import { TabRestricter } from "@/lib/tab-restricter"; -import { Themer } from "@/lib/themer"; - -export const metadata: Metadata = { - title: "QuickFinder", - description: "Generated by create next app" -}; export default function RootLayout({ children @@ -19,25 +8,7 @@ export default function RootLayout({ return ( - - - - - - {children} - - - - - + {children} ); - - /* https://ray.so/_next/static/media/bg-dark.3b248455.jpeg */ } diff --git a/frontend/app/overlay/page.tsx b/frontend/app/overlay/page.tsx new file mode 100644 index 0000000..08ba651 --- /dev/null +++ b/frontend/app/overlay/page.tsx @@ -0,0 +1,56 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import React, { useEffect } from "react"; +import { useReward } from "react-rewards"; + +const CONFETTI_LIFETIME = 200; +const CONFETTI_SIZE = 25; +const CONFETTI_START_VELOCITY = 20; +const CONFETTI_DECAY = 0.985; +const CONFETTI_SPREAD = 90; +const CONFETTI_AMOUNT = 150; + +export default function ConfettiPage() { + const { reward: rewardLeft } = useReward("rewardIdLeft", "confetti", { + angle: 45, + lifetime: CONFETTI_LIFETIME, + elementSize: CONFETTI_SIZE, + startVelocity: CONFETTI_START_VELOCITY, + spread: CONFETTI_SPREAD, + elementCount: CONFETTI_AMOUNT, + decay: CONFETTI_DECAY + }); + + const { reward: rewardRight } = useReward("rewardIdRight", "confetti", { + angle: 135, + lifetime: CONFETTI_LIFETIME, + elementSize: CONFETTI_SIZE, + startVelocity: CONFETTI_START_VELOCITY, + spread: CONFETTI_SPREAD, + elementCount: CONFETTI_AMOUNT, + decay: CONFETTI_DECAY + }); + + const launchConfetti = () => { + rewardLeft(); + rewardRight(); + }; + + useEffect(() => { + if (typeof overlay !== "undefined") { + overlay.onConfetti(launchConfetti); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + <> + {false && } +
+ + +
+ + ); +} diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 37a7078..4eeba8a 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,5 +1,12 @@ -import SpotterHome from "@/components/spotter/pages/home"; - export default function Home() { - return ; + return ( + <> +

Welcome!

+ You have reached the home page of QuickFinder. +
+ + Open Spotter + + + ); } diff --git a/frontend/app/spotter/layout.tsx b/frontend/app/spotter/layout.tsx new file mode 100644 index 0000000..71f2ba8 --- /dev/null +++ b/frontend/app/spotter/layout.tsx @@ -0,0 +1,34 @@ +import { ThemeProvider } from "@/components/theme/theme-provider"; +import { RouterProvider } from "@/lib/stack-router"; +import SpotterError from "@/components/spotter/pages/error"; +import { TabRestricter } from "@/lib/tab-restricter"; +import { Themer } from "@/lib/themer"; + +export default function RootLayout({ + children +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + + + + + + {children} + + + + + + + ); +} diff --git a/frontend/app/spotter/page.tsx b/frontend/app/spotter/page.tsx new file mode 100644 index 0000000..37a7078 --- /dev/null +++ b/frontend/app/spotter/page.tsx @@ -0,0 +1,5 @@ +import SpotterHome from "@/components/spotter/pages/home"; + +export default function Home() { + return ; +} diff --git a/frontend/bun.lockb b/frontend/bun.lockb index 54c8dd6..f05498f 100755 Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ diff --git a/frontend/components/spotter/types/others/spotter-global.ts b/frontend/components/spotter/types/others/globals.ts similarity index 81% rename from frontend/components/spotter/types/others/spotter-global.ts rename to frontend/components/spotter/types/others/globals.ts index f9483cd..2256528 100644 --- a/frontend/components/spotter/types/others/spotter-global.ts +++ b/frontend/components/spotter/types/others/globals.ts @@ -16,6 +16,12 @@ declare global { show: () => void; hide: () => void; quit: () => void; + + launchConfetti: () => void; + }; + + const overlay: { + onConfetti: (callback: () => void) => void; }; } diff --git a/frontend/extensions/applications/commands.tsx b/frontend/extensions/applications/commands.tsx index fe0768e..319b4c4 100644 --- a/frontend/extensions/applications/commands.tsx +++ b/frontend/extensions/applications/commands.tsx @@ -1,7 +1,7 @@ "use client"; import { SpotterCommand } from "@/components/spotter/types/others/commands"; -import { ApplicationItem } from "@/components/spotter/types/others/spotter-global"; +import { ApplicationItem } from "@/components/spotter/types/others/globals"; import { openApp } from "@/lib/utils"; import { useEffect, useMemo, useState } from "react"; diff --git a/frontend/extensions/main/commands.tsx b/frontend/extensions/main/commands.tsx index 381d1a4..db35059 100644 --- a/frontend/extensions/main/commands.tsx +++ b/frontend/extensions/main/commands.tsx @@ -1,8 +1,9 @@ "use client"; +import { ConfettiCommand } from "./confetti"; import { QuitApp } from "./quit-app"; -const initialCommands = [QuitApp]; +const initialCommands = [QuitApp, ConfettiCommand]; const commands = initialCommands.map((command) => { return { extensionId: "main", diff --git a/frontend/extensions/main/confetti.tsx b/frontend/extensions/main/confetti.tsx new file mode 100644 index 0000000..29d8ef3 --- /dev/null +++ b/frontend/extensions/main/confetti.tsx @@ -0,0 +1,14 @@ +import { SpotterCommand } from "@/components/spotter/types/others/commands"; +import { confetti } from "@/lib/utils"; + +async function execute() { + confetti(); +} + +export const ConfettiCommand: SpotterCommand = { + icon: "PartyPopper", + id: "Confetti", + title: "Confetti", + type: "Command", + execute +}; diff --git a/frontend/lib/stack-router.tsx b/frontend/lib/stack-router.tsx index b696e3c..f41fe27 100644 --- a/frontend/lib/stack-router.tsx +++ b/frontend/lib/stack-router.tsx @@ -137,9 +137,6 @@ export function RouterProvider({ children, config }: RouterProviderProps) { }), [push, pop, popToRoot, replace, popTo, stack, currentPage] ); - useEffect(() => { - console.log("stack", stack); - }, [stack]); function ErrorFallback({ error, resetErrorBoundary: resetter }: FallbackProps) { errorBoundaryResetter.current = resetter; diff --git a/frontend/lib/utils.ts b/frontend/lib/utils.ts index af28eeb..76160e6 100644 --- a/frontend/lib/utils.ts +++ b/frontend/lib/utils.ts @@ -35,3 +35,7 @@ export function openFileLocation(filePath: string) { export function quitApp() { return spotter.quit(); } + +export function confetti() { + return spotter.launchConfetti(); +} diff --git a/frontend/next.config.ts b/frontend/next.config.ts index 0a65f6f..fe6d113 100644 --- a/frontend/next.config.ts +++ b/frontend/next.config.ts @@ -1,7 +1,8 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - assetPrefix: "../", + assetPrefix: ".", + output: "export", images: { unoptimized: true diff --git a/frontend/package.json b/frontend/package.json index 011cb58..7921c68 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,6 +28,7 @@ "react-dom": "19.0.0-rc-66855b96-20241106", "react-error-boundary": "^4.1.2", "react-markdown": "^9.0.1", + "react-rewards": "^2.0.4", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7" },