Compare commits
9 Commits
8eb2d69e13
...
master
Author | SHA1 | Date | |
---|---|---|---|
a59424171d | |||
97caf4b30e | |||
55c8b628ca | |||
1e858021be | |||
bb1d9f71a8 | |||
95d8d9a58f | |||
e63f351f63 | |||
db394ea201 | |||
9831046592 |
6
.gitignore
vendored
6
.gitignore
vendored
@ -92,4 +92,8 @@ typings/
|
|||||||
out/
|
out/
|
||||||
|
|
||||||
# WebStorm
|
# WebStorm
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# Data Directory
|
||||||
|
data/
|
||||||
|
*.test
|
@ -1,3 +1,5 @@
|
|||||||
# Smart-Monopoly
|
# Smart-Monopoly
|
||||||
|
|
||||||
Siehe [Wiki](https://git.gaminggeneration.de/TobiasH/smart-monopoly/wiki/?action=_pages)
|
Siehe [Wiki](https://git.gaminggeneration.de/TobiasH/smart-monopoly/wiki/?action=_pages)
|
||||||
|
|
||||||
|
System um das Papiergeld obsolet zu machen und einige Dinge zu vereinfachen!
|
@ -20,7 +20,13 @@ const config: ForgeConfig = {
|
|||||||
new MakerSquirrel({}),
|
new MakerSquirrel({}),
|
||||||
new MakerZIP({}, ['darwin']),
|
new MakerZIP({}, ['darwin']),
|
||||||
new MakerRpm({}),
|
new MakerRpm({}),
|
||||||
new MakerDeb({})],
|
new MakerDeb({
|
||||||
|
options: {
|
||||||
|
depends: [
|
||||||
|
"libpcsclite1", "libpcsclite-dev", "pcscd"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})],
|
||||||
plugins: [
|
plugins: [
|
||||||
new AutoUnpackNativesPlugin({}),
|
new AutoUnpackNativesPlugin({}),
|
||||||
new WebpackPlugin({
|
new WebpackPlugin({
|
||||||
|
188
package-lock.json
generated
188
package-lock.json
generated
@ -14,10 +14,12 @@
|
|||||||
"@fontsource/roboto": "^5.0.12",
|
"@fontsource/roboto": "^5.0.12",
|
||||||
"@mui/icons-material": "^5.15.14",
|
"@mui/icons-material": "^5.15.14",
|
||||||
"@mui/material": "^5.15.14",
|
"@mui/material": "^5.15.14",
|
||||||
|
"@types/websocket": "^1.0.10",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-squirrel-startup": "^1.0.0",
|
||||||
"node-wifi-scanner": "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner",
|
"node-wifi-scanner": "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0",
|
||||||
|
"websocket": "^1.0.34"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-forge/cli": "^7.3.1",
|
"@electron-forge/cli": "^7.3.1",
|
||||||
@ -1953,7 +1955,6 @@
|
|||||||
"version": "20.11.30",
|
"version": "20.11.30",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
|
||||||
"integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
|
"integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~5.26.4"
|
||||||
@ -2100,6 +2101,14 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/websocket": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-svjGZvPB7EzuYS94cI7a+qhwgGU1y89wUgjT6E2wVUfmAGIvRfT7obBvRtnhXCSsoMdlG4gBFGE7MfkIXZLoww==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.10",
|
"version": "8.5.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||||
@ -3212,6 +3221,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/bufferutil": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@ -3969,6 +3990,18 @@
|
|||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/d": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
|
||||||
|
"dependencies": {
|
||||||
|
"es5-ext": "^0.10.64",
|
||||||
|
"type": "^2.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/data-view-buffer": {
|
"node_modules/data-view-buffer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
|
||||||
@ -4873,6 +4906,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es5-ext": {
|
||||||
|
"version": "0.10.64",
|
||||||
|
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
|
||||||
|
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"es6-iterator": "^2.0.3",
|
||||||
|
"es6-symbol": "^3.1.3",
|
||||||
|
"esniff": "^2.0.1",
|
||||||
|
"next-tick": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es6-error": {
|
"node_modules/es6-error": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
|
||||||
@ -4881,6 +4929,28 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/es6-iterator": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
|
||||||
|
"dependencies": {
|
||||||
|
"d": "1",
|
||||||
|
"es5-ext": "^0.10.35",
|
||||||
|
"es6-symbol": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es6-symbol": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
|
||||||
|
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
|
||||||
|
"dependencies": {
|
||||||
|
"d": "^1.0.2",
|
||||||
|
"ext": "^1.7.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escalade": {
|
"node_modules/escalade": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||||
@ -5158,6 +5228,20 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/esniff": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
|
||||||
|
"dependencies": {
|
||||||
|
"d": "^1.0.1",
|
||||||
|
"es5-ext": "^0.10.62",
|
||||||
|
"event-emitter": "^0.3.5",
|
||||||
|
"type": "^2.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
"version": "9.6.1",
|
"version": "9.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
||||||
@ -5232,6 +5316,15 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/event-emitter": {
|
||||||
|
"version": "0.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||||
|
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
|
||||||
|
"dependencies": {
|
||||||
|
"d": "1",
|
||||||
|
"es5-ext": "~0.10.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eventemitter3": {
|
"node_modules/eventemitter3": {
|
||||||
"version": "4.0.7",
|
"version": "4.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||||
@ -5462,6 +5555,14 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/ext": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
|
||||||
|
"dependencies": {
|
||||||
|
"type": "^2.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/extract-zip": {
|
"node_modules/extract-zip": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
||||||
@ -7200,6 +7301,11 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-typedarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
|
||||||
|
},
|
||||||
"node_modules/is-unicode-supported": {
|
"node_modules/is-unicode-supported": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||||
@ -8180,6 +8286,11 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/next-tick": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
|
||||||
|
},
|
||||||
"node_modules/nice-try": {
|
"node_modules/nice-try": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||||
@ -8285,6 +8396,16 @@
|
|||||||
"node": "^12.13 || ^14.13 || >=16"
|
"node": "^12.13 || ^14.13 || >=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-gyp-build": {
|
||||||
|
"version": "4.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
|
||||||
|
"integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==",
|
||||||
|
"bin": {
|
||||||
|
"node-gyp-build": "bin.js",
|
||||||
|
"node-gyp-build-optional": "optional.js",
|
||||||
|
"node-gyp-build-test": "build-test.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-loader": {
|
"node_modules/node-loader": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-loader/-/node-loader-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-loader/-/node-loader-2.0.0.tgz",
|
||||||
@ -11069,6 +11190,11 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/type": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@ -11186,6 +11312,14 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typedarray-to-buffer": {
|
||||||
|
"version": "3.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||||
|
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-typedarray": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.5.5",
|
"version": "4.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
|
||||||
@ -11220,7 +11354,6 @@
|
|||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unique-filename": {
|
"node_modules/unique-filename": {
|
||||||
@ -11324,6 +11457,18 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/utf-8-validate": {
|
||||||
|
"version": "5.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||||
|
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@ -11734,6 +11879,22 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/websocket": {
|
||||||
|
"version": "1.0.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
|
||||||
|
"integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"debug": "^2.2.0",
|
||||||
|
"es5-ext": "^0.10.50",
|
||||||
|
"typedarray-to-buffer": "^3.1.5",
|
||||||
|
"utf-8-validate": "^5.0.2",
|
||||||
|
"yaeti": "^0.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/websocket-driver": {
|
"node_modules/websocket-driver": {
|
||||||
"version": "0.7.4",
|
"version": "0.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
|
||||||
@ -11759,6 +11920,19 @@
|
|||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/websocket/node_modules/debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/websocket/node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
|
},
|
||||||
"node_modules/whatwg-url": {
|
"node_modules/whatwg-url": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
@ -11934,6 +12108,14 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/yaeti": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.32"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
@ -49,9 +49,12 @@
|
|||||||
"@fontsource/roboto": "^5.0.12",
|
"@fontsource/roboto": "^5.0.12",
|
||||||
"@mui/icons-material": "^5.15.14",
|
"@mui/icons-material": "^5.15.14",
|
||||||
"@mui/material": "^5.15.14",
|
"@mui/material": "^5.15.14",
|
||||||
|
"@types/websocket": "^1.0.10",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-squirrel-startup": "^1.0.0",
|
||||||
|
"nfc-pcsc": "^0.8.1",
|
||||||
"node-wifi-scanner": "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner",
|
"node-wifi-scanner": "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0",
|
||||||
|
"websocket": "^1.0.34"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
scripts/addWifi.sh
Normal file → Executable file
8
scripts/addWifi.sh
Normal file → Executable file
@ -31,15 +31,21 @@ update_config=1
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Validate arguments
|
# Validate arguments
|
||||||
if [ -z "$ssid" ] || [ -z "$psk" ]; then
|
if [ -z "$ssid" ]; then
|
||||||
echo "invalid-args"
|
echo "invalid-args"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
key="WPA-PSK"
|
||||||
|
if [ -z "$psk" ]; then
|
||||||
|
key="NONE"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
network={
|
network={
|
||||||
ssid=\"$ssid\"
|
ssid=\"$ssid\"
|
||||||
psk=\"$psk\"
|
psk=\"$psk\"
|
||||||
|
key_mgmt=\"$key\"
|
||||||
}
|
}
|
||||||
" | sudo tee -a "$file" >/dev/null
|
" | sudo tee -a "$file" >/dev/null
|
||||||
|
|
||||||
|
89
scripts/connectToWifi.sh
Normal file → Executable file
89
scripts/connectToWifi.sh
Normal file → Executable file
@ -3,84 +3,6 @@
|
|||||||
iface=$(iw dev | awk '$1=="Interface"{print $2}' | grep '^wlan')
|
iface=$(iw dev | awk '$1=="Interface"{print $2}' | grep '^wlan')
|
||||||
file="/etc/wpa_supplicant/wpa_supplicant-monopoly.conf"
|
file="/etc/wpa_supplicant/wpa_supplicant-monopoly.conf"
|
||||||
|
|
||||||
ssid="no_args_given"
|
|
||||||
|
|
||||||
# Parse arguments
|
|
||||||
while getopts ":s:p:" opt; do
|
|
||||||
case ${opt} in
|
|
||||||
s )
|
|
||||||
ssid="$OPTARG"
|
|
||||||
;;
|
|
||||||
: )
|
|
||||||
echo "Invalid option: $OPTARG" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND -1))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Remove all disabled
|
|
||||||
sudo sed -i '/disabled=1/d' "$file"
|
|
||||||
|
|
||||||
# Temporary file to store modified content
|
|
||||||
temp_file=$(mktemp)
|
|
||||||
|
|
||||||
# Use awk to add disabled=1 within each network block
|
|
||||||
awk '
|
|
||||||
BEGIN { RS="\n\n"; FS="\n"; OFS="\n" }
|
|
||||||
{
|
|
||||||
found=0
|
|
||||||
for(i=1; i<=NF; i++) {
|
|
||||||
if ($i ~ /^network=/) {
|
|
||||||
for(j=i+1; j<=NF && $j !~ /^}/; j++) {
|
|
||||||
if ($j ~ /^disabled=1/) {
|
|
||||||
found=1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
$i = $i "\n disabled=1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print $0 "\n"
|
|
||||||
}' "$file" > "$temp_file"
|
|
||||||
|
|
||||||
# Overwrite the original file with the modified content
|
|
||||||
sudo mv -f "$temp_file" "$file"
|
|
||||||
|
|
||||||
|
|
||||||
temp_file=$(mktemp)
|
|
||||||
|
|
||||||
while IFS= read -r line
|
|
||||||
do
|
|
||||||
if [[ "$line" == *"$ssid"* ]]; then
|
|
||||||
echo $line $ssid
|
|
||||||
remove_line=1
|
|
||||||
echo "remove_line=1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$remove_line" -eq 1 && "$line" == *"disabled=1"* ]]; then
|
|
||||||
echo "skipped disabled line"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$line" == *"}"* ]]; then
|
|
||||||
in_block=0
|
|
||||||
remove_line=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$line" >> "$temp_file"
|
|
||||||
done < "$file"
|
|
||||||
|
|
||||||
# Overwrite the original file with the modified content
|
|
||||||
sudo mv -f "$temp_file" "$file"
|
|
||||||
|
|
||||||
cat $file
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
|
|
||||||
sudo ip addr flush dev $iface
|
sudo ip addr flush dev $iface
|
||||||
sudo killall wpa_supplicant
|
sudo killall wpa_supplicant
|
||||||
@ -88,11 +10,12 @@ sudo truncate -s 0 /tmp/wifi_connection_status.txt
|
|||||||
sudo wpa_supplicant -B -i $iface -f /tmp/wifi_connection_status.txt -c $file
|
sudo wpa_supplicant -B -i $iface -f /tmp/wifi_connection_status.txt -c $file
|
||||||
|
|
||||||
declare -i i=0
|
declare -i i=0
|
||||||
declare -i timeout=5
|
declare -i timeout=8
|
||||||
while [ $i -le $timeout ]; do
|
while [ $i -le $timeout ]; do
|
||||||
if grep -iq 'CTRL-EVENT-CONNECTED' /tmp/wifi_connection_status.txt; then
|
if grep -iq 'CTRL-EVENT-CONNECTED' /tmp/wifi_connection_status.txt; then
|
||||||
sudo dhclient wlan0
|
sudo dhclient $iface
|
||||||
exit 2
|
echo "!!ok"
|
||||||
|
exit 0
|
||||||
elif grep -iq '4-Way Handshake failed' /tmp/wifi_connection_status.txt; then
|
elif grep -iq '4-Way Handshake failed' /tmp/wifi_connection_status.txt; then
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
@ -100,5 +23,5 @@ while [ $i -le $timeout ]; do
|
|||||||
(( i++ ))
|
(( i++ ))
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
echo "!!nok"
|
||||||
exit 0
|
exit -1
|
36
src/CloudHandler.ts
Normal file
36
src/CloudHandler.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import {w3cwebsocket, IMessageEvent} from "websocket";
|
||||||
|
|
||||||
|
export default class CloudHandler {
|
||||||
|
|
||||||
|
|
||||||
|
private static connection: w3cwebsocket;
|
||||||
|
|
||||||
|
static connect() {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
this.connection = new w3cwebsocket('wss://smartmonopoly.iif.li');
|
||||||
|
this.connection.onerror = (err: Error) => {
|
||||||
|
this.connection = null;
|
||||||
|
reject(err);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.connection.onopen = () => {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.connection.onclose = () => {
|
||||||
|
this.connection = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.connection.onmessage = (e) => this.handleMessage(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static handleMessage(e: IMessageEvent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static isConnected(): boolean {
|
||||||
|
return !!this.connection;
|
||||||
|
}
|
||||||
|
}
|
66
src/ConfigHandler.ts
Normal file
66
src/ConfigHandler.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import path from "path";
|
||||||
|
import process from "process";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import {Config, GameRules} from "./RawConstants";
|
||||||
|
import {app} from "electron";
|
||||||
|
|
||||||
|
|
||||||
|
export class ConfigHandler {
|
||||||
|
private static dataPath = path.resolve(app.getPath('userData'), "config");
|
||||||
|
private static confPath = path.resolve(this.dataPath, "config.json");
|
||||||
|
|
||||||
|
private static defaultConfig = {
|
||||||
|
rules: {
|
||||||
|
switchValues: {},
|
||||||
|
inputValues: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static generateDefault() {
|
||||||
|
fs.writeFileSync(this.confPath, JSON.stringify(this.defaultConfig, null, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static get() {
|
||||||
|
this.existsOrGenerate();
|
||||||
|
|
||||||
|
let confRaw = fs.readFileSync(this.confPath).toString('utf8');
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSON.parse(confRaw);
|
||||||
|
} catch (e) {
|
||||||
|
this.generateDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Config retrieved!")
|
||||||
|
return JSON.parse(confRaw) as Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
static existsOrGenerate() {
|
||||||
|
if (!fs.existsSync(this.dataPath))
|
||||||
|
fs.mkdirSync(this.dataPath);
|
||||||
|
|
||||||
|
if (!fs.existsSync(this.confPath))
|
||||||
|
this.generateDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
static set(conf: Config) {
|
||||||
|
this.existsOrGenerate();
|
||||||
|
|
||||||
|
let confRaw = fs.readFileSync(this.confPath).toString('utf8');
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSON.parse(confRaw);
|
||||||
|
} catch (e) {
|
||||||
|
this.generateDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let current = JSON.parse(confRaw) as Config;
|
||||||
|
current = {...current, ...conf};
|
||||||
|
console.log("Config saved to " + this.confPath);
|
||||||
|
fs.writeFileSync(this.confPath, JSON.stringify(current, null, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,34 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
export type IPCChannel =
|
|
||||||
'WIFI_STATUS'
|
|
||||||
| 'WIFI_SCAN'
|
|
||||||
| 'WIFI_LIST'
|
|
||||||
| 'WIFI_CONNECT'
|
|
||||||
| 'FUNCTION_TEST'
|
|
||||||
| 'CLOUD_STATUS'
|
|
||||||
| 'CLOUD_CONNECT'
|
|
||||||
|
|
||||||
|
|
||||||
export interface IPCAnswer {
|
|
||||||
status: boolean,
|
|
||||||
data?: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPCRequest {
|
|
||||||
data?: any,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WiFiNetwork {
|
|
||||||
ssid: string,
|
|
||||||
isSecured: boolean,
|
|
||||||
isKnown?: boolean,
|
|
||||||
psk?: string,
|
|
||||||
rssi?: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FunctionTest {
|
|
||||||
hasSudo: boolean,
|
|
||||||
hasWPASupplicant: boolean,
|
|
||||||
hasInternet: boolean
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import { ipcMain } from 'electron';
|
|
||||||
import IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
|
|
||||||
import {IPCAnswer, IPCChannel, IPCRequest} from "./IPCConstants";
|
|
||||||
|
|
||||||
|
|
||||||
export const IPCHandler = (
|
|
||||||
channel: IPCChannel,
|
|
||||||
listener: (
|
|
||||||
event: IpcMainInvokeEvent,
|
|
||||||
request: IPCRequest,
|
|
||||||
...args: any[]
|
|
||||||
) => Promise<IPCAnswer> | IPCAnswer
|
|
||||||
): void => {
|
|
||||||
ipcMain.handle(channel, listener);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
25
src/IPCMainHandler.ts
Normal file
25
src/IPCMainHandler.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ipcMain } from 'electron';
|
||||||
|
import IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
|
||||||
|
import {IPCAnswer, IPCChannel, IPCListenChannels, IPCRequest} from "./RawConstants";
|
||||||
|
|
||||||
|
|
||||||
|
export const IPCHandle = (
|
||||||
|
channel: IPCChannel,
|
||||||
|
listener: (
|
||||||
|
event: IpcMainInvokeEvent,
|
||||||
|
request: IPCRequest,
|
||||||
|
...args: any[]
|
||||||
|
) => Promise<IPCAnswer> | IPCAnswer
|
||||||
|
): void => {
|
||||||
|
ipcMain.handle(channel, listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IPCSend = (
|
||||||
|
channel: IPCListenChannels,
|
||||||
|
message: IPCAnswer,
|
||||||
|
...args: any
|
||||||
|
): void => {
|
||||||
|
console.log("Sending ", message, " to " + channel);
|
||||||
|
|
||||||
|
global.mainWebContents.send(channel, message, ...args);
|
||||||
|
};
|
236
src/NFCHandler.ts
Normal file
236
src/NFCHandler.ts
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
import {NFC} from "nfc-pcsc";
|
||||||
|
import {IPCSend} from "./IPCMainHandler";
|
||||||
|
import {
|
||||||
|
IPCListenChannels,
|
||||||
|
NFCAccountCard,
|
||||||
|
NFCCard,
|
||||||
|
NFCCardType,
|
||||||
|
NFCPropertyCard,
|
||||||
|
NFCTaskCard,
|
||||||
|
PropertyColor, TaskType
|
||||||
|
} from "./RawConstants";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
|
||||||
|
export default class NFCHandler {
|
||||||
|
public static initPCSC() {
|
||||||
|
const nfc = new NFC(); // optionally you can pass logger
|
||||||
|
|
||||||
|
nfc.on('reader', reader => {
|
||||||
|
|
||||||
|
console.log(`${reader.name} device attached`);
|
||||||
|
|
||||||
|
// enable when you want to auto-process ISO 14443-4 tags (standard=TAG_ISO_14443_4)
|
||||||
|
// when an ISO 14443-4 is detected, SELECT FILE command with the AID is issued
|
||||||
|
// the response is available as card.data in the card event
|
||||||
|
// see examples/basic.js line 17 for more info
|
||||||
|
// reader.aid = 'F222222222';
|
||||||
|
|
||||||
|
reader.on('card', card => {
|
||||||
|
// card is object containing following data
|
||||||
|
// [always] String type: TAG_ISO_14443_3 (standard nfc tags like MIFARE) or TAG_ISO_14443_4 (Android HCE and others)
|
||||||
|
// [always] String standard: same as type
|
||||||
|
// [only TAG_ISO_14443_3] String uid: tag uid
|
||||||
|
// [only TAG_ISO_14443_4] Buffer data: raw data from select APDU response
|
||||||
|
|
||||||
|
console.log(`${reader.name} card detected`, card);
|
||||||
|
|
||||||
|
let parsed = this.formClass(card.uid, card.data.toString("utf8"));
|
||||||
|
if (parsed && parsed.isComplete)
|
||||||
|
IPCSend(IPCListenChannels.NFC_CARD, {status: true, data: parsed.card});
|
||||||
|
|
||||||
|
IPCSend(IPCListenChannels.NFC_RAW, {status: !!parsed, data: parsed});
|
||||||
|
});
|
||||||
|
|
||||||
|
reader.on('card.off', card => {
|
||||||
|
console.log(`${reader.name} card removed`, card);
|
||||||
|
});
|
||||||
|
|
||||||
|
reader.on('error', err => {
|
||||||
|
console.log(`${reader.name} an error occurred`, err);
|
||||||
|
});
|
||||||
|
|
||||||
|
reader.on('end', () => {
|
||||||
|
console.log(`${reader.name} device removed`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
nfc.on('error', err => {
|
||||||
|
console.log('an error occurred', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static initTest() {
|
||||||
|
fs.watchFile(path.resolve(process.cwd(), "nfc.test"), (curr, prev) => {
|
||||||
|
let contents = fs.readFileSync(path.resolve(process.cwd(), "nfc.test")).toString("utf-8");
|
||||||
|
let parsed = this.formClass("xyz", contents);
|
||||||
|
if (parsed.isComplete)
|
||||||
|
IPCSend(IPCListenChannels.NFC_CARD, {status: true, data: parsed.card});
|
||||||
|
|
||||||
|
IPCSend(IPCListenChannels.NFC_RAW, {status: parsed.isComplete, data: parsed.card});
|
||||||
|
|
||||||
|
console.log("Got NFC", parsed);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns formed nfc card or null if nothing can be parsed
|
||||||
|
* @param uid
|
||||||
|
* @param raw
|
||||||
|
*/
|
||||||
|
public static formClass(uid: string, raw: string): formClassReturn | null {
|
||||||
|
raw = Buffer.from(raw, "base64").toString("utf-8");
|
||||||
|
|
||||||
|
/*
|
||||||
|
NFC-Card FULL
|
||||||
|
|
||||||
|
CARD_TYPE|PROPERTIES
|
||||||
|
|
||||||
|
- ACCOUNT
|
||||||
|
- PROPERTY
|
||||||
|
- TASK
|
||||||
|
*/
|
||||||
|
let preParsed: NFCCard = {
|
||||||
|
uid: uid,
|
||||||
|
raw: raw,
|
||||||
|
cardType: NFCCardType.INVALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
let parsing = raw.split("|");
|
||||||
|
switch (parsing[0]) {
|
||||||
|
case "PROPERTY": {
|
||||||
|
preParsed.cardType = NFCCardType.PROPERTY;
|
||||||
|
const splitProperty = parsing[1].split(";");
|
||||||
|
/*
|
||||||
|
0 Name
|
||||||
|
1 Color
|
||||||
|
2 Fullset Amount
|
||||||
|
3 Buy Value
|
||||||
|
4 Mortgage Value
|
||||||
|
5 Rent Object (split with ,)
|
||||||
|
0 Basic rent
|
||||||
|
[1 Rent with 1 house
|
||||||
|
2 Rent with 2 houses
|
||||||
|
3 Rent with 3 houses
|
||||||
|
4 Rent with 4 houses
|
||||||
|
5 Rent with 1 hotel]
|
||||||
|
6 Special Props
|
||||||
|
""
|
||||||
|
"TRAINSTATION"
|
||||||
|
"UTILITY"
|
||||||
|
*/
|
||||||
|
let name = this.valueOr(splitProperty, 0, "");
|
||||||
|
let color = this.valueOr(splitProperty, 1, PropertyColor.WHITE);
|
||||||
|
let fullSetAmount = this.valueOr(splitProperty, 2, 0);
|
||||||
|
let buyValue = this.valueOr(splitProperty, 3, 0);
|
||||||
|
let mortgageValue = this.valueOr(splitProperty, 4, 0);
|
||||||
|
|
||||||
|
let rent = 0;
|
||||||
|
let rent1 = 0;
|
||||||
|
let rent2 = 0;
|
||||||
|
let rent3 = 0;
|
||||||
|
let rent4 = 0;
|
||||||
|
let rentHotel = 0;
|
||||||
|
if (splitProperty[5]) {
|
||||||
|
let rentSplit = splitProperty[5].split(",");
|
||||||
|
rent = this.valueOr(rentSplit, 0, 0);
|
||||||
|
rent1 = this.valueOr(rentSplit, 1, undefined);
|
||||||
|
rent2 = this.valueOr(rentSplit, 2, undefined);
|
||||||
|
rent3 = this.valueOr(rentSplit, 3, undefined);
|
||||||
|
rent4 = this.valueOr(rentSplit, 4, undefined);
|
||||||
|
rentHotel = this.valueOr(rentSplit, 5, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
let specialProperties = this.valueOr(splitProperty, 6, "");
|
||||||
|
|
||||||
|
let propertyParsed: NFCPropertyCard = {
|
||||||
|
...preParsed,
|
||||||
|
name: name,
|
||||||
|
color: color,
|
||||||
|
fullSetAmount: fullSetAmount,
|
||||||
|
buyValue: buyValue,
|
||||||
|
mortgageValue: mortgageValue,
|
||||||
|
rent: rent,
|
||||||
|
rent1: rent1,
|
||||||
|
rent2: rent2,
|
||||||
|
rent3: rent3,
|
||||||
|
rent4: rent4,
|
||||||
|
rentHotel: rentHotel,
|
||||||
|
specialProperties: specialProperties,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (splitProperty.length != 7)
|
||||||
|
return {card: propertyParsed, isComplete: false};
|
||||||
|
|
||||||
|
return {card: propertyParsed, isComplete: true};
|
||||||
|
}
|
||||||
|
|
||||||
|
case "ACCOUNT": {
|
||||||
|
preParsed.cardType = NFCCardType.ACCOUNT;
|
||||||
|
const splitAccount = parsing[1].split(";");
|
||||||
|
let symbol = this.valueOr(splitAccount, 0, "");
|
||||||
|
let nickname = this.valueOr(splitAccount, 1, "");
|
||||||
|
let pin = this.valueOr(splitAccount, 2, 0);
|
||||||
|
|
||||||
|
const splitParsed: NFCAccountCard = {
|
||||||
|
...preParsed,
|
||||||
|
symbol: symbol,
|
||||||
|
nickname: nickname,
|
||||||
|
pin: Number.parseInt(pin)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitAccount.length != 3)
|
||||||
|
return {card: splitParsed, isComplete: false};
|
||||||
|
return {card: splitParsed, isComplete: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "TASK": {
|
||||||
|
preParsed.cardType = NFCCardType.ACCOUNT;
|
||||||
|
const splitTask = parsing[1].split(";");
|
||||||
|
let taskType = this.valueOr(splitTask, 0, "");
|
||||||
|
let taskAmount1 = this.valueOr(splitTask, 1, 0);
|
||||||
|
let taskAmount2 = this.valueOr(splitTask, 2, 0);
|
||||||
|
|
||||||
|
const splitParsed: NFCTaskCard = {
|
||||||
|
...preParsed,
|
||||||
|
type: taskType as TaskType,
|
||||||
|
amount: Number.parseInt(taskAmount1) || 0,
|
||||||
|
amount2: Number.parseInt(taskAmount2) || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitTask.length < 1 || splitTask.length > 3)
|
||||||
|
return {card: splitParsed, isComplete: false};
|
||||||
|
|
||||||
|
return {card: splitParsed, isComplete: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return {card: preParsed, isComplete: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static valueOr(arr: string[], index: number, def: any) {
|
||||||
|
try {
|
||||||
|
if (arr[index])
|
||||||
|
return arr[index];
|
||||||
|
return def;
|
||||||
|
} catch (e) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface formClassReturn {
|
||||||
|
card: NFCCard;
|
||||||
|
isComplete: boolean;
|
||||||
|
}
|
128
src/OSHandler.ts
128
src/OSHandler.ts
@ -1,17 +1,24 @@
|
|||||||
import {WiFiNetwork} from "./IPCConstants";
|
import {WiFiNetwork} from "./RawConstants";
|
||||||
import {spawn, exec} from 'node:child_process';
|
import {spawn, exec} from 'node:child_process';
|
||||||
import * as dns from "dns";
|
import * as dns from "dns";
|
||||||
import * as process from "process";
|
import * as process from "process";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
const wifiScan = require("node-wifi-scanner");
|
const wifiScan = require("node-wifi-scanner");
|
||||||
|
|
||||||
|
|
||||||
export default class OSHandler {
|
export default class OSHandler {
|
||||||
|
static scriptPath = path.resolve(process.cwd(), "scripts");
|
||||||
|
|
||||||
|
static async enableAllWifis() {
|
||||||
|
return this.overwriteWifis(await this.getKnownWifis());
|
||||||
|
}
|
||||||
|
|
||||||
static getKnownWifis(): Promise<WiFiNetwork[]> {
|
static getKnownWifis(): Promise<WiFiNetwork[]> {
|
||||||
return new Promise<WiFiNetwork[]>((resolve, reject) => {
|
return new Promise<WiFiNetwork[]>((resolve, reject) => {
|
||||||
exec("sudo touch /etc/wpa_supplicant/wpa_supplicant-monopoly.conf && sudo cat /etc/wpa_supplicant/wpa_supplicant-monopoly.conf", (err, stdout) => {
|
exec("sudo touch /etc/wpa_supplicant/wpa_supplicant-monopoly.conf && sudo cat /etc/wpa_supplicant/wpa_supplicant-monopoly.conf", (err, stdout) => {
|
||||||
if(err)
|
if (err)
|
||||||
return reject(err);
|
return reject(err);
|
||||||
|
|
||||||
let lines = stdout.split("\n");
|
let lines = stdout.split("\n");
|
||||||
@ -20,25 +27,26 @@ export default class OSHandler {
|
|||||||
|
|
||||||
let inBlock = false;
|
let inBlock = false;
|
||||||
let currentNetwork: WiFiNetwork = {ssid: "", psk: "", isSecured: false};
|
let currentNetwork: WiFiNetwork = {ssid: "", psk: "", isSecured: false};
|
||||||
for(let line of lines)
|
for (let line of lines) {
|
||||||
{
|
if (line.includes("network={"))
|
||||||
if(line.includes("network={"))
|
|
||||||
inBlock = true;
|
inBlock = true;
|
||||||
|
|
||||||
if(line.includes("}")) {
|
if (line.includes("}")) {
|
||||||
inBlock = false;
|
inBlock = false;
|
||||||
currentNetwork.isSecured = !!currentNetwork.psk;
|
//currentNetwork.isSecured = !!currentNetwork.psk;
|
||||||
if(currentNetwork.ssid)
|
if (currentNetwork.ssid)
|
||||||
wifis.push(currentNetwork);
|
wifis.push({...currentNetwork});
|
||||||
currentNetwork.ssid = "";
|
currentNetwork.ssid = "";
|
||||||
currentNetwork.psk = "";
|
currentNetwork.psk = "";
|
||||||
currentNetwork.isSecured = false;
|
currentNetwork.isSecured = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inBlock && line.includes("ssid"))
|
if (inBlock && line.includes("ssid"))
|
||||||
currentNetwork.ssid = line.substring(line.indexOf('"')+1, line.lastIndexOf('"'));
|
currentNetwork.ssid = line.substring(line.indexOf('"') + 1, line.lastIndexOf('"'));
|
||||||
if(inBlock && line.includes("psk"))
|
if (inBlock && line.includes("psk"))
|
||||||
currentNetwork.psk = line.substring(line.indexOf('"')+1, line.lastIndexOf('"'));
|
currentNetwork.psk = line.substring(line.indexOf('"') + 1, line.lastIndexOf('"'));
|
||||||
|
if (inBlock && line.includes("key_mgmt"))
|
||||||
|
currentNetwork.isSecured = line.includes("WPA-PSK");
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(wifis);
|
resolve(wifis);
|
||||||
@ -46,32 +54,91 @@ export default class OSHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static addWifi(wifi: string, passkey: string | null) {
|
/**
|
||||||
|
* Adds a new wifi to the known networks
|
||||||
|
* @param ssid
|
||||||
|
* @param passkey
|
||||||
|
*/
|
||||||
|
static addWifi(ssid: string, passkey: string) {
|
||||||
|
return new Promise<void>(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let knownWifis = await this.getKnownWifis();
|
||||||
|
let found = false;
|
||||||
|
for (let wifi of knownWifis) {
|
||||||
|
if (wifi.ssid == wifi.ssid) {
|
||||||
|
// We know this wifi! - Refresh it!
|
||||||
|
found = true;
|
||||||
|
wifi.psk = passkey;
|
||||||
|
wifi.isSecured = !!passkey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
knownWifis.push({ssid: ssid, psk: passkey, isSecured: !!passkey});
|
||||||
|
}
|
||||||
|
await this.overwriteWifis(knownWifis);
|
||||||
|
return resolve();
|
||||||
|
} catch (e) {
|
||||||
|
return reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrites the custom wpa_supplicant file
|
||||||
|
* @param wifis
|
||||||
|
* @param ssid
|
||||||
|
*/
|
||||||
|
static overwriteWifis(wifis: WiFiNetwork[], ssid = "") {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
let p = path.resolve(process.cwd(), "/scripts/addWifi.sh");
|
let wifi_str = `ctrl_interface=/run/wpa_supplicant \nupdate_config=0\n\n`;
|
||||||
exec(p + ` -s "${wifi}" -p "${passkey}"`, (err, stdout) => {
|
for (let wifi of wifis) {
|
||||||
if(err)
|
wifi_str += "network={\n";
|
||||||
|
wifi_str += ` ssid="${wifi.ssid}"\n`
|
||||||
|
wifi_str += ` key_mgmt="${wifi.isSecured ? "WPA-PSK" : "NONE"}"\n`
|
||||||
|
|
||||||
|
if (ssid && ssid != wifi.ssid)
|
||||||
|
wifi_str += ` disabled=1\n`
|
||||||
|
if (wifi.psk)
|
||||||
|
wifi_str += ` psk="${wifi.psk}"\n`
|
||||||
|
wifi_str += `}\n\n`
|
||||||
|
}
|
||||||
|
fs.writeFileSync("/tmp/wpa_supplicant.conf", wifi_str);
|
||||||
|
exec("sudo mv -f /tmp/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-monopoly.conf", (err, stdout) => {
|
||||||
|
if (err)
|
||||||
return reject(err);
|
return reject(err);
|
||||||
if(stdout == "ok")
|
resolve();
|
||||||
resolve();
|
});
|
||||||
else
|
})
|
||||||
reject("no-return");
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static connectToWifi(ssid: string)
|
/**
|
||||||
{
|
* Connects to a specific wifi
|
||||||
|
* @param ssid
|
||||||
|
*/
|
||||||
|
static connectToWifi(ssid: string) {
|
||||||
return new Promise<boolean>((resolve, reject) => {
|
return new Promise<boolean>((resolve, reject) => {
|
||||||
|
this.getKnownWifis().then((wifis) => {
|
||||||
let p = path.resolve(process.cwd(), "/scripts/connectToWifi.sh");
|
this.overwriteWifis(wifis, ssid).then(() => {
|
||||||
exec(p + ``)
|
let p = path.resolve(this.scriptPath, "connectToWifi.sh");
|
||||||
|
exec(p, (error, stdout, stderr) => {
|
||||||
|
if (!error)
|
||||||
|
return resolve(stdout.includes("!!ok"));
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
}).catch(reject);
|
||||||
|
}).catch(reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static disableAllWifis() {
|
static removeWifi(ssid: string) {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
this.getKnownWifis().then(wifis => {
|
||||||
|
wifis.filter((ele) => {
|
||||||
|
return ele.ssid != ssid;
|
||||||
|
});
|
||||||
|
this.overwriteWifis(wifis).then(resolve).catch(reject);
|
||||||
|
}).catch(reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +180,6 @@ export default class OSHandler {
|
|||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(networks);
|
|
||||||
|
|
||||||
networks = networks.filter((ele, index) => {
|
networks = networks.filter((ele, index) => {
|
||||||
// If empty ssid
|
// If empty ssid
|
||||||
|
184
src/RawConstants.ts
Normal file
184
src/RawConstants.ts
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
export type IPCChannel =
|
||||||
|
'WIFI_SCAN'
|
||||||
|
| 'WIFI_CONNECT'
|
||||||
|
| 'FUNCTION_TEST'
|
||||||
|
| 'CLOUD_STATUS'
|
||||||
|
| 'CLOUD_CONNECT'
|
||||||
|
| 'SETTINGS'
|
||||||
|
| 'PREPARING'
|
||||||
|
|
||||||
|
export enum IPCListenChannels {
|
||||||
|
'KEYPAD_INPUT' = 'KEYPAD_INPUT',
|
||||||
|
'NFC_CARD' = 'NFC_CARD',
|
||||||
|
'NFC_RAW' = 'NFC_RAW'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPCAnswer {
|
||||||
|
status: boolean,
|
||||||
|
data?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPCRequest {
|
||||||
|
data?: any,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WiFiNetwork {
|
||||||
|
ssid: string,
|
||||||
|
isSecured: boolean,
|
||||||
|
isKnown?: boolean,
|
||||||
|
psk?: string,
|
||||||
|
rssi?: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FunctionTest {
|
||||||
|
hasSudo: boolean,
|
||||||
|
hasWPASupplicant: boolean,
|
||||||
|
hasInternet: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GameSwitch = {
|
||||||
|
name: GameSwitchNames,
|
||||||
|
label: string,
|
||||||
|
depends?: GameSwitchNames,
|
||||||
|
value: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GameInput = {
|
||||||
|
name: GameInputNames,
|
||||||
|
type: "number" | "text",
|
||||||
|
label: string,
|
||||||
|
depends?: GameSwitchNames,
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GameSwitchNames =
|
||||||
|
"GET_BONUS_PASSING_START"
|
||||||
|
| "DOUBLE_BONUS_ON_GO"
|
||||||
|
| "PUT_PAID_PENALTIES_IN_MIDDLE"
|
||||||
|
| "RECEIVE_PENALTIES_AT_FREE_PARKING"
|
||||||
|
| "PUT_10_IN_MIDDLE_AFTER_EACH_GO"
|
||||||
|
| "STREET_MUST_BE_AUCTIONED_IF_NOT_PURCHASED"
|
||||||
|
| "TWO_HOTELS_PER_STREET_ALLOWED"
|
||||||
|
| "MORTGAGE_REDUCES_RENT"
|
||||||
|
| "GOODS_GO_TO_OTHER_PLAYERS_UPON_BANKRUPTCY"
|
||||||
|
| "STREETS_CAN_BE_SOLD_BACK_TO_THE_BANK"
|
||||||
|
| "PRISON_CAN_BE_PURCHASED_RENT_GOES_TO_PLAYER"
|
||||||
|
| "KEEP_MONEY_MORE_SECRET";
|
||||||
|
|
||||||
|
export type GameInputNames =
|
||||||
|
"PASSING_GO_CASH"
|
||||||
|
| "STARTING_CASH"
|
||||||
|
| "PRISON_RELEASE_FEE"
|
||||||
|
| "CURRENCY";
|
||||||
|
|
||||||
|
export interface GameRules {
|
||||||
|
switchValues: { [key in GameSwitchNames]?: boolean },
|
||||||
|
inputValues: { [key in GameInputNames]?: string }
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Config {
|
||||||
|
rules?: GameRules
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum NFCCardType {
|
||||||
|
INVALID = "INVALID",
|
||||||
|
ACCOUNT = "ACCOUNT",
|
||||||
|
PROPERTY = "PROPERTY",
|
||||||
|
TASK = "TASK",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NFCCard {
|
||||||
|
cardType: NFCCardType,
|
||||||
|
uid?: string,
|
||||||
|
raw?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AccountSymbols {
|
||||||
|
HAT= "Hut",
|
||||||
|
CAT= "Katze",
|
||||||
|
SHOE= "Schuh",
|
||||||
|
SHIP= "Kriegsschiff",
|
||||||
|
RACE_CAR = "Rennauto",
|
||||||
|
THIMBLE= "Fingerhut",
|
||||||
|
WHEELBARROW= "Schubkarre",
|
||||||
|
DOG = "Hund",
|
||||||
|
IRON = "Bügeleisen",
|
||||||
|
BATTLESHIP = "Schlachtschiff",
|
||||||
|
TOP_HAT = "Zylinder",
|
||||||
|
CANNON = "Kanone",
|
||||||
|
TREX = "T-Rex",
|
||||||
|
RUBBER_DUCK = "Gummiente",
|
||||||
|
PENGUIN = "Pinguin",
|
||||||
|
|
||||||
|
PLAYTYPUS= "Schnabeltier"
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NFCAccountCard extends NFCCard {
|
||||||
|
symbol: AccountSymbols,
|
||||||
|
nickname: string,
|
||||||
|
pin: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PropertyColor {
|
||||||
|
YELLOW= "YELLOW",
|
||||||
|
GOLD="GOLD",
|
||||||
|
SILVER="SILVER",
|
||||||
|
ORANGE = "ORANGE",
|
||||||
|
PINK = "PINK",
|
||||||
|
BEIGE="BEIGE",
|
||||||
|
BROWN = "BROWN",
|
||||||
|
RED ="RED",
|
||||||
|
GREEN="GREEN",
|
||||||
|
BLACK="BLACK",
|
||||||
|
WHITE="WHITE",
|
||||||
|
LIGHT_BLUE ="LIGHT_BLUE",
|
||||||
|
DARK_BLUE = "DARK_BLUE",
|
||||||
|
|
||||||
|
TRAINSTATION = "TRAINSTATION",
|
||||||
|
UTILITY = "UTILITY",
|
||||||
|
|
||||||
|
CUSTOM1 ="CUSTOM1",
|
||||||
|
CUSTOM2 = "CUSTOM2",
|
||||||
|
CUSTOM3 = "CUSTOM3"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NFCPropertyCardSpecialProperties =
|
||||||
|
"TRAINSTATION" | "UTILITY"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NFC Property Card
|
||||||
|
* NAME(str);COLOR(str);FULLSET(num);BUYVAL(num);MORTGAGEVAL(num);RENT,RENT1,RENT2,RENT3,RENT4,RENT_HOTEL,SPECIAl_PROPS
|
||||||
|
*/
|
||||||
|
export interface NFCPropertyCard extends NFCCard {
|
||||||
|
name: string,
|
||||||
|
color: PropertyColor,
|
||||||
|
fullSetAmount: number,
|
||||||
|
buyValue: number,
|
||||||
|
mortgageValue: number,
|
||||||
|
rent: number,
|
||||||
|
rent1?: number,
|
||||||
|
rent2?: number,
|
||||||
|
rent3?: number,
|
||||||
|
rent4?: number,
|
||||||
|
rentHotel?: number,
|
||||||
|
specialProperties: NFCPropertyCardSpecialProperties|"",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TaskType {
|
||||||
|
GET_FROM_BANK= "GET_FROM_BANK", // 1 val
|
||||||
|
PAY_TO_BANK= "PAY_TO_BANK", // 1 val
|
||||||
|
PAY_TO_ALL_PLAYERS= "PAY_TO_ALL_PLAYERS", // 1 val
|
||||||
|
PAY_FOR_PROPS= "PAY_FOR_PROPS", // 2 val
|
||||||
|
ESCAPE_JAIL= "ESCAPE_JAIL" // 0 val
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NFC Task Card
|
||||||
|
* RAW: TYPE;AMOUNT;AMOUNT2
|
||||||
|
*/
|
||||||
|
export interface NFCTaskCard extends NFCCard {
|
||||||
|
type: TaskType
|
||||||
|
amount?: number,
|
||||||
|
amount2?: number
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
|||||||
import {IPCHandler} from "./IPCHandler";
|
import {IPCHandle} from "./IPCMainHandler";
|
||||||
import {FunctionTest, WiFiNetwork} from "./IPCConstants";
|
import {FunctionTest, GameRules} from "./RawConstants";
|
||||||
import OSHandler from "./OSHandler";
|
import OSHandler from "./OSHandler";
|
||||||
import WiFi from "./web/WiFi";
|
import CloudHandler from "./CloudHandler";
|
||||||
|
import {ConfigHandler} from "./ConfigHandler";
|
||||||
|
import NFCHandler from "./NFCHandler";
|
||||||
|
|
||||||
const wifiScan = require("node-wifi-scanner");
|
const wifiScan = require("node-wifi-scanner");
|
||||||
|
|
||||||
@ -12,11 +14,12 @@ const wifiScan = require("node-wifi-scanner");
|
|||||||
export default class SmartMonopoly {
|
export default class SmartMonopoly {
|
||||||
static run() {
|
static run() {
|
||||||
this.setupIPCEvents();
|
this.setupIPCEvents();
|
||||||
OSHandler.getKnownWifis().then(console.log);
|
OSHandler.enableAllWifis().then().catch(console.error);
|
||||||
|
NFCHandler.initTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
static setupIPCEvents() {
|
static setupIPCEvents() {
|
||||||
IPCHandler("FUNCTION_TEST", async (e, request, args) => {
|
IPCHandle("FUNCTION_TEST", async (e, request, args) => {
|
||||||
let data: FunctionTest = {
|
let data: FunctionTest = {
|
||||||
hasSudo: await OSHandler.checkForSudo(),
|
hasSudo: await OSHandler.checkForSudo(),
|
||||||
hasWPASupplicant: false,
|
hasWPASupplicant: false,
|
||||||
@ -29,22 +32,59 @@ export default class SmartMonopoly {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
IPCHandler("WIFI_CONNECT", async (e, request, args) => {
|
IPCHandle("WIFI_CONNECT", async (e, request, args) => {
|
||||||
let data = request.data as {wifi: string, password: string}
|
let data = request.data as { ssid: string, psk: string }
|
||||||
await OSHandler.addWifi(data.wifi, data.password);
|
try {
|
||||||
|
await OSHandler.addWifi(data.ssid, data.psk);
|
||||||
|
let status = await OSHandler.connectToWifi(data.ssid);
|
||||||
return {status: false}
|
return {status: status};
|
||||||
|
} catch (e) {
|
||||||
|
return {status: false}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
IPCHandler("WIFI_SCAN", async (e, request, args) => {
|
IPCHandle("WIFI_SCAN", async (e, request) => {
|
||||||
try {
|
try {
|
||||||
let networks = await OSHandler.scanWifis();
|
let networks = await OSHandler.scanWifis();
|
||||||
return {status: true, data: networks};
|
return {status: true, data: networks};
|
||||||
} catch(e)
|
} catch (e) {
|
||||||
{
|
|
||||||
return {status: false};
|
return {status: false};
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
IPCHandle("CLOUD_CONNECT", async (e, request) => {
|
||||||
|
try {
|
||||||
|
await CloudHandler.connect();
|
||||||
|
return {status: true};
|
||||||
|
} catch (e) {
|
||||||
|
return {status: false, data: e.toString()};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
IPCHandle("SETTINGS", async(e, request) => {
|
||||||
|
if(request.data && request.data["rules"])
|
||||||
|
{
|
||||||
|
let rules = request.data.rules as GameRules;
|
||||||
|
ConfigHandler.set({rules: rules});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {status: true, data: ConfigHandler.get()};
|
||||||
|
});
|
||||||
|
|
||||||
|
IPCHandle("PREPARING", async(e, request) => {
|
||||||
|
const useCloud = !!request.data.useCloud;
|
||||||
|
console.log("Preparing - useCloud: " + useCloud);
|
||||||
|
if(useCloud && !CloudHandler.isConnected())
|
||||||
|
try {
|
||||||
|
await CloudHandler.connect();
|
||||||
|
}catch(e)
|
||||||
|
{
|
||||||
|
return {status: false, data: 'Cloud connection issue: ' + e};
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo when using cloud, get session etc.
|
||||||
|
|
||||||
|
return {status: true};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
1
src/global.ts
Normal file
1
src/global.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare var mainWebContents: Electron.WebContents;
|
@ -9,8 +9,6 @@ declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||||
if (require('electron-squirrel-startup')) {
|
if (require('electron-squirrel-startup')) {
|
||||||
app.quit();
|
app.quit();
|
||||||
@ -32,6 +30,8 @@ const createWindow = (): void => {
|
|||||||
|
|
||||||
// Background
|
// Background
|
||||||
SmartMonopoly.run();
|
SmartMonopoly.run();
|
||||||
|
|
||||||
|
global.mainWebContents = mainWindow.webContents;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
// This method will be called when Electron has finished
|
||||||
|
68
src/nfc-pcsd.d.ts
vendored
Normal file
68
src/nfc-pcsd.d.ts
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
declare module 'nfc-pcsc' {
|
||||||
|
export type ListenerSignature<L> = {
|
||||||
|
[E in keyof L]: (...args: any[]) => any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DefaultListener = {
|
||||||
|
[k: string]: (...args: any[]) => any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class TypedEmitter<L extends ListenerSignature<L> = DefaultListener> {
|
||||||
|
static defaultMaxListeners: number;
|
||||||
|
addListener<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
prependListener<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
prependOnceListener<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
removeListener<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
removeAllListeners(event?: keyof L): this;
|
||||||
|
once<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
on<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
off<U extends keyof L>(event: U, listener: L[U]): this;
|
||||||
|
emit<U extends keyof L>(event: U, ...args: Parameters<L[U]>): boolean;
|
||||||
|
eventNames<U extends keyof L>(): U[];
|
||||||
|
listenerCount(type: keyof L): number;
|
||||||
|
listeners<U extends keyof L>(type: U): L[U][];
|
||||||
|
rawListeners<U extends keyof L>(type: U): L[U][];
|
||||||
|
getMaxListeners(): number;
|
||||||
|
setMaxListeners(n: number): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type = 'TAG_ISO_14443_3' | 'TAG_ISO_14443_4';
|
||||||
|
|
||||||
|
const KEY_TYPE_A = 0x60;
|
||||||
|
const KEY_TYPE_B = 0x61;
|
||||||
|
|
||||||
|
interface Card {
|
||||||
|
type: Type;
|
||||||
|
standard: Type;
|
||||||
|
uid?: string;
|
||||||
|
data?: Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReaderEmitter {
|
||||||
|
card: (x: Card) => void;
|
||||||
|
'card.off': (x: Card) => void;
|
||||||
|
error: (x: Error) => void;
|
||||||
|
end: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Reader extends TypedEmitter<ReaderEmitter> {
|
||||||
|
get name(): string;
|
||||||
|
|
||||||
|
authenticate(blockNumber: number, keyType: number, key: string, obsolete?: boolean): Promise<boolean>;
|
||||||
|
|
||||||
|
read(
|
||||||
|
blockNumber: number,
|
||||||
|
length: number,
|
||||||
|
blockSize?: number,
|
||||||
|
packetSize?: number,
|
||||||
|
readClass?: number
|
||||||
|
): Promise<Buffer>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NFCEmitter {
|
||||||
|
reader: (reader: Reader) => void;
|
||||||
|
error: (error: Error) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NFC extends TypedEmitter<NFCEmitter> {}
|
||||||
|
}
|
@ -2,15 +2,14 @@
|
|||||||
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
|
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
|
||||||
|
|
||||||
import {ipcRenderer, contextBridge} from 'electron';
|
import {ipcRenderer, contextBridge} from 'electron';
|
||||||
import {IPCAnswer, IPCChannel, IPCRequest} from "./IPCConstants";
|
import {IPCAnswer, IPCChannel, IPCRequest} from "./RawConstants";
|
||||||
import IpcRendererEvent = Electron.IpcRendererEvent;
|
import IpcRendererEvent = Electron.IpcRendererEvent;
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('api', {
|
contextBridge.exposeInMainWorld('api', {
|
||||||
request: (channel: IPCChannel, request: IPCRequest, ...args: any): Promise<IPCAnswer> => {
|
request: (channel: IPCChannel, request: IPCRequest, ...args: any): Promise<IPCAnswer> => {
|
||||||
return ipcRenderer.invoke(channel, request, ...args);
|
return ipcRenderer.invoke(channel, request, ...args);
|
||||||
},
|
},
|
||||||
receive: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => {
|
listen: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => {
|
||||||
console.log("preload-receive called. args: ");
|
|
||||||
ipcRenderer.on(channel, (event, message: IPCAnswer, ...args: any) => func(event, message, ...args));
|
ipcRenderer.on(channel, (event, message: IPCAnswer, ...args: any) => func(event, message, ...args));
|
||||||
},
|
},
|
||||||
})
|
})
|
@ -2,66 +2,16 @@ import {createRoot} from 'react-dom/client';
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import Startup from "./Startup";
|
import Startup from "./Startup";
|
||||||
import WiFi from "./WiFi";
|
import WiFi from "./WiFi";
|
||||||
import Cloud from "./Cloud";
|
|
||||||
import Game from "./Game";
|
import Game from "./Game";
|
||||||
import GameSetup from "./GameSetup";
|
import GameSetup from "./GameSetup";
|
||||||
import GameEnd from "./GameEnd";
|
import GameEnd from "./GameEnd";
|
||||||
import Setup from "./Setup";
|
import Setup from "./Setup";
|
||||||
|
import IPCRendererListener from "./IPCRendererListener";
|
||||||
|
|
||||||
const root = createRoot(document.getElementById("root"));
|
const root = createRoot(document.getElementById("root"));
|
||||||
|
|
||||||
//window.app = window.MyNamespace || {};
|
|
||||||
|
|
||||||
|
export enum PAGE {
|
||||||
interface HeadingSwitcherState {
|
|
||||||
counter: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
class HeadingSwitcher extends Component<{}, HeadingSwitcherState> {
|
|
||||||
private interval: NodeJS.Timeout;
|
|
||||||
|
|
||||||
constructor(props: {}) {
|
|
||||||
super(props);
|
|
||||||
this.state = {counter: 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.interval = setInterval(() => this.tick(), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
clearInterval(this.interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
tick() {
|
|
||||||
if (this.state.counter > 5)
|
|
||||||
this.setState({counter: 1});
|
|
||||||
else
|
|
||||||
this.setState({counter: this.state.counter + 1});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
switch (this.state.counter) {
|
|
||||||
case 1:
|
|
||||||
return <h1>H1</h1>;
|
|
||||||
case 2:
|
|
||||||
return <h2>H2</h2>;
|
|
||||||
case 3:
|
|
||||||
return <h3>H3</h3>;
|
|
||||||
case 4:
|
|
||||||
return <h4>H4</h4>;
|
|
||||||
case 5:
|
|
||||||
return <h5>H5</h5>;
|
|
||||||
case 6:
|
|
||||||
return <h6>H6</h6>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum PAGE {
|
|
||||||
STARTUP,
|
STARTUP,
|
||||||
SETUP,
|
SETUP,
|
||||||
WIFI,
|
WIFI,
|
||||||
@ -73,7 +23,7 @@ enum PAGE {
|
|||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
currentPage: PAGE,
|
currentPage: PAGE,
|
||||||
showWiFi: boolean
|
showWiFi: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export class App extends Component<{}, AppState> {
|
export class App extends Component<{}, AppState> {
|
||||||
@ -83,9 +33,10 @@ export class App extends Component<{}, AppState> {
|
|||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
currentPage: PAGE.STARTUP,
|
currentPage: PAGE.SETUP,
|
||||||
showWiFi: false
|
showWiFi: false,
|
||||||
}
|
}
|
||||||
|
IPCRendererListener.initialAttach();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleWiFiSettings = (state: boolean) => {
|
toggleWiFiSettings = (state: boolean) => {
|
||||||
@ -95,14 +46,28 @@ export class App extends Component<{}, AppState> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleSetup = (state: boolean) => {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
showSetup: state
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPage = (page: PAGE) => {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
currentPage: page
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="app">
|
||||||
{this.state.showWiFi ? <WiFi/> : null}
|
{this.state.showWiFi ? <WiFi/> : null}
|
||||||
|
|
||||||
{this.state.currentPage == PAGE.STARTUP ? <Startup ref={(ref) => {
|
{this.state.currentPage == PAGE.STARTUP || this.state.currentPage == PAGE.SETUP ? <Startup visible={this.state.currentPage == PAGE.STARTUP} ref={(ref) => {
|
||||||
App.PAGES.set(PAGE.STARTUP, ref);
|
App.PAGES.set(PAGE.STARTUP, ref);
|
||||||
}}/> : null}
|
}}/> : null}
|
||||||
|
|
||||||
@ -110,14 +75,6 @@ export class App extends Component<{}, AppState> {
|
|||||||
App.PAGES.set(PAGE.SETUP, ref);
|
App.PAGES.set(PAGE.SETUP, ref);
|
||||||
}}/> : null}
|
}}/> : null}
|
||||||
|
|
||||||
{this.state.currentPage == PAGE.WIFI ? <WiFi ref={(ref) => {
|
|
||||||
App.PAGES.set(PAGE.WIFI, ref);
|
|
||||||
}}/> : null}
|
|
||||||
|
|
||||||
{this.state.currentPage == PAGE.CLOUD ? <Cloud ref={(ref) => {
|
|
||||||
App.PAGES.set(PAGE.CLOUD, ref);
|
|
||||||
}}/> : null}
|
|
||||||
|
|
||||||
{this.state.currentPage == PAGE.GAME_SETUP ? <GameSetup ref={(ref) => {
|
{this.state.currentPage == PAGE.GAME_SETUP ? <GameSetup ref={(ref) => {
|
||||||
App.PAGES.set(PAGE.GAME_SETUP, ref);
|
App.PAGES.set(PAGE.GAME_SETUP, ref);
|
||||||
}}/> : null}
|
}}/> : null}
|
||||||
|
449
src/web/CardSetup.tsx
Normal file
449
src/web/CardSetup.tsx
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
import {
|
||||||
|
AccountSymbols,
|
||||||
|
NFCAccountCard,
|
||||||
|
NFCCard,
|
||||||
|
NFCCardType,
|
||||||
|
NFCPropertyCard,
|
||||||
|
NFCTaskCard,
|
||||||
|
PropertyColor,
|
||||||
|
TaskType
|
||||||
|
} from "../RawConstants";
|
||||||
|
import React, {Component} from "react";
|
||||||
|
import {
|
||||||
|
Backdrop,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Fade,
|
||||||
|
FormControl,
|
||||||
|
FormControlLabel,
|
||||||
|
FormGroup,
|
||||||
|
FormLabel,
|
||||||
|
Grid,
|
||||||
|
InputLabel,
|
||||||
|
MenuItem,
|
||||||
|
Modal,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
Select,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
type AccountValues = keyof NFCAccountCard;
|
||||||
|
type PropertyValues = keyof NFCPropertyCard;
|
||||||
|
type TaskValues = keyof NFCTaskCard;
|
||||||
|
|
||||||
|
interface CardSetupState {
|
||||||
|
NFCCardType: NFCCardType,
|
||||||
|
|
||||||
|
accountValues: { [key in AccountValues]?: string | number },
|
||||||
|
propertyValues: { [key in PropertyValues]?: string | number | boolean },
|
||||||
|
taskValues: { [key in TaskValues]?: string | TaskType | number }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CardSetupProps {
|
||||||
|
closeCallback: () => void;
|
||||||
|
card?: NFCCard;
|
||||||
|
validCard: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class CardSetup extends Component<CardSetupProps, CardSetupState> {
|
||||||
|
constructor(props: CardSetupProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
let defaultType = NFCCardType.ACCOUNT;
|
||||||
|
let accountValues: { [key in AccountValues]?: string | number } = {
|
||||||
|
symbol: "pleaseSelect"
|
||||||
|
};
|
||||||
|
let propertyValues: { [key in PropertyValues]?: string | number | boolean } = {
|
||||||
|
color: "pleaseSelect"
|
||||||
|
};
|
||||||
|
let taskValues: { [key in TaskValues]?: string | TaskType | number } = {
|
||||||
|
type: "pleaseSelect"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.card) {
|
||||||
|
defaultType = props.card.cardType as NFCCardType;
|
||||||
|
console.log("Detected card type: " + defaultType);
|
||||||
|
switch (defaultType) {
|
||||||
|
case NFCCardType.ACCOUNT:
|
||||||
|
let accountCard = props.card as NFCAccountCard;
|
||||||
|
accountValues = {
|
||||||
|
...accountCard
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFCCardType.PROPERTY:
|
||||||
|
let propertyCard = props.card as NFCPropertyCard;
|
||||||
|
propertyValues = {
|
||||||
|
...propertyCard
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFCCardType.TASK:
|
||||||
|
let taskCard = props.card as NFCTaskCard;
|
||||||
|
taskValues = {
|
||||||
|
...taskCard
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
NFCCardType: defaultType,
|
||||||
|
|
||||||
|
accountValues: accountValues,
|
||||||
|
propertyValues: propertyValues,
|
||||||
|
taskValues: taskValues,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
modalStyle = {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
width: 700,
|
||||||
|
maxHeight: '85%',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
height: 'auto',
|
||||||
|
display: 'block',
|
||||||
|
bgcolor: 'background.paper',
|
||||||
|
border: '2px solid #0000',
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
changeAccountState(prop: AccountValues, ev: any, useUpperCase = false) {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
accountValues: {
|
||||||
|
...prevState.accountValues,
|
||||||
|
[prop]: useUpperCase ? ev.target.value.toUpperCase() : ev.target.value
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
changePropertyState(prop: PropertyValues, ev: any) {
|
||||||
|
if (prop == "fullSetAmount") {
|
||||||
|
if (ev.target.value > 4)
|
||||||
|
ev.target.value = 4;
|
||||||
|
if (ev.target.value < 1)
|
||||||
|
ev.target.value = 1;
|
||||||
|
}
|
||||||
|
if (prop == "buyValue" || prop == "mortgageValue" || prop.includes("rent")) {
|
||||||
|
if (ev.target.value < 0)
|
||||||
|
ev.target.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
propertyValues: {
|
||||||
|
...prevState.propertyValues,
|
||||||
|
[prop]: ev.target.value
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
changeTaskState(prop: TaskValues, ev: any) {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
taskValues: {
|
||||||
|
...prevState.taskValues,
|
||||||
|
[prop]: ev.target.value
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
insertInputsPerType = () => {
|
||||||
|
if (this.state.NFCCardType == NFCCardType.ACCOUNT) {
|
||||||
|
return (<FormGroup sx={{m: 1}}>
|
||||||
|
<InputLabel id="symbolLabel">Symbol</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId={"symbolLabel"}
|
||||||
|
sx={{mb: 1}}
|
||||||
|
onChange={(ev) => this.changeAccountState("symbol", ev)}
|
||||||
|
label="Symbol "
|
||||||
|
value={this.state.accountValues["symbol"]}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<MenuItem disabled={true} value="pleaseSelect">Bitte wählen...</MenuItem>
|
||||||
|
{Object.entries(AccountSymbols).map((ele) => (
|
||||||
|
<MenuItem key={ele[0]} value={ele[0]}>{ele[1]}</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
<TextField sx={{mb: 1}}
|
||||||
|
label="Nickname"
|
||||||
|
type="text"
|
||||||
|
value={this.state.accountValues["nickname"]}
|
||||||
|
onChange={(ev) => this.changeAccountState("nickname", ev)}
|
||||||
|
/>
|
||||||
|
<TextField sx={{mb: 1}}
|
||||||
|
label="PIN"
|
||||||
|
type="number"
|
||||||
|
value={this.state.accountValues["pin"]}
|
||||||
|
onChange={(ev) => this.changeAccountState("pin", ev)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</FormGroup>)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.NFCCardType == NFCCardType.PROPERTY) {
|
||||||
|
return (<FormGroup sx={{m: 1}}>
|
||||||
|
<Grid container spacing={2} sx={{width: '100%'}}>
|
||||||
|
<Grid item xs={12} sm={12}>
|
||||||
|
<InputLabel>Name</InputLabel>
|
||||||
|
<TextField
|
||||||
|
sx={{mb: 1}}
|
||||||
|
type="text"
|
||||||
|
value={this.state.propertyValues["name"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("name", ev)}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<InputLabel id="colorLabel">Farbcode / Typ</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId={"colorLabel"}
|
||||||
|
sx={{mb: 1}}
|
||||||
|
onChange={(ev) => this.changePropertyState("color", ev)}
|
||||||
|
label="Farbcode / Typ "
|
||||||
|
value={this.state.propertyValues["color"]}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<MenuItem disabled={true} value="pleaseSelect">Bitte wählen...</MenuItem>
|
||||||
|
{Object.keys(PropertyColor).map((color: string) => (
|
||||||
|
<MenuItem key={color} value={color}>{color}</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<InputLabel>Voller Satz Anzahl</InputLabel>
|
||||||
|
<TextField
|
||||||
|
sx={{mb: 1}}
|
||||||
|
type="number"
|
||||||
|
value={this.state.propertyValues["fullSetAmount"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("fullSetAmount", ev)}
|
||||||
|
fullWidth
|
||||||
|
aria-valuemin={0}
|
||||||
|
aria-valuemax={4}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<InputLabel>Kauf-Wert</InputLabel>
|
||||||
|
<TextField
|
||||||
|
sx={{mb: 1}}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
type="number"
|
||||||
|
value={this.state.propertyValues["buyValue"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("buyValue", ev)}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<InputLabel>Hypothek-Wert</InputLabel>
|
||||||
|
<TextField
|
||||||
|
sx={{mb: 1}}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
type="number"
|
||||||
|
value={this.state.propertyValues["mortgageValue"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("mortgageValue", ev)}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={4} sm={4}>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label={"Grundmiete"}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
value={this.state.propertyValues["rent"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("rent", ev)}
|
||||||
|
helperText={"Grundmiete ohne Haus und Set"}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4} sm={4}>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label={"Miete 1"}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
value={this.state.propertyValues["rent1"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("rent1", ev)}
|
||||||
|
helperText={"Miete bei einem Haus"}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4} sm={4}>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label={"Miete 2"}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
value={this.state.propertyValues["rent2"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("rent2", ev)}
|
||||||
|
helperText={"Miete bei 2 Häusern"}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={4} sm={4}>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label={"Miete 3"}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
value={this.state.propertyValues["rent3"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("rent3", ev)}
|
||||||
|
helperText={"Miete bei 3 Häusern"}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={4} sm={4}>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label={"Miete 4"}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
value={this.state.propertyValues["rent4"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("rent4", ev)}
|
||||||
|
helperText={"Miete bei 4 Häusern"}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={4} sm={4}>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label={"Miete Hotel"}
|
||||||
|
inputProps={{"step": 5}}
|
||||||
|
value={this.state.propertyValues["rentHotel"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("rentHotel", ev)}
|
||||||
|
helperText={"Miete bei einem Hotel"}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={12}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<FormLabel id="cardProperties">Besondere Eigenschaften</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
row
|
||||||
|
aria-labelledby="cardProperties"
|
||||||
|
defaultValue={""}
|
||||||
|
value={this.state.propertyValues["specialProperties"]}
|
||||||
|
onChange={(ev) => this.changePropertyState("specialProperties", ev)}
|
||||||
|
>
|
||||||
|
<FormControlLabel value={""} control={<Radio/>} label="Keine"/>
|
||||||
|
<FormControlLabel value="TRAINSTATION" control={<Radio/>} label="Bahnhof"/>
|
||||||
|
<FormControlLabel value="UTILITY" control={<Radio/>} label="Versorgungswerk"/>
|
||||||
|
<FormControlLabel value="JAIL" control={<Radio/>} label="Gefängnis"/>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
</FormGroup>)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.NFCCardType == NFCCardType.TASK) {
|
||||||
|
/**
|
||||||
|
* type: TaskType
|
||||||
|
* amount?: number,
|
||||||
|
* amount2?: number
|
||||||
|
*/
|
||||||
|
return (<FormGroup sx={{m: 1}}>
|
||||||
|
<InputLabel id="typeLabel">Typ</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId={"typeLabel"}
|
||||||
|
sx={{mb: 1}}
|
||||||
|
onChange={(ev) => this.changeTaskState("type", ev)}
|
||||||
|
label="Typ "
|
||||||
|
value={this.state.taskValues["type"]}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<MenuItem disabled={true} value="pleaseSelect">Bitte wählen...</MenuItem>
|
||||||
|
{Object.keys(TaskType).map((tt: string) => (
|
||||||
|
<MenuItem key={tt} value={tt}>{tt}</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
<TextField sx={{mb: 1}}
|
||||||
|
label="Betrag 1"
|
||||||
|
type="text"
|
||||||
|
disabled={this.state.taskValues["type"] == "ESCAPE_JAIL"}
|
||||||
|
value={this.state.taskValues["amount"]}
|
||||||
|
onChange={(ev) => this.changeAccountState("nickname", ev)}
|
||||||
|
helperText={this.state.taskValues["type"] == "PAY_FOR_PROPS" ? "Preis pro Haus" : "Geldbetrag"}
|
||||||
|
/>
|
||||||
|
<TextField sx={{mb: 1}}
|
||||||
|
label="Betrag 2"
|
||||||
|
type="number"
|
||||||
|
disabled={this.state.taskValues["type"] != "PAY_FOR_PROPS"}
|
||||||
|
value={this.state.taskValues["amount2"]}
|
||||||
|
onChange={(ev) => this.changeAccountState("pin", ev)}
|
||||||
|
helperText={"gfs. Preis pro Hotel"}
|
||||||
|
/>
|
||||||
|
</FormGroup>)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<div>Bitte einen Typ selektieren um fortzufahren.<br/> </div>)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (<Modal
|
||||||
|
aria-labelledby="transition-modal-title"
|
||||||
|
aria-describedby="transition-modal-description"
|
||||||
|
open={true}
|
||||||
|
onClose={() => {
|
||||||
|
this.props.closeCallback()
|
||||||
|
}}
|
||||||
|
closeAfterTransition
|
||||||
|
slots={{backdrop: Backdrop}}
|
||||||
|
slotProps={{
|
||||||
|
backdrop: {
|
||||||
|
timeout: 500,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Fade in={true}>
|
||||||
|
<Box sx={this.modalStyle}>
|
||||||
|
<Typography id="transition-modal-title" variant="h6" component="h2">
|
||||||
|
NFC-Karte konfigurieren
|
||||||
|
</Typography>
|
||||||
|
<Typography id="transition-modal-description" sx={{mt: 2}}>
|
||||||
|
{this.props.validCard ? "Es wurde eine gültige Spielkarte erkannt." : "Es wurde eine ungültige NFC-Karte erkannt."}
|
||||||
|
<br/><br/>
|
||||||
|
<div>
|
||||||
|
<InputLabel id="nfcCardTypeLabel">Karten-Typ</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="nfcCardTypeLabel"
|
||||||
|
value={this.state.NFCCardType.toString()}
|
||||||
|
onChange={(ev) =>
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
NFCCardType: ev.target.value as NFCCardType
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Object.values(NFCCardType).map(e => {
|
||||||
|
return (
|
||||||
|
<MenuItem key={e} value={(e)}>{(e == NFCCardType.INVALID ? "Bitte wählen" : e)}</MenuItem>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
{this.insertInputsPerType()}
|
||||||
|
<br/>
|
||||||
|
<Button variant="contained" onClick={() => {
|
||||||
|
this.props.closeCallback();
|
||||||
|
}}
|
||||||
|
color="secondary">Schließen</Button>
|
||||||
|
|
||||||
|
<Button variant="contained" color="primary" sx={{ml: 1}}
|
||||||
|
onClick={() => {
|
||||||
|
}}>Karte beschreiben</Button>
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Fade>
|
||||||
|
</Modal>);
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
import {Component} from "react";
|
|
||||||
|
|
||||||
|
|
||||||
interface CloudState {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Cloud extends Component<{}, CloudState> {
|
|
||||||
constructor(props: {}) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <p>Test</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
64
src/web/GameHandler.ts
Normal file
64
src/web/GameHandler.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import {PAGE} from "./App";
|
||||||
|
import {IPCListenChannels, NFCCard} from "../RawConstants";
|
||||||
|
import IPCRendererListener from "./IPCRendererListener";
|
||||||
|
|
||||||
|
export enum GAME_STATE {
|
||||||
|
NOT_STARTED,
|
||||||
|
PREPARING,
|
||||||
|
PLAYING,
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GameHandler {
|
||||||
|
|
||||||
|
static GAMESTATE: GAME_STATE = GAME_STATE.NOT_STARTED;
|
||||||
|
static attachedNFCHandler: number = 0;
|
||||||
|
|
||||||
|
static setGameState(state: GAME_STATE)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case GAME_STATE.NOT_STARTED:
|
||||||
|
window.app.setPage(PAGE.STARTUP);
|
||||||
|
break;
|
||||||
|
case GAME_STATE.PREPARING :
|
||||||
|
window.app.setPage(PAGE.GAME_SETUP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.GAMESTATE = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static attachNFCHandler(cb: (card: NFCCard) => void)
|
||||||
|
{
|
||||||
|
IPCRendererListener.detach(this.attachedNFCHandler);
|
||||||
|
this.attachedNFCHandler = IPCRendererListener.attach(IPCListenChannels.NFC_CARD, (ipcMsg) => {
|
||||||
|
if(ipcMsg.status)
|
||||||
|
cb(ipcMsg.data as NFCCard);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static detachNFCHandler()
|
||||||
|
{
|
||||||
|
IPCRendererListener.detach(this.attachedNFCHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async requestPreparing(useCloud: boolean)
|
||||||
|
{
|
||||||
|
let response = await window.api.request("PREPARING", {
|
||||||
|
data:
|
||||||
|
{
|
||||||
|
useCloud: useCloud,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!response.status)
|
||||||
|
{
|
||||||
|
this.setGameState(GAME_STATE.NOT_STARTED);
|
||||||
|
throw new Error(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setGameState(GAME_STATE.PREPARING);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,157 @@
|
|||||||
import {Component} from "react";
|
import React, {Component} from "react";
|
||||||
|
import {
|
||||||
|
Button, Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
Grid, ListItemAvatar,
|
||||||
|
Snackbar,
|
||||||
|
Typography,
|
||||||
|
Avatar, ListItemText, ListItem, List, Chip
|
||||||
|
} from "@mui/material";
|
||||||
|
import NfcIcon from '@mui/icons-material/Nfc';
|
||||||
|
import AddCardIcon from '@mui/icons-material/AddCard';
|
||||||
|
import PersonAddIcon from '@mui/icons-material/PersonAdd';
|
||||||
|
|
||||||
|
|
||||||
|
import GameHandler from "./GameHandler";
|
||||||
|
import {NFCCard} from "../RawConstants";
|
||||||
|
import {Person as PersonIcon, QrCode, RemoveDone} from "@mui/icons-material";
|
||||||
|
import CloudIcon from "@mui/icons-material/Cloud";
|
||||||
|
|
||||||
interface GameState {
|
interface GameState {
|
||||||
|
snackMsg: string,
|
||||||
|
helpDialog: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class GameSetup extends Component<{}, GameState> {
|
export default class GameSetup extends Component<{}, GameState> {
|
||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
snackMsg: "",
|
||||||
|
helpDialog: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
helpDialog: false,
|
||||||
|
snackMsg: "Zum hinzufügen von Spielern, NFC-Karte an das Lesegerät halten!",
|
||||||
|
}))
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
GameHandler.attachNFCHandler((card: NFCCard) => {
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
GameHandler.detachNFCHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <p>Test</p>
|
return <div className="gameSetup">
|
||||||
|
<Snackbar
|
||||||
|
open={!!this.state.snackMsg}
|
||||||
|
autoHideDuration={10000}
|
||||||
|
onClose={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
snackMsg: ""
|
||||||
|
}))
|
||||||
|
}}
|
||||||
|
message={this.state.snackMsg}
|
||||||
|
/>
|
||||||
|
<Dialog
|
||||||
|
open={this.state.helpDialog}
|
||||||
|
onClose={() => {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
helpDialog: false
|
||||||
|
}))
|
||||||
|
}}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">
|
||||||
|
Spielerkarte auf Gerät legen! <AddCardIcon/>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Um eine Figur zum Spiel hinzuzufügen, musst du die NFC-Spielerkarte an den Kartenleser
|
||||||
|
halten. <br/><br/>
|
||||||
|
Ein kurzes Berühren reicht aus, schon sollte der Spieler in der Tabelle auftauchen! <PersonAddIcon/>
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
helpDialog: false
|
||||||
|
}))}>
|
||||||
|
Okay</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Chip sx={{position: "absolute", top: "1%", right: "1%"}} onClick={() => {this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
helpDialog: true
|
||||||
|
}))}}
|
||||||
|
label="?" color="info"
|
||||||
|
variant="outlined"/>
|
||||||
|
|
||||||
|
<Typography variant="h2" >Wer spielt mit?</Typography>
|
||||||
|
<Chip onClick={() => {this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
snackMsg: "Um einen Spieler hinzuzufügen, lege eine NFC-Karte auf den leser!"
|
||||||
|
}))}}
|
||||||
|
label={<div><NfcIcon sx={{marginTop: 0.9}} className={"animationBreathe"}
|
||||||
|
color="primary"/> NFC</div>} color="secondary"
|
||||||
|
variant="outlined"/>
|
||||||
|
<Grid sx={{mt: 2}} container spacing={1}>
|
||||||
|
<Grid item xs={2}></Grid>
|
||||||
|
<Grid justifyContent="center" alignItems="center" item xs={"auto"}>
|
||||||
|
<List sx={{ width: '100%', minWidth: '60%', bgcolor: 'background.paper', border: "1px solid black", borderRadius: "5px" }}>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<PersonIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary="Hut" secondary="Connect+ QR-Code anzeigen" onClick={() => {console.log("connect?")}}/>
|
||||||
|
<Button sx={{ml: 4}} variant="outlined" color="info">Umbenennen</Button>
|
||||||
|
<Button sx={{ml: 1}} variant="outlined" color="error">Rauswerfen</Button>
|
||||||
|
<Button disabled sx={{ml: 1}} variant="outlined" color="primary"><QrCode/></Button>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<PersonIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary="Schubkarre" secondary="Connect+ QR-Code anzeigen" onClick={() => {}}/>
|
||||||
|
<Button sx={{ml: 4}} variant="outlined" color="info">Umbenennen</Button>
|
||||||
|
<Button sx={{ml: 1}} variant="outlined" color="error">Rauswerfen</Button>
|
||||||
|
<Button disabled sx={{ml: 1}} variant="outlined" color="primary"><QrCode/></Button>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<CloudIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary="Schuh" secondary="Connect+ verbunden" onClick={() => {}}/>
|
||||||
|
<Button sx={{ml: 4}} variant="outlined" color="info">Umbenennen</Button>
|
||||||
|
<Button sx={{ml: 1}} variant="outlined" color="error">Rauswerfen</Button>
|
||||||
|
<Button disabled sx={{ml: 1}} variant="outlined" color="primary"><QrCode/></Button>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
36
src/web/IPCRendererListener.ts
Normal file
36
src/web/IPCRendererListener.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import {IPCAnswer, IPCListenChannels} from "../RawConstants";
|
||||||
|
|
||||||
|
type IPCListen = {
|
||||||
|
channel: IPCListenChannels,
|
||||||
|
fn: (message: IPCAnswer, ...args: any) => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class IPCRendererListener {
|
||||||
|
private static attachments: Map<number, IPCListen> = new Map<number, IPCListen>();
|
||||||
|
private static uID = 99;
|
||||||
|
|
||||||
|
public static attach(event: IPCListenChannels, fn: (message: IPCAnswer, ...args: any) => void): number {
|
||||||
|
this.uID++;
|
||||||
|
this.attachments.set(this.uID, {fn: fn, channel: event});
|
||||||
|
return this.uID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static detach(id: number)
|
||||||
|
{
|
||||||
|
this.attachments.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static initialAttach()
|
||||||
|
{
|
||||||
|
for(let c of Object.keys(IPCListenChannels))
|
||||||
|
{
|
||||||
|
window.api.listen((c as unknown as IPCListenChannels), (event, message: IPCAnswer, ...args: any) => {
|
||||||
|
for(let [a, listener] of this.attachments)
|
||||||
|
{
|
||||||
|
listener.fn(message, ...args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
src/web/Player.ts
Normal file
4
src/web/Player.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export default class Player {
|
||||||
|
private nickname: string;
|
||||||
|
private figure: string;
|
||||||
|
}
|
@ -1,25 +1,416 @@
|
|||||||
import {Component} from "react";
|
import React, {Component} from "react";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Chip,
|
||||||
|
FormControl,
|
||||||
|
FormControlLabel,
|
||||||
|
FormGroup,
|
||||||
|
FormLabel,
|
||||||
|
Grid,
|
||||||
|
Snackbar,
|
||||||
|
Switch,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import RestartAltIcon from '@mui/icons-material/RestartAlt';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
import SaveIcon from '@mui/icons-material/Save';
|
||||||
|
import {PAGE} from "./App";
|
||||||
|
import {
|
||||||
|
Config,
|
||||||
|
GameInput,
|
||||||
|
GameRules,
|
||||||
|
GameSwitch,
|
||||||
|
GameSwitchNames,
|
||||||
|
IPCListenChannels,
|
||||||
|
NFCCard,
|
||||||
|
NFCCardType,
|
||||||
|
NFCPropertyCard,
|
||||||
|
PropertyColor
|
||||||
|
} from "../RawConstants";
|
||||||
|
import NfcIcon from "@mui/icons-material/Nfc";
|
||||||
|
import IPCRendererListener from "./IPCRendererListener";
|
||||||
|
import CardSetup from "./CardSetup";
|
||||||
|
|
||||||
|
|
||||||
interface InitialSetupState {
|
interface InitialSetupState {
|
||||||
|
open: boolean,
|
||||||
|
switchValues: GameSwitch[],
|
||||||
|
inputValues: GameInput[],
|
||||||
|
savedMsg: boolean,
|
||||||
|
openNFCModal: boolean,
|
||||||
|
nfcCard: NFCCard,
|
||||||
|
validCard: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultConf: InitialSetupState = {
|
||||||
|
open: true,
|
||||||
|
savedMsg: false,
|
||||||
|
openNFCModal: false,
|
||||||
|
nfcCard: null,
|
||||||
|
validCard: false,
|
||||||
|
switchValues: [
|
||||||
|
{
|
||||||
|
name: "GET_BONUS_PASSING_START",
|
||||||
|
label: "Über Los Bonus einziehen",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DOUBLE_BONUS_ON_GO",
|
||||||
|
label: "Wenn auf Los, doppelten Bonus einziehen",
|
||||||
|
depends: "GET_BONUS_PASSING_START",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PUT_PAID_PENALTIES_IN_MIDDLE",
|
||||||
|
label: "Gezahlte Strafen in die 'Mitte' legen",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "RECEIVE_PENALTIES_AT_FREE_PARKING",
|
||||||
|
label: "Bei 'Frei Parken' Strafen aus der 'Mitte' einziehen",
|
||||||
|
depends: "PUT_PAID_PENALTIES_IN_MIDDLE",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PUT_10_IN_MIDDLE_AFTER_EACH_GO",
|
||||||
|
label: "Nach jedem Los 10 in die Mitte",
|
||||||
|
depends: "PUT_PAID_PENALTIES_IN_MIDDLE",
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "STREET_MUST_BE_AUCTIONED_IF_NOT_PURCHASED",
|
||||||
|
label: "Straße muss versteigert werden bei Nichtkauf",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TWO_HOTELS_PER_STREET_ALLOWED",
|
||||||
|
label: "Zwei Hotels pro Straße erlaubt",
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MORTGAGE_REDUCES_RENT",
|
||||||
|
label: "Hypothek verringert Miete",
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GOODS_GO_TO_OTHER_PLAYERS_UPON_BANKRUPTCY",
|
||||||
|
label: "Güter gehen an anderen Spieler über bei Bankrott",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "STREETS_CAN_BE_SOLD_BACK_TO_THE_BANK",
|
||||||
|
label: "Straßen können zurück an die Bank verkauft werden",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PRISON_CAN_BE_PURCHASED_RENT_GOES_TO_PLAYER",
|
||||||
|
label: "Gefängnis kann erworben werden, Miete geht an den Spieler",
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KEEP_MONEY_MORE_SECRET",
|
||||||
|
label: "Geld von anderen Spielern ungenauer anzeigen",
|
||||||
|
value: false
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
inputValues: [
|
||||||
|
{
|
||||||
|
name: "STARTING_CASH",
|
||||||
|
type: "number",
|
||||||
|
label: "Start Guthaben",
|
||||||
|
value: "1500"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PASSING_GO_CASH",
|
||||||
|
type: "number",
|
||||||
|
label: "Lohn über Los",
|
||||||
|
value: "200"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PRISON_RELEASE_FEE",
|
||||||
|
type: "number",
|
||||||
|
label: "Gefängnis Gebühren",
|
||||||
|
value: "50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CURRENCY",
|
||||||
|
type: "text",
|
||||||
|
label: "Währung",
|
||||||
|
value: "€"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default class Setup extends Component<{}, InitialSetupState> {
|
export default class Setup extends Component<{}, InitialSetupState> {
|
||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
|
let x: NFCPropertyCard = {
|
||||||
|
cardType: NFCCardType.PROPERTY,
|
||||||
|
"name": "Test",
|
||||||
|
mortgageValue: 2,
|
||||||
|
rent: 100,
|
||||||
|
buyValue: 200,
|
||||||
|
specialProperties: "",
|
||||||
|
color: PropertyColor.BEIGE,
|
||||||
|
fullSetAmount: 2,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
...defaultConf,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset = () => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
...defaultConf
|
||||||
|
}))
|
||||||
|
|
||||||
|
//window.api.request("")
|
||||||
|
}
|
||||||
|
|
||||||
|
style = {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
width: '50%',
|
||||||
|
bgcolor: 'background.paper',
|
||||||
|
border: '2px solid #000',
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
onSwitch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const {name, checked} = event.target;
|
||||||
|
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
switchValues: prevState.switchValues.map((switchObj) => {
|
||||||
|
if (switchObj.name === name) {
|
||||||
|
return {
|
||||||
|
...switchObj,
|
||||||
|
value: checked
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return switchObj;
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
onInput = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const {name, value} = event.target;
|
||||||
|
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
inputValues: prevState.inputValues.map((switchObj) => {
|
||||||
|
if (switchObj.name === name) {
|
||||||
|
return {
|
||||||
|
...switchObj,
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return switchObj;
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
getSettings = () => {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
window.api.request("SETTINGS", {}).then(answer => {
|
||||||
|
try {
|
||||||
|
let data = answer.data as Config;
|
||||||
|
for (let [sw, state] of Object.entries(data.rules.switchValues)) {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
switchValues: prevState.switchValues.map((obj) => {
|
||||||
|
if (obj.name === sw) {
|
||||||
|
return {
|
||||||
|
...obj,
|
||||||
|
value: state
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
for (let [sw, state] of Object.entries(data.rules.inputValues)) {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
inputValues: prevState.inputValues.map((obj) => {
|
||||||
|
if (obj.name === sw) {
|
||||||
|
return {
|
||||||
|
...obj,
|
||||||
|
value: state
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSettings = (silent = false) => {
|
||||||
|
let gameSettings: any = {
|
||||||
|
switchValues: {},
|
||||||
|
inputValues: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
for (let ele of this.state.switchValues) {
|
||||||
|
gameSettings.switchValues[ele.name] = ele.value;
|
||||||
|
if (!!ele.depends && ele.value)
|
||||||
|
gameSettings.switchValues[ele.name] = this.checkDependsValue(ele.depends);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let ele of this.state.inputValues) {
|
||||||
|
gameSettings.inputValues[ele.name] = ele.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.api.request("SETTINGS", {data: {rules: gameSettings as GameRules}}).then();
|
||||||
|
|
||||||
|
if (!silent)
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
savedMsg: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onNFCRawEvent = (card: NFCCard|null, isComplete: boolean) => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
openNFCModal: true,
|
||||||
|
nfcCard: card,
|
||||||
|
validCard: isComplete
|
||||||
|
}));
|
||||||
|
console.log(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
private rawNFCListener: number = 0;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
||||||
|
this.rawNFCListener = IPCRendererListener.attach(IPCListenChannels.NFC_RAW, (message) => {
|
||||||
|
this.onNFCRawEvent(message.data, message.status);
|
||||||
|
console.log("Got an raw nfc event")
|
||||||
|
})
|
||||||
|
this.getSettings().then();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
IPCRendererListener.detach(this.rawNFCListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClose = () => {
|
||||||
|
window.app.toggleWiFiSettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDependsValue = (depends: GameSwitchNames) => {
|
||||||
|
for (let x of this.state.switchValues) {
|
||||||
|
if (x.name == depends)
|
||||||
|
return x.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <p>Test</p>
|
return <div className="setup">
|
||||||
|
<Snackbar
|
||||||
|
open={this.state.savedMsg}
|
||||||
|
autoHideDuration={6000}
|
||||||
|
onClose={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
savedMsg: false
|
||||||
|
}))
|
||||||
|
}}
|
||||||
|
message={"Einstellungen gespeichert!"}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{this.state.openNFCModal &&
|
||||||
|
<CardSetup card={this.state.nfcCard} validCard={this.state.validCard} closeCallback={() => this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
openNFCModal: false
|
||||||
|
}))}/>}
|
||||||
|
<Typography variant="h2" sx={{mb: 2}}>Einstellungen</Typography>
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControl component="fieldset" variant="standard">
|
||||||
|
<FormLabel component="legend">Schalter-Regeln</FormLabel>
|
||||||
|
<FormGroup>
|
||||||
|
{Object.values(this.state.switchValues).map(value => {
|
||||||
|
return (
|
||||||
|
<FormControlLabel key={value.name} sx={{mb: 1}}
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={(value.value && !value.depends) || (value.value && !!value.depends && this.checkDependsValue(value.depends))}
|
||||||
|
disabled={!!value.depends && !this.checkDependsValue(value.depends)}
|
||||||
|
onChange={this.onSwitch}
|
||||||
|
name={value.name}/>
|
||||||
|
} label={value.label}
|
||||||
|
/>)
|
||||||
|
})}
|
||||||
|
</FormGroup>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControl component="fieldset" variant="standard">
|
||||||
|
<FormLabel component="legend">Werte-Regeln</FormLabel>
|
||||||
|
<FormGroup>
|
||||||
|
{Object.values(this.state.inputValues).map(value => {
|
||||||
|
return (
|
||||||
|
<FormControlLabel key={value.name} sx={{mb: 2}}
|
||||||
|
control={
|
||||||
|
<TextField type={value.type} variant="standard"
|
||||||
|
value={value.value}
|
||||||
|
disabled={!!value.depends && !this.checkDependsValue(value.depends)}
|
||||||
|
onChange={this.onInput}
|
||||||
|
name={value.name}/>
|
||||||
|
} label={value.label}
|
||||||
|
/>)
|
||||||
|
})}
|
||||||
|
</FormGroup>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl sx={{mt: 5, mb: 1}} component="fieldset" variant="standard">
|
||||||
|
<FormLabel component="legend">Spielkarten</FormLabel>
|
||||||
|
<Typography sx={{ml: -2}} width={"95%"} variant="body1"><Chip
|
||||||
|
label={<div><NfcIcon sx={{marginTop: 0.9}} className={"animationBreathe"}
|
||||||
|
color="primary"/> NFC</div>} color="secondary"
|
||||||
|
variant="outlined"/><br/>Bitte die Karte an das Lesegerät halten, um sie zu
|
||||||
|
konfigurieren.<br/>Anschließend können die Einstellungen der Karte im Dialog angepasst
|
||||||
|
werden.</Typography>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={3.5}></Grid>
|
||||||
|
<Grid item xs={"auto"} alignItems="center">
|
||||||
|
<Button variant="contained" color="secondary" onClick={() => {
|
||||||
|
this.getSettings().then(r => window.app.setPage(PAGE.STARTUP));
|
||||||
|
}}>Abbrechen <CloseIcon/></Button>
|
||||||
|
<Button sx={{ml: 2}} variant="outlined" color="error"
|
||||||
|
onClick={() => this.reset()}>Zurücksetzen <RestartAltIcon/></Button>
|
||||||
|
<Button sx={{ml: 2}} variant="contained" color="success" onClick={() => {
|
||||||
|
this.saveSettings();
|
||||||
|
window.app.setPage(PAGE.STARTUP);
|
||||||
|
}}>Speichern <SaveIcon/></Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,41 +2,53 @@ import React, {Component} from "react";
|
|||||||
import {
|
import {
|
||||||
Backdrop,
|
Backdrop,
|
||||||
Box,
|
Box,
|
||||||
CircularProgress,
|
|
||||||
Fade,
|
|
||||||
Modal,
|
|
||||||
Stack,
|
|
||||||
Typography,
|
|
||||||
Button,
|
Button,
|
||||||
|
Chip,
|
||||||
|
CircularProgress,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle, DialogContent, DialogContentText, DialogActions, Chip, FormControl
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
Fade,
|
||||||
|
FormControl,
|
||||||
|
Modal,
|
||||||
|
Snackbar,
|
||||||
|
Stack,
|
||||||
|
Typography, Zoom
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import {FunctionTest} from "../IPCConstants";
|
import {FunctionTest} from "../RawConstants";
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
import PlayCircleIcon from '@mui/icons-material/PlayCircle';
|
import PlayCircleIcon from '@mui/icons-material/PlayCircle';
|
||||||
import CloudOffIcon from '@mui/icons-material/CloudOff';
|
import CloudOffIcon from '@mui/icons-material/CloudOff';
|
||||||
import CloudIcon from '@mui/icons-material/Cloud';
|
import CloudIcon from '@mui/icons-material/Cloud';
|
||||||
|
import {PAGE} from "./App";
|
||||||
|
import GameHandler from "./GameHandler";
|
||||||
|
|
||||||
|
interface StartupProps {
|
||||||
|
visible: boolean
|
||||||
|
}
|
||||||
|
|
||||||
interface StartupState {
|
interface StartupState {
|
||||||
statusTxt: string,
|
statusTxt: string,
|
||||||
openCloudConnectModal: boolean,
|
openCloudConnectModal: boolean,
|
||||||
showStartBtn: boolean,
|
showStartBtn: boolean,
|
||||||
isConnected: boolean,
|
isCloudConnected: boolean,
|
||||||
|
snackErrorMsg: string,
|
||||||
isConnectionIssue: boolean,
|
isConnectionIssue: boolean,
|
||||||
openWifiQuestion: boolean,
|
|
||||||
startCounter: number,
|
startCounter: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Startup extends Component<{}, StartupState> {
|
export default class Startup extends Component<StartupProps, StartupState> {
|
||||||
constructor(props: {}) {
|
constructor(props: StartupProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
statusTxt: "Smart-Monopoly wird gestartet...",
|
statusTxt: "Smart-Monopoly wird gestartet...",
|
||||||
openCloudConnectModal: false,
|
openCloudConnectModal: false,
|
||||||
showStartBtn: false,
|
showStartBtn: false,
|
||||||
isConnected: false,
|
isCloudConnected: false,
|
||||||
isConnectionIssue: false,
|
isConnectionIssue: false,
|
||||||
openWifiQuestion: false,
|
snackErrorMsg: "",
|
||||||
startCounter: 10,
|
startCounter: 10,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -50,7 +62,6 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
openCloudConnectModal: true,
|
openCloudConnectModal: true,
|
||||||
statusTxt: "Möchten Sie CloudConnect+ nutzen?"
|
statusTxt: "Möchten Sie CloudConnect+ nutzen?"
|
||||||
}));
|
}));
|
||||||
this.cloudDecision(true).then();
|
|
||||||
}, 1)
|
}, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,14 +72,46 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
connectToCloud = async (): Promise<boolean> => {
|
connectToCloud = async (): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
let response = await window.api.request("CLOUD_CONNECT", {});
|
let response = await window.api.request("CLOUD_CONNECT", {});
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
snackErrorMsg: "Fehler:" + response.data.toString(),
|
||||||
|
isCloudConnected: response.status,
|
||||||
|
isConnectionIssue: !response.status,
|
||||||
|
}));
|
||||||
|
console.log(response)
|
||||||
return response.status;
|
return response.status;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
snackErrorMsg: "Ein unerwarteter Fehler ist aufgetreten.",
|
||||||
|
}));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startupBtnClick = () => {
|
startupBtnClick = () => {
|
||||||
// Startup handle
|
// Startup handle
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
showStartBtn: false,
|
||||||
|
statusTxt: "Kapitalismus an die Macht!"
|
||||||
|
}));
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
let resp = await GameHandler.requestPreparing(this.state.isCloudConnected);
|
||||||
|
} catch(e)
|
||||||
|
{
|
||||||
|
this.setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
showStartBtn: true,
|
||||||
|
snackErrorMsg: "Start fehlgeschlagen! \n" + e.toString()
|
||||||
|
}));
|
||||||
|
await this.cloudDecision(false);
|
||||||
|
}
|
||||||
|
}, 1500)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
style = {
|
style = {
|
||||||
@ -84,14 +127,12 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async cloudDecision(decision: boolean) {
|
async cloudDecision(decision: boolean) {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
openWifiQuestion: false,
|
|
||||||
openCloudConnectModal: false,
|
openCloudConnectModal: false,
|
||||||
isConnectionIssue: false,
|
isConnectionIssue: false,
|
||||||
isConnected: false,
|
isCloudConnected: false,
|
||||||
startCounter: 30
|
startCounter: 30
|
||||||
}));
|
}));
|
||||||
clearInterval(this.counterInterval);
|
clearInterval(this.counterInterval);
|
||||||
@ -107,8 +148,8 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
if (!status.hasInternet) {
|
if (!status.hasInternet) {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
openWifiQuestion: true, // Weiterleiten auf WiFiFrage
|
isConnectionIssue: true, // Weiterleiten auf Fehlermodal
|
||||||
statusTxt: "Warten auf Netzwerkkonfiguration..."
|
statusTxt: "Warten auf Netzwerk..."
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
@ -119,73 +160,65 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
this.connectToCloud().then((connected) => {
|
this.connectToCloud().then((connected) => {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
statusTxt: "Bereit zum spielen?",
|
statusTxt: "Bereit zum Spielen?",
|
||||||
showStartBtn: true,
|
showStartBtn: true,
|
||||||
isConnectionIssue: !connected,
|
|
||||||
isConnected: connected
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
if(connected)
|
if (connected)
|
||||||
this.counterInterval = setInterval(() => {
|
this.counterInterval = setInterval(() => {
|
||||||
this.setState((prevState) => ({
|
if (!this.props.visible) return;
|
||||||
...prevState,
|
|
||||||
startCounter: prevState.startCounter-1
|
if (this.state.startCounter == 0) {
|
||||||
}));
|
|
||||||
if(this.state.startCounter == 0) {
|
|
||||||
clearInterval(this.counterInterval);
|
clearInterval(this.counterInterval);
|
||||||
this.startupBtnClick();
|
this.startupBtnClick();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
startCounter: prevState.startCounter - 1
|
||||||
|
}));
|
||||||
|
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
statusTxt: "Bereit zum spielen?",
|
statusTxt: "Bereit zum Spielen?",
|
||||||
showStartBtn: true,
|
showStartBtn: true,
|
||||||
startCounter: 30
|
startCounter: 30
|
||||||
}));
|
}));
|
||||||
this.counterInterval = setInterval(() => {
|
this.counterInterval = setInterval(() => {
|
||||||
this.setState((prevState) => ({
|
if (!this.props.visible) return;
|
||||||
...prevState,
|
|
||||||
startCounter: prevState.startCounter-1
|
if (this.state.startCounter == 0) {
|
||||||
}));
|
|
||||||
if(this.state.startCounter == 0) {
|
|
||||||
clearInterval(this.counterInterval);
|
clearInterval(this.counterInterval);
|
||||||
this.startupBtnClick();
|
this.startupBtnClick();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
startCounter: prevState.startCounter - 1
|
||||||
|
}));
|
||||||
|
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div className="startup">
|
return <div className={`startup ${this.props.visible ? '' : 'hidden'}`}>
|
||||||
<Dialog
|
<Snackbar
|
||||||
open={this.state.openWifiQuestion}
|
open={this.state.snackErrorMsg != ""}
|
||||||
onClose={null}
|
autoHideDuration={8000}
|
||||||
aria-labelledby="alert-dialog-title"
|
onClose={() => {
|
||||||
aria-describedby="alert-dialog-description"
|
this.setState(prevState => ({
|
||||||
>
|
...prevState,
|
||||||
<DialogTitle id="alert-dialog-title">
|
snackErrorMsg: ""
|
||||||
Keine Internetverbindung!
|
}))
|
||||||
</DialogTitle>
|
}}
|
||||||
<DialogContent>
|
message={this.state.snackErrorMsg}
|
||||||
<DialogContentText id="alert-dialog-description">
|
/>
|
||||||
Es wurde keine Internetverbindung erkannt.<br/><br/>
|
|
||||||
<strong>Möchten Sie eine WLAN-Verbindung einrichten?</strong>
|
|
||||||
<br/><i>Andernfalls können Sie SmartMonopoly offline nutzen.</i>
|
|
||||||
</DialogContentText>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={() => this.cloudDecision(false)}>
|
|
||||||
Offline nutzen
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => {
|
|
||||||
window.app.toggleWiFiSettings(true)
|
|
||||||
}} autoFocus>Einrichten</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
<Dialog
|
<Dialog
|
||||||
open={this.state.isConnectionIssue}
|
open={this.state.isConnectionIssue}
|
||||||
onClose={null}
|
onClose={null}
|
||||||
@ -237,7 +270,8 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
<i>Dafür wird eine WiFi-Verbindung hergestellt</i>
|
<i>Dafür wird eine WiFi-Verbindung hergestellt</i>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<Button variant="contained" sx={{mr: 1}} onClick={() => this.cloudDecision(true)}>Ja</Button>
|
<Button variant="contained" sx={{mr: 1}}
|
||||||
|
onClick={() => this.cloudDecision(true)}>Ja</Button>
|
||||||
<Button variant="contained" onClick={() => this.cloudDecision(false)}
|
<Button variant="contained" onClick={() => this.cloudDecision(false)}
|
||||||
color="error">Nein</Button>
|
color="error">Nein</Button>
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -245,25 +279,33 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
</Fade>
|
</Fade>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Stack alignItems="center" sx={{width: '100%'}}>
|
<Stack className="centerMiddle" alignItems="center">
|
||||||
<h1>Willkommen!</h1>
|
<h1>Willkommen!</h1>
|
||||||
<br/>
|
<br/>
|
||||||
<p>{this.state.statusTxt}</p>
|
<p>{this.state.statusTxt}</p>
|
||||||
<br/>
|
<br/>
|
||||||
{!this.state.showStartBtn && <CircularProgress/>}
|
{!this.state.showStartBtn && <CircularProgress/>}
|
||||||
|
|
||||||
<Box alignItems="center" sx={{width: '100%', ml: 10}}>
|
<Box alignItems="center" sx={{width: '100%'}}>
|
||||||
<FormControl sx={{mr: 2, minWidth: '30%'}}>
|
<FormControl sx={{mr: 2, minWidth: '30%'}}>
|
||||||
{this.state.showStartBtn && <Button color="secondary" variant="contained">Setup <SettingsIcon/></Button>}
|
<Zoom in={this.state.showStartBtn}><Button color="secondary"
|
||||||
|
onClick={() => window.app.setPage(PAGE.SETUP)}
|
||||||
|
variant="contained">Einstellungen <SettingsIcon/></Button></Zoom>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl sx={{minWidth: '30%'}}>
|
<FormControl sx={{minWidth: '30%'}}>
|
||||||
{this.state.showStartBtn && <Button color="success" variant="contained">Start <Chip sx={{ml: 1}} size="small" label={this.state.startCounter} /> <PlayCircleIcon/></Button>}
|
<Zoom in={this.state.showStartBtn}><Button color="success"
|
||||||
|
onClick={() => this.startupBtnClick()}
|
||||||
|
variant="contained">Start <Chip sx={{ml: 1}}
|
||||||
|
size="small"
|
||||||
|
label={this.state.startCounter}/>
|
||||||
|
<PlayCircleIcon/></Button></Zoom>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
<Chip sx={{mt: 3}} color={this.state.isConnected ? "success" : "default"} onClick={() => this.setState(prevState => ({
|
<Chip sx={{mt: 3}} color={this.state.isCloudConnected ? "success" : "default"}
|
||||||
|
disabled={!this.state.showStartBtn} onClick={() => this.setState(prevState => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
openCloudConnectModal: true
|
openCloudConnectModal: true
|
||||||
}))} label={this.state.isConnected ? <CloudIcon/> : <CloudOffIcon />}/>
|
}))} label={this.state.isCloudConnected ? <CloudIcon/> : <CloudOffIcon/>}/>
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
|
|
||||||
import WifiPasswordIcon from "@mui/icons-material/WifiPassword";
|
import WifiPasswordIcon from "@mui/icons-material/WifiPassword";
|
||||||
import WifiIcon from "@mui/icons-material/Wifi";
|
import WifiIcon from "@mui/icons-material/Wifi";
|
||||||
import {IPCAnswer, WiFiNetwork} from "../IPCConstants";
|
import {IPCAnswer, WiFiNetwork} from "../RawConstants";
|
||||||
|
|
||||||
|
|
||||||
interface WiFiState {
|
interface WiFiState {
|
||||||
@ -26,7 +26,8 @@ interface WiFiState {
|
|||||||
selectedSecured: boolean,
|
selectedSecured: boolean,
|
||||||
foundWiFis: WiFiNetwork[],
|
foundWiFis: WiFiNetwork[],
|
||||||
scanning: boolean,
|
scanning: boolean,
|
||||||
status: status
|
status: status,
|
||||||
|
password: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
type status = "NONE" | "SELECTION_FAILURE" | "CONNECTING" | "PASSWORD_NEEDED" | "FAILURE" | "CONNECTED" | 'SCAN_FAILURE';
|
type status = "NONE" | "SELECTION_FAILURE" | "CONNECTING" | "PASSWORD_NEEDED" | "FAILURE" | "CONNECTED" | 'SCAN_FAILURE';
|
||||||
@ -41,6 +42,7 @@ export default class WiFi extends Component<{}, WiFiState> {
|
|||||||
foundWiFis: [],
|
foundWiFis: [],
|
||||||
scanning: false,
|
scanning: false,
|
||||||
status: "NONE",
|
status: "NONE",
|
||||||
|
password: "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +102,7 @@ export default class WiFi extends Component<{}, WiFiState> {
|
|||||||
...prevState,
|
...prevState,
|
||||||
status: "CONNECTING"
|
status: "CONNECTING"
|
||||||
}));
|
}));
|
||||||
window.api.request('WIFI_CONNECT', {data: this.state.currentSelection}).then((answer: IPCAnswer) => {
|
window.api.request('WIFI_CONNECT', {data: {ssid: this.state.currentSelection, psk: this.state.password}}).then((answer: IPCAnswer) => {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
status: answer.status ? "CONNECTED" : "FAILURE"
|
status: answer.status ? "CONNECTED" : "FAILURE"
|
||||||
@ -149,9 +151,10 @@ export default class WiFi extends Component<{}, WiFiState> {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Typography id="transition-modal-description" sx={{mt: 2}}>
|
<Typography id="transition-modal-description" sx={{mt: 2}}>
|
||||||
<Alert variant={this.state.status == "FAILURE" ? "filled" : "standard"}
|
<Alert variant={this.state.status == "FAILURE" ? "filled" : "standard"}
|
||||||
severity={this.state.status.includes("FAILURE") ? "error" : "info"}>
|
severity={this.state.status.includes("FAILURE") ? "error" : (this.state.status == "CONNECTED" ? "success" : "info")}>
|
||||||
{this.state.status == "NONE" && "Bitte wählen Sie eins der folgenden Netzwerke aus"}
|
{this.state.status == "NONE" && "Bitte wählen Sie eins der folgenden Netzwerke aus"}
|
||||||
{this.state.status == "CONNECTING" && "Verbinden..." }
|
{this.state.status == "CONNECTING" && "Verbinden..." }
|
||||||
|
{this.state.status == "CONNECTED" && "Verbunden!" }
|
||||||
{this.state.status == "SCAN_FAILURE" && "Das Scannen ist fehlgeschlagen. - Möglicherweise fehlen Berechtigungen, um Netzwerke zu scannen, oder es befindet sich kein WLAN-Interface auf diesem Gerät." }
|
{this.state.status == "SCAN_FAILURE" && "Das Scannen ist fehlgeschlagen. - Möglicherweise fehlen Berechtigungen, um Netzwerke zu scannen, oder es befindet sich kein WLAN-Interface auf diesem Gerät." }
|
||||||
{this.state.status == "FAILURE" && "Verbindungsfehler!" }
|
{this.state.status == "FAILURE" && "Verbindungsfehler!" }
|
||||||
{this.state.status == "SELECTION_FAILURE" && "Bitte zunächst ein Netzwerk auswählen!" }
|
{this.state.status == "SELECTION_FAILURE" && "Bitte zunächst ein Netzwerk auswählen!" }
|
||||||
@ -193,7 +196,10 @@ export default class WiFi extends Component<{}, WiFiState> {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl sx={{m: 1, minWidth: '70%'}}>
|
<FormControl sx={{m: 1, minWidth: '70%'}}>
|
||||||
<TextField id="password" label="Passwort" disabled={this.state.scanning || !this.state.selectedSecured} variant="outlined" />
|
<TextField id="password" value={this.state.password} onChange={evt => this.setState(prev => ({
|
||||||
|
...prev,
|
||||||
|
password: evt.target.value
|
||||||
|
}))} label="Passwort" disabled={this.state.scanning || !this.state.selectedSecured} variant="outlined" />
|
||||||
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
@ -219,7 +225,7 @@ export default class WiFi extends Component<{}, WiFiState> {
|
|||||||
<FormControl sx={{ml: 2, minWidth: '20%'}}>
|
<FormControl sx={{ml: 2, minWidth: '20%'}}>
|
||||||
<Button variant="contained" disabled={this.state.status == "CONNECTING"}
|
<Button variant="contained" disabled={this.state.status == "CONNECTING"}
|
||||||
onClick={() => this.handleClose()}
|
onClick={() => this.handleClose()}
|
||||||
color="error">Abbrechen</Button>
|
color="secondary">Schließen</Button>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,6 +1,44 @@
|
|||||||
.startup {
|
.centerMiddle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
width: 99%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animationBreathe {
|
||||||
|
animation: breathing 2.5s ease-out infinite normal;
|
||||||
|
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes breathing {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale(0.9);
|
||||||
|
-ms-transform: scale(0.9);
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
-webkit-transform: scale(1.2);
|
||||||
|
-ms-transform: scale(1.2);
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
-webkit-transform: scale(0.9);
|
||||||
|
-ms-transform: scale(0.9);
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale(0.9);
|
||||||
|
-ms-transform: scale(0.9);
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
import {IPCAnswer, IPCChannel, IPCRequest} from "../IPCConstants";
|
import {IPCAnswer, IPCChannel, IPCListenChannels, IPCRequest} from "../RawConstants";
|
||||||
import IpcRendererEvent = Electron.IpcRendererEvent;
|
import IpcRendererEvent = Electron.IpcRendererEvent;
|
||||||
import {App} from "./App"
|
import {App} from "./App";
|
||||||
|
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
"api": {
|
"api": {
|
||||||
request: (channel: IPCChannel, request: IPCRequest, ...args: any) => Promise<IPCAnswer>;
|
request: (channel: IPCChannel, request: IPCRequest, ...args: any) => Promise<IPCAnswer>;
|
||||||
listen: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => void;
|
listen: (channel: IPCListenChannels, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => void;
|
||||||
}
|
}
|
||||||
app: App;
|
app: App;
|
||||||
}
|
}
|
||||||
|
157
yarn.lock
157
yarn.lock
@ -840,6 +840,14 @@
|
|||||||
mkdirp "^1.0.4"
|
mkdirp "^1.0.4"
|
||||||
rimraf "^3.0.2"
|
rimraf "^3.0.2"
|
||||||
|
|
||||||
|
"@pokusew/pcsclite@^0.6.0":
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@pokusew/pcsclite/-/pcsclite-0.6.0.tgz#30ae3fbf9d1137f2a1b343c32cd8569be581ba2d"
|
||||||
|
integrity sha512-jX7zRXM2Or5Pms1AFjNtawsXDjLiZOzOUo7Sf0put7Pnq/EKIR9g0KvTx62HtwdPpVP6hWHGydUTHgIi9PxodQ==
|
||||||
|
dependencies:
|
||||||
|
bindings "^1.5.0"
|
||||||
|
nan "^2.14.0"
|
||||||
|
|
||||||
"@popperjs/core@^2.11.8":
|
"@popperjs/core@^2.11.8":
|
||||||
version "2.11.8"
|
version "2.11.8"
|
||||||
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
|
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
|
||||||
@ -1142,6 +1150,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/websocket@^1.0.10":
|
||||||
|
version "1.0.10"
|
||||||
|
resolved "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.10.tgz"
|
||||||
|
integrity sha512-svjGZvPB7EzuYS94cI7a+qhwgGU1y89wUgjT6E2wVUfmAGIvRfT7obBvRtnhXCSsoMdlG4gBFGE7MfkIXZLoww==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/ws@^8.5.5":
|
"@types/ws@^8.5.5":
|
||||||
version "8.5.10"
|
version "8.5.10"
|
||||||
resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz"
|
resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz"
|
||||||
@ -1693,6 +1708,13 @@ binary-extensions@^2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
||||||
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
|
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
|
||||||
|
|
||||||
|
bindings@^1.5.0:
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||||
|
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
|
||||||
|
dependencies:
|
||||||
|
file-uri-to-path "1.0.0"
|
||||||
|
|
||||||
bl@^4.1.0:
|
bl@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz"
|
resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz"
|
||||||
@ -1793,6 +1815,13 @@ buffer@^5.5.0:
|
|||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.1.13"
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
|
bufferutil@^4.0.1:
|
||||||
|
version "4.0.8"
|
||||||
|
resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz"
|
||||||
|
integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==
|
||||||
|
dependencies:
|
||||||
|
node-gyp-build "^4.3.0"
|
||||||
|
|
||||||
bytes@3.0.0:
|
bytes@3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz"
|
||||||
@ -2223,6 +2252,14 @@ csstype@^3.0.2, csstype@^3.1.3:
|
|||||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||||
|
|
||||||
|
d@1, d@^1.0.1, d@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.npmjs.org/d/-/d-1.0.2.tgz"
|
||||||
|
integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==
|
||||||
|
dependencies:
|
||||||
|
es5-ext "^0.10.64"
|
||||||
|
type "^2.7.2"
|
||||||
|
|
||||||
data-view-buffer@^1.0.1:
|
data-view-buffer@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz"
|
||||||
@ -2697,11 +2734,38 @@ es-to-primitive@^1.2.1:
|
|||||||
is-date-object "^1.0.1"
|
is-date-object "^1.0.1"
|
||||||
is-symbol "^1.0.2"
|
is-symbol "^1.0.2"
|
||||||
|
|
||||||
|
es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14:
|
||||||
|
version "0.10.64"
|
||||||
|
resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz"
|
||||||
|
integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==
|
||||||
|
dependencies:
|
||||||
|
es6-iterator "^2.0.3"
|
||||||
|
es6-symbol "^3.1.3"
|
||||||
|
esniff "^2.0.1"
|
||||||
|
next-tick "^1.1.0"
|
||||||
|
|
||||||
es6-error@^4.1.1:
|
es6-error@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz"
|
resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz"
|
||||||
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
|
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
|
||||||
|
|
||||||
|
es6-iterator@^2.0.3:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz"
|
||||||
|
integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==
|
||||||
|
dependencies:
|
||||||
|
d "1"
|
||||||
|
es5-ext "^0.10.35"
|
||||||
|
es6-symbol "^3.1.1"
|
||||||
|
|
||||||
|
es6-symbol@^3.1.1, es6-symbol@^3.1.3:
|
||||||
|
version "3.1.4"
|
||||||
|
resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz"
|
||||||
|
integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==
|
||||||
|
dependencies:
|
||||||
|
d "^1.0.2"
|
||||||
|
ext "^1.7.0"
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz"
|
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz"
|
||||||
@ -2826,6 +2890,16 @@ eslint@^8.0.1:
|
|||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
text-table "^0.2.0"
|
text-table "^0.2.0"
|
||||||
|
|
||||||
|
esniff@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz"
|
||||||
|
integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==
|
||||||
|
dependencies:
|
||||||
|
d "^1.0.1"
|
||||||
|
es5-ext "^0.10.62"
|
||||||
|
event-emitter "^0.3.5"
|
||||||
|
type "^2.7.2"
|
||||||
|
|
||||||
espree@^9.6.0, espree@^9.6.1:
|
espree@^9.6.0, espree@^9.6.1:
|
||||||
version "9.6.1"
|
version "9.6.1"
|
||||||
resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz"
|
resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz"
|
||||||
@ -2869,6 +2943,14 @@ etag@~1.8.1:
|
|||||||
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
|
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
|
||||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||||
|
|
||||||
|
event-emitter@^0.3.5:
|
||||||
|
version "0.3.5"
|
||||||
|
resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz"
|
||||||
|
integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==
|
||||||
|
dependencies:
|
||||||
|
d "1"
|
||||||
|
es5-ext "~0.10.14"
|
||||||
|
|
||||||
eventemitter3@^4.0.0:
|
eventemitter3@^4.0.0:
|
||||||
version "4.0.7"
|
version "4.0.7"
|
||||||
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz"
|
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz"
|
||||||
@ -2963,6 +3045,13 @@ express@^4.17.1, express@^4.17.3:
|
|||||||
utils-merge "1.0.1"
|
utils-merge "1.0.1"
|
||||||
vary "~1.1.2"
|
vary "~1.1.2"
|
||||||
|
|
||||||
|
ext@^1.7.0:
|
||||||
|
version "1.7.0"
|
||||||
|
resolved "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz"
|
||||||
|
integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==
|
||||||
|
dependencies:
|
||||||
|
type "^2.7.2"
|
||||||
|
|
||||||
extract-zip@^2.0.0, extract-zip@^2.0.1:
|
extract-zip@^2.0.0, extract-zip@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz"
|
resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz"
|
||||||
@ -3028,6 +3117,11 @@ file-entry-cache@^6.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flat-cache "^3.0.4"
|
flat-cache "^3.0.4"
|
||||||
|
|
||||||
|
file-uri-to-path@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||||
|
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||||
|
|
||||||
filename-reserved-regex@^2.0.0:
|
filename-reserved-regex@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz"
|
||||||
@ -3978,6 +4072,11 @@ is-typed-array@^1.1.13:
|
|||||||
dependencies:
|
dependencies:
|
||||||
which-typed-array "^1.1.14"
|
which-typed-array "^1.1.14"
|
||||||
|
|
||||||
|
is-typedarray@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz"
|
||||||
|
integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
|
||||||
|
|
||||||
is-unicode-supported@^0.1.0:
|
is-unicode-supported@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz"
|
resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz"
|
||||||
@ -4540,6 +4639,11 @@ multicast-dns@^7.2.5:
|
|||||||
dns-packet "^5.2.2"
|
dns-packet "^5.2.2"
|
||||||
thunky "^1.0.2"
|
thunky "^1.0.2"
|
||||||
|
|
||||||
|
nan@^2.14.0:
|
||||||
|
version "2.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0"
|
||||||
|
integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==
|
||||||
|
|
||||||
nanoid@^3.3.7:
|
nanoid@^3.3.7:
|
||||||
version "3.3.7"
|
version "3.3.7"
|
||||||
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz"
|
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz"
|
||||||
@ -4565,6 +4669,18 @@ neo-async@^2.6.2:
|
|||||||
resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz"
|
resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz"
|
||||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||||
|
|
||||||
|
next-tick@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz"
|
||||||
|
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
|
||||||
|
|
||||||
|
nfc-pcsc@^0.8.1:
|
||||||
|
version "0.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/nfc-pcsc/-/nfc-pcsc-0.8.1.tgz#76882be17842cb832a72b76345e665c8108ff049"
|
||||||
|
integrity sha512-wEfacG0dwPVZOG/WY28Mk3P4Q+yz6q7LnjpnZvdFddx3iXavEXiGhftRZXBtudr0NrzH1MrGWSkWq77tef7BMA==
|
||||||
|
dependencies:
|
||||||
|
"@pokusew/pcsclite" "^0.6.0"
|
||||||
|
|
||||||
nice-try@^1.0.4:
|
nice-try@^1.0.4:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz"
|
resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz"
|
||||||
@ -4609,6 +4725,11 @@ node-forge@^1:
|
|||||||
resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz"
|
resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz"
|
||||||
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
|
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
|
||||||
|
|
||||||
|
node-gyp-build@^4.3.0:
|
||||||
|
version "4.8.0"
|
||||||
|
resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz"
|
||||||
|
integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==
|
||||||
|
|
||||||
node-gyp@^9.0.0:
|
node-gyp@^9.0.0:
|
||||||
version "9.4.1"
|
version "9.4.1"
|
||||||
resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz"
|
resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz"
|
||||||
@ -6193,6 +6314,11 @@ type-is@~1.6.18:
|
|||||||
media-typer "0.3.0"
|
media-typer "0.3.0"
|
||||||
mime-types "~2.1.24"
|
mime-types "~2.1.24"
|
||||||
|
|
||||||
|
type@^2.7.2:
|
||||||
|
version "2.7.2"
|
||||||
|
resolved "https://registry.npmjs.org/type/-/type-2.7.2.tgz"
|
||||||
|
integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==
|
||||||
|
|
||||||
typed-array-buffer@^1.0.2:
|
typed-array-buffer@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz"
|
||||||
@ -6237,6 +6363,13 @@ typed-array-length@^1.0.5:
|
|||||||
is-typed-array "^1.1.13"
|
is-typed-array "^1.1.13"
|
||||||
possible-typed-array-names "^1.0.0"
|
possible-typed-array-names "^1.0.0"
|
||||||
|
|
||||||
|
typedarray-to-buffer@^3.1.5:
|
||||||
|
version "3.1.5"
|
||||||
|
resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz"
|
||||||
|
integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
|
||||||
|
dependencies:
|
||||||
|
is-typedarray "^1.0.0"
|
||||||
|
|
||||||
typescript@~4.5.4:
|
typescript@~4.5.4:
|
||||||
version "4.5.5"
|
version "4.5.5"
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz"
|
||||||
@ -6309,6 +6442,13 @@ username@^5.1.0:
|
|||||||
execa "^1.0.0"
|
execa "^1.0.0"
|
||||||
mem "^4.3.0"
|
mem "^4.3.0"
|
||||||
|
|
||||||
|
utf-8-validate@^5.0.2:
|
||||||
|
version "5.0.10"
|
||||||
|
resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz"
|
||||||
|
integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==
|
||||||
|
dependencies:
|
||||||
|
node-gyp-build "^4.3.0"
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||||
@ -6479,6 +6619,18 @@ websocket-extensions@>=0.1.1:
|
|||||||
resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz"
|
resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz"
|
||||||
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
|
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
|
||||||
|
|
||||||
|
websocket@^1.0.34:
|
||||||
|
version "1.0.34"
|
||||||
|
resolved "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz"
|
||||||
|
integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==
|
||||||
|
dependencies:
|
||||||
|
bufferutil "^4.0.1"
|
||||||
|
debug "^2.2.0"
|
||||||
|
es5-ext "^0.10.50"
|
||||||
|
typedarray-to-buffer "^3.1.5"
|
||||||
|
utf-8-validate "^5.0.2"
|
||||||
|
yaeti "^0.0.6"
|
||||||
|
|
||||||
whatwg-url@^5.0.0:
|
whatwg-url@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz"
|
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz"
|
||||||
@ -6598,6 +6750,11 @@ y18n@^5.0.5:
|
|||||||
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
||||||
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||||
|
|
||||||
|
yaeti@^0.0.6:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz"
|
||||||
|
integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==
|
||||||
|
|
||||||
yallist@^4.0.0:
|
yallist@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
|
||||||
|
Reference in New Issue
Block a user