Compare commits
No commits in common. "39a514b2cc64ca2c7a8a8e2fe3d5508fa4dac225" and "1f08a4885b93850605ad6795333909d260e36c46" have entirely different histories.
39a514b2cc
...
1f08a4885b
@ -123,10 +123,6 @@ const resolve = (plugins = []) => {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
extensions: [ ".tsx", '.ts', '.js' ],
|
extensions: [ ".tsx", '.ts', '.js' ],
|
||||||
fallback: {
|
|
||||||
'react/jsx-runtime': 'react/jsx-runtime.js',
|
|
||||||
'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js',
|
|
||||||
},
|
|
||||||
plugins: plugins
|
plugins: plugins
|
||||||
};
|
};
|
||||||
|
|
||||||
|
190
package-lock.json
generated
190
package-lock.json
generated
@ -16,8 +16,6 @@
|
|||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"gl-matrix": "^3.4.3",
|
"gl-matrix": "^3.4.3",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dnd": "^16.0.1",
|
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
@ -728,17 +726,6 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
|
||||||
"version": "7.17.9",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.9.tgz",
|
|
||||||
"integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==",
|
|
||||||
"dependencies": {
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@discoveryjs/json-ext": {
|
"node_modules/@discoveryjs/json-ext": {
|
||||||
"version": "0.5.6",
|
"version": "0.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
|
||||||
@ -1036,21 +1023,6 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-dnd/asap": {
|
|
||||||
"version": "5.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@react-dnd/asap/-/asap-5.0.2.tgz",
|
|
||||||
"integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A=="
|
|
||||||
},
|
|
||||||
"node_modules/@react-dnd/invariant": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@react-dnd/invariant/-/invariant-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw=="
|
|
||||||
},
|
|
||||||
"node_modules/@react-dnd/shallowequal": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA=="
|
|
||||||
},
|
|
||||||
"node_modules/@sindresorhus/is": {
|
"node_modules/@sindresorhus/is": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||||
@ -1223,7 +1195,7 @@
|
|||||||
"version": "17.0.21",
|
"version": "17.0.21",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
|
||||||
"integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
|
"integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
|
||||||
"devOptional": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/normalize-package-data": {
|
"node_modules/@types/normalize-package-data": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
@ -2845,16 +2817,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dnd-core": {
|
|
||||||
"version": "16.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/dnd-core/-/dnd-core-16.0.1.tgz",
|
|
||||||
"integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==",
|
|
||||||
"dependencies": {
|
|
||||||
"@react-dnd/asap": "^5.0.1",
|
|
||||||
"@react-dnd/invariant": "^4.0.1",
|
|
||||||
"redux": "^4.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dns-equal": {
|
"node_modules/dns-equal": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||||
@ -3355,7 +3317,8 @@
|
|||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.2.11",
|
"version": "3.2.11",
|
||||||
@ -3982,14 +3945,6 @@
|
|||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hoist-non-react-statics": {
|
|
||||||
"version": "3.3.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
|
||||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
|
||||||
"dependencies": {
|
|
||||||
"react-is": "^16.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hosted-git-info": {
|
"node_modules/hosted-git-info": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
|
||||||
@ -6209,43 +6164,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dnd": {
|
|
||||||
"version": "16.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-dnd/-/react-dnd-16.0.1.tgz",
|
|
||||||
"integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"@react-dnd/invariant": "^4.0.1",
|
|
||||||
"@react-dnd/shallowequal": "^4.0.1",
|
|
||||||
"dnd-core": "^16.0.1",
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"hoist-non-react-statics": "^3.3.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/hoist-non-react-statics": ">= 3.3.1",
|
|
||||||
"@types/node": ">= 12",
|
|
||||||
"@types/react": ">= 16",
|
|
||||||
"react": ">= 16.14"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/hoist-non-react-statics": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/node": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-dnd-html5-backend": {
|
|
||||||
"version": "16.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz",
|
|
||||||
"integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==",
|
|
||||||
"dependencies": {
|
|
||||||
"dnd-core": "^16.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||||
@ -6259,11 +6177,6 @@
|
|||||||
"react": "17.0.2"
|
"react": "17.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-is": {
|
|
||||||
"version": "16.13.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
|
||||||
},
|
|
||||||
"node_modules/read-pkg": {
|
"node_modules/read-pkg": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||||
@ -6392,19 +6305,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/redux": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/redux/-/redux-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.9.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/regenerator-runtime": {
|
|
||||||
"version": "0.13.9",
|
|
||||||
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
|
||||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
|
||||||
},
|
|
||||||
"node_modules/regexp.prototype.flags": {
|
"node_modules/regexp.prototype.flags": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
|
||||||
@ -8867,14 +8767,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime": {
|
|
||||||
"version": "7.17.9",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.9.tgz",
|
|
||||||
"integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==",
|
|
||||||
"requires": {
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@discoveryjs/json-ext": {
|
"@discoveryjs/json-ext": {
|
||||||
"version": "0.5.6",
|
"version": "0.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
|
||||||
@ -9121,21 +9013,6 @@
|
|||||||
"rimraf": "^3.0.2"
|
"rimraf": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@react-dnd/asap": {
|
|
||||||
"version": "5.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@react-dnd/asap/-/asap-5.0.2.tgz",
|
|
||||||
"integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A=="
|
|
||||||
},
|
|
||||||
"@react-dnd/invariant": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@react-dnd/invariant/-/invariant-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw=="
|
|
||||||
},
|
|
||||||
"@react-dnd/shallowequal": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA=="
|
|
||||||
},
|
|
||||||
"@sindresorhus/is": {
|
"@sindresorhus/is": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||||
@ -9299,7 +9176,7 @@
|
|||||||
"version": "17.0.21",
|
"version": "17.0.21",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
|
||||||
"integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
|
"integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
|
||||||
"devOptional": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/normalize-package-data": {
|
"@types/normalize-package-data": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
@ -10611,16 +10488,6 @@
|
|||||||
"path-type": "^4.0.0"
|
"path-type": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dnd-core": {
|
|
||||||
"version": "16.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/dnd-core/-/dnd-core-16.0.1.tgz",
|
|
||||||
"integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==",
|
|
||||||
"requires": {
|
|
||||||
"@react-dnd/asap": "^5.0.1",
|
|
||||||
"@react-dnd/invariant": "^4.0.1",
|
|
||||||
"redux": "^4.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dns-equal": {
|
"dns-equal": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||||
@ -11038,7 +10905,8 @@
|
|||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "3.2.11",
|
"version": "3.2.11",
|
||||||
@ -11516,14 +11384,6 @@
|
|||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"hoist-non-react-statics": {
|
|
||||||
"version": "3.3.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
|
||||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
|
||||||
"requires": {
|
|
||||||
"react-is": "^16.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hosted-git-info": {
|
"hosted-git-info": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
|
||||||
@ -13191,26 +13051,6 @@
|
|||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-dnd": {
|
|
||||||
"version": "16.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-dnd/-/react-dnd-16.0.1.tgz",
|
|
||||||
"integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==",
|
|
||||||
"requires": {
|
|
||||||
"@react-dnd/invariant": "^4.0.1",
|
|
||||||
"@react-dnd/shallowequal": "^4.0.1",
|
|
||||||
"dnd-core": "^16.0.1",
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"hoist-non-react-statics": "^3.3.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"react-dnd-html5-backend": {
|
|
||||||
"version": "16.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz",
|
|
||||||
"integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==",
|
|
||||||
"requires": {
|
|
||||||
"dnd-core": "^16.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||||
@ -13221,11 +13061,6 @@
|
|||||||
"scheduler": "^0.20.2"
|
"scheduler": "^0.20.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-is": {
|
|
||||||
"version": "16.13.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
|
||||||
},
|
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||||
@ -13328,19 +13163,6 @@
|
|||||||
"strip-indent": "^3.0.0"
|
"strip-indent": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redux": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/redux/-/redux-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.9.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"regenerator-runtime": {
|
|
||||||
"version": "0.13.9",
|
|
||||||
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
|
||||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
|
||||||
},
|
|
||||||
"regexp.prototype.flags": {
|
"regexp.prototype.flags": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
|
||||||
|
@ -75,8 +75,6 @@
|
|||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"gl-matrix": "^3.4.3",
|
"gl-matrix": "^3.4.3",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dnd": "^16.0.1",
|
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
@import "../Theme/Theme.scss";
|
|
||||||
|
|
||||||
div.command-bar {
|
div.command-bar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -7,53 +5,32 @@ div.command-bar {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
div.command-button {
|
button.ms-Button.command-button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
|
||||||
transition: all 100ms ease-in-out;
|
transition: all 100ms ease-in-out;
|
||||||
cursor: pointer;
|
color: inherit;
|
||||||
|
|
||||||
i {
|
span.ms-Button-flexContainer i.ms-Icon {
|
||||||
font-size: 22px;
|
font-size: 25px;
|
||||||
}
|
|
||||||
|
|
||||||
div.command-button-loading {
|
|
||||||
|
|
||||||
div.ms-Spinner-circle {
|
|
||||||
border-width: 2px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.command-button.on-end {
|
button.ms-Button.command-button.on-end {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.command-bar.dark div.command-button div.command-button-loading div.ms-Spinner-circle {
|
div.command-bar.dark button.ms-Button.command-button.active,
|
||||||
border-top-color: rgba($color: #FFFFFF, $alpha: .9);
|
div.command-bar.dark button.ms-Button.command-button:hover {
|
||||||
border-left-color: rgba($color: #FFFFFF, $alpha: .4);
|
|
||||||
border-bottom-color: rgba($color: #FFFFFF, $alpha: .4);
|
|
||||||
border-right-color: rgba($color: #FFFFFF, $alpha: .4);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.command-bar.light div.command-button div.command-button-loading div.ms-Spinner-circle {
|
|
||||||
border-top-color: rgba($color: #000000, $alpha: .9);
|
|
||||||
border-left-color: rgba($color: #000000, $alpha: .4);
|
|
||||||
border-bottom-color: rgba($color: #000000, $alpha: .4);
|
|
||||||
border-right-color: rgba($color: #000000, $alpha: .4);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.command-bar.dark div.command-button.active,
|
|
||||||
div.command-bar.dark div.command-button:hover {
|
|
||||||
background-color: rgba($color: #FFFFFF, $alpha: .2);
|
background-color: rgba($color: #FFFFFF, $alpha: .2);
|
||||||
color: rgba($color: #FFFFFF, $alpha: 1);
|
color: rgba($color: #FFFFFF, $alpha: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
div.command-bar.light div.command-button.active,
|
div.command-bar.light button.ms-Button.command-button.active,
|
||||||
div.command-bar.light div.command-button:hover {
|
div.command-bar.light button.ms-Button.command-button:hover {
|
||||||
background-color: rgba($color: #000000, $alpha: .08);
|
background-color: rgba($color: #000000, $alpha: .08);
|
||||||
color: rgba($color: #000000, $alpha: 1);
|
color: rgba($color: #000000, $alpha: 1);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, ReactNode, FunctionComponent } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { DirectionalHint, Icon, Spinner } from "@fluentui/react";
|
import { DirectionalHint, IconButton } from "@fluentui/react";
|
||||||
import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
||||||
import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
|
import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
|
||||||
import { BackgroundLevel, Theme } from "@Component/Theme/Theme";
|
import { BackgroundLevel, Theme } from "@Component/Theme/Theme";
|
||||||
@ -18,28 +18,23 @@ interface IRenderButtonParameter {
|
|||||||
iconName?: string;
|
iconName?: string;
|
||||||
click?: () => void;
|
click?: () => void;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
isLoading?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICommandBarState {
|
interface ICommandBarState {
|
||||||
isSaveRunning: boolean;
|
isSaveRunning: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommandButton: FunctionComponent<IRenderButtonParameter> = (param) => {
|
function getRenderButton(param: IRenderButtonParameter): ReactNode {
|
||||||
return <LocalizationTooltipHost
|
return <LocalizationTooltipHost
|
||||||
i18nKey={param.i18NKey}
|
i18nKey={param.i18NKey}
|
||||||
directionalHint={DirectionalHint.rightCenter}
|
directionalHint={DirectionalHint.rightCenter}
|
||||||
>
|
>
|
||||||
<div
|
<IconButton
|
||||||
style={{ height: COMMAND_BAR_WIDTH }}
|
style={{ height: COMMAND_BAR_WIDTH }}
|
||||||
onClick={ param.isLoading ? undefined : param.click }
|
iconProps={{ iconName: param.iconName }}
|
||||||
|
onClick={ param.click }
|
||||||
className={"command-button on-end" + (param.active ? " active" : "")}
|
className={"command-button on-end" + (param.active ? " active" : "")}
|
||||||
>
|
/>
|
||||||
{param.isLoading ?
|
|
||||||
<Spinner className="command-button-loading"/> :
|
|
||||||
<Icon iconName={param.iconName}/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</LocalizationTooltipHost>
|
</LocalizationTooltipHost>
|
||||||
}
|
}
|
||||||
@useSetting
|
@useSetting
|
||||||
@ -73,84 +68,78 @@ class CommandBar extends Component<IMixinSettingProps & IMixinStatusProps, IComm
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="Save"
|
iconName: "Save",
|
||||||
i18NKey="Command.Bar.Save.Info"
|
i18NKey: "Command.Bar.Save.Info",
|
||||||
isLoading={this.state.isSaveRunning}
|
click: () => {
|
||||||
click={() => {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isSaveRunning: true
|
isSaveRunning: true
|
||||||
});
|
});
|
||||||
}}
|
}
|
||||||
/>
|
})}
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName={this.props.status?.actuator.start() ? "Pause" : "Play"}
|
iconName: this.props.status?.actuator.start() ? "Pause" : "Play",
|
||||||
i18NKey="Command.Bar.Play.Info"
|
i18NKey: "Command.Bar.Play.Info",
|
||||||
click={() => this.props.status ? this.props.status.actuator.start(
|
click: () => this.props.status ? this.props.status.actuator.start(
|
||||||
!this.props.status.actuator.start()
|
!this.props.status.actuator.start()
|
||||||
) : undefined}
|
) : undefined
|
||||||
/>
|
})}
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="HandsFree"
|
iconName: "HandsFree", i18NKey: "Command.Bar.Drag.Info",
|
||||||
i18NKey="Command.Bar.Drag.Info"
|
active: mouseMod === MouseMod.Drag,
|
||||||
active={mouseMod === MouseMod.Drag}
|
click: () => this.props.status ? this.props.status.setMouseMod(MouseMod.Drag) : undefined
|
||||||
click={() => this.props.status ? this.props.status.setMouseMod(MouseMod.Drag) : undefined}
|
})}
|
||||||
/>
|
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="TouchPointer"
|
iconName: "TouchPointer", i18NKey: "Command.Bar.Select.Info",
|
||||||
i18NKey="Command.Bar.Select.Info"
|
active: mouseMod === MouseMod.click,
|
||||||
active={mouseMod === MouseMod.click}
|
click: () => this.props.status ? this.props.status.setMouseMod(MouseMod.click) : undefined
|
||||||
click={() => this.props.status ? this.props.status.setMouseMod(MouseMod.click) : undefined}
|
})}
|
||||||
/>
|
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="WebAppBuilderFragmentCreate"
|
iconName: "WebAppBuilderFragmentCreate",
|
||||||
i18NKey="Command.Bar.Add.Group.Info"
|
i18NKey: "Command.Bar.Add.Group.Info",
|
||||||
click={() => {
|
click: () => {
|
||||||
this.props.status ? this.props.status.newGroup() : undefined;
|
this.props.status ? this.props.status.newGroup() : undefined;
|
||||||
}}
|
}
|
||||||
/>
|
})}
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="ProductVariant"
|
iconName: "ProductVariant",
|
||||||
i18NKey="Command.Bar.Add.Range.Info"
|
i18NKey: "Command.Bar.Add.Range.Info",
|
||||||
click={() => {
|
click: () => {
|
||||||
this.props.status ? this.props.status.newRange() : undefined;
|
this.props.status ? this.props.status.newRange() : undefined;
|
||||||
}}
|
}
|
||||||
/>
|
})}
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="Running"
|
iconName: "Running",
|
||||||
i18NKey="Command.Bar.Add.Behavior.Info"
|
i18NKey: "Command.Bar.Add.Behavior.Info",
|
||||||
click={() => {
|
click: () => {
|
||||||
this.props.status?.popup.showPopup(BehaviorPopup, {});
|
this.props.status?.popup.showPopup(BehaviorPopup, {});
|
||||||
}}
|
}
|
||||||
/>
|
})}
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="Tag"
|
iconName: "Tag",
|
||||||
i18NKey="Command.Bar.Add.Tag.Info"
|
i18NKey: "Command.Bar.Add.Tag.Info",
|
||||||
click={() => {
|
click: () => {
|
||||||
this.props.status ? this.props.status.newLabel() : undefined;
|
this.props.status ? this.props.status.newLabel() : undefined;
|
||||||
}}
|
}
|
||||||
/>
|
})}
|
||||||
|
|
||||||
<CommandButton
|
{getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
|
||||||
iconName="Camera"
|
|
||||||
i18NKey="Command.Bar.Camera.Info"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<CommandButton
|
{getRenderButton({
|
||||||
iconName="Settings"
|
iconName: "Settings",
|
||||||
i18NKey="Command.Bar.Setting.Info"
|
i18NKey: "Command.Bar.Setting.Info",
|
||||||
click={() => {
|
click: () => {
|
||||||
this.props.status?.popup.showPopup(SettingPopup, {});
|
this.props.status?.popup.showPopup(SettingPopup, {});
|
||||||
}}
|
}
|
||||||
/>
|
})}
|
||||||
</div>
|
</div>
|
||||||
</Theme>
|
</Theme>
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ interface IConfirmPopupProps {
|
|||||||
titleI18N?: AllI18nKeys;
|
titleI18N?: AllI18nKeys;
|
||||||
titleI18NOption?: Record<string, string>;
|
titleI18NOption?: Record<string, string>;
|
||||||
infoI18n?: AllI18nKeys;
|
infoI18n?: AllI18nKeys;
|
||||||
infoI18nOption?: Record<string, string>;
|
|
||||||
yesI18n?: AllI18nKeys;
|
yesI18n?: AllI18nKeys;
|
||||||
noI18n?: AllI18nKeys;
|
noI18n?: AllI18nKeys;
|
||||||
renderInfo?: () => ReactNode;
|
renderInfo?: () => ReactNode;
|
||||||
@ -65,10 +64,8 @@ class ConfirmPopup extends Popup<IConfirmPopupProps> {
|
|||||||
this.props.renderInfo ?
|
this.props.renderInfo ?
|
||||||
this.props.renderInfo() :
|
this.props.renderInfo() :
|
||||||
this.props.infoI18n ?
|
this.props.infoI18n ?
|
||||||
<Message
|
<Message i18nKey={this.props.infoI18n}/> :
|
||||||
i18nKey={this.props.infoI18n}
|
null
|
||||||
options={this.props.infoI18nOption}
|
|
||||||
/> : null
|
|
||||||
}
|
}
|
||||||
</ConfirmContent>
|
</ConfirmContent>
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,8 @@
|
|||||||
@import "../Theme/Theme.scss";
|
@import "../Theme/Theme.scss";
|
||||||
|
|
||||||
div.load-file-app-root {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.load-file-layer-root {
|
div.load-file-layer-root {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
pointer-events: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20px;
|
|
||||||
|
|
||||||
div.load-file-layer {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -22,7 +10,6 @@ div.load-file-layer-root {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
div {
|
div {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -40,21 +27,12 @@ div.load-file-layer-root {
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.load-file-layer-root.light {
|
div.load-file-layer-root.light {
|
||||||
background-color: rgba($color: #FFFFFF, $alpha: .6);
|
background-color: rgba($color: #FFFFFF, $alpha: .75);
|
||||||
|
|
||||||
div.load-file-layer {
|
|
||||||
border: 2px dashed $lt-font-color-normal-light;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.load-file-layer-root.dark {
|
div.load-file-layer-root.dark {
|
||||||
background-color: rgba($color: #000000, $alpha: .6);
|
background-color: rgba($color: #000000, $alpha: .75);
|
||||||
|
|
||||||
div.load-file-layer {
|
|
||||||
border: 2px dashed $lt-font-color-normal-dark;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,20 +1,16 @@
|
|||||||
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
|
||||||
import { Localization } from "@Component/Localization/Localization";
|
import { Localization } from "@Component/Localization/Localization";
|
||||||
import { FontLevel, Theme } from "@Component/Theme/Theme";
|
import { FontLevel, Theme } from "@Component/Theme/Theme";
|
||||||
import { Status, useStatus, IMixinStatusProps } from "@Context/Status";
|
|
||||||
import { Icon } from "@fluentui/react";
|
import { Icon } from "@fluentui/react";
|
||||||
import { FunctionComponent } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { useDrop } from 'react-dnd'
|
|
||||||
import { NativeTypes } from "react-dnd-html5-backend"
|
|
||||||
import "./LoadFile.scss";
|
import "./LoadFile.scss";
|
||||||
|
|
||||||
const DragFileMask: FunctionComponent = () => {
|
class LoadFile extends Component {
|
||||||
|
|
||||||
|
private renderMask() {
|
||||||
return <Theme
|
return <Theme
|
||||||
className="load-file-layer-root"
|
className="load-file-layer-root"
|
||||||
fontLevel={FontLevel.normal}
|
fontLevel={FontLevel.normal}
|
||||||
>
|
>
|
||||||
<div className="load-file-layer">
|
|
||||||
<div className="drag-icon">
|
<div className="drag-icon">
|
||||||
<Icon iconName="KnowledgeArticle"/>
|
<Icon iconName="KnowledgeArticle"/>
|
||||||
</div>
|
</div>
|
||||||
@ -24,119 +20,12 @@ const DragFileMask: FunctionComponent = () => {
|
|||||||
<div className="drag-intro">
|
<div className="drag-intro">
|
||||||
<Localization i18nKey="Info.Hint.Load.File.Intro"/>
|
<Localization i18nKey="Info.Hint.Load.File.Intro"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Theme>;
|
</Theme>;
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): ReactNode {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fileChecker(status: Status, file?: File) {
|
|
||||||
|
|
||||||
if (!status) return undefined;
|
|
||||||
|
|
||||||
return new Promise((r, j) => {
|
|
||||||
|
|
||||||
// 检查文件存在性
|
|
||||||
if (!file) {
|
|
||||||
status.popup.showPopup(ConfirmPopup, {
|
|
||||||
infoI18n: "Popup.Load.Save.Error.Empty",
|
|
||||||
titleI18N: "Popup.Load.Save.Title",
|
|
||||||
yesI18n: "Popup.Load.Save.confirm"
|
|
||||||
});
|
|
||||||
return j();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测拓展名
|
|
||||||
let extendName = (file.name.match(/\.(\w+)$/) ?? [])[1];
|
|
||||||
if (extendName !== "ltss") {
|
|
||||||
status.popup.showPopup(ConfirmPopup, {
|
|
||||||
infoI18n: "Popup.Load.Save.Error.Type",
|
|
||||||
infoI18nOption: { ext: extendName },
|
|
||||||
titleI18N: "Popup.Load.Save.Title",
|
|
||||||
yesI18n: "Popup.Load.Save.confirm"
|
|
||||||
});
|
|
||||||
return j();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件读取
|
|
||||||
let fileReader = new FileReader();
|
|
||||||
fileReader.readAsText(file);
|
|
||||||
fileReader.onload = () => {
|
|
||||||
|
|
||||||
const loadFunc = () => {
|
|
||||||
|
|
||||||
// 进行转换
|
|
||||||
let errorMessage = status.archive.load(status.model, fileReader.result as string, file.name, file.path);
|
|
||||||
if (errorMessage) {
|
|
||||||
status.popup.showPopup(ConfirmPopup, {
|
|
||||||
infoI18n: "Popup.Load.Save.Error.Parse",
|
|
||||||
infoI18nOption: { why: errorMessage },
|
|
||||||
titleI18N: "Popup.Load.Save.Title",
|
|
||||||
yesI18n: "Popup.Load.Save.confirm"
|
|
||||||
});
|
|
||||||
j();
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
r(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果保存进行提示
|
|
||||||
if (!status.archive.isSaved) {
|
|
||||||
status.popup.showPopup(ConfirmPopup, {
|
|
||||||
infoI18n: "Popup.Load.Save.Overwrite.Info",
|
|
||||||
titleI18N: "Popup.Load.Save.Title",
|
|
||||||
yesI18n: "Popup.Load.Save.Overwrite",
|
|
||||||
noI18n: "Popup.Action.No",
|
|
||||||
red: "yes",
|
|
||||||
yes: () => {
|
|
||||||
loadFunc();
|
|
||||||
},
|
|
||||||
no: () => {
|
|
||||||
j();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
loadFunc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fileReader.onerror = () => {
|
|
||||||
status.popup.showPopup(ConfirmPopup, {
|
|
||||||
infoI18n: "Popup.Load.Save.Error.Parse",
|
|
||||||
infoI18nOption: { why: "Unknown error" },
|
|
||||||
titleI18N: "Popup.Load.Save.Title",
|
|
||||||
yesI18n: "Popup.Load.Save.confirm"
|
|
||||||
});
|
|
||||||
j();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoadFileView: FunctionComponent<IMixinStatusProps> = (props) => {
|
|
||||||
|
|
||||||
const [{ isOver }, drop] = useDrop(() => ({
|
|
||||||
accept: NativeTypes.FILE,
|
|
||||||
drop: (item: { files: File[] }) => {
|
|
||||||
if (props.status) {
|
|
||||||
fileChecker(props.status, item.files[0]).catch((e) => undefined);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isOver: monitor.isOver()
|
|
||||||
})
|
|
||||||
}));
|
|
||||||
|
|
||||||
return <>
|
|
||||||
{
|
|
||||||
isOver ? <DragFileMask/> : null
|
|
||||||
}
|
|
||||||
<div className="load-file-app-root" ref={drop}>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoadFile = useStatus(LoadFileView);
|
|
||||||
|
|
||||||
export { LoadFile };
|
export { LoadFile };
|
@ -1,9 +1,8 @@
|
|||||||
import { FunctionComponent, useEffect } from "react";
|
import { FunctionComponent, useEffect } from "react";
|
||||||
|
import * as download from "downloadjs";
|
||||||
import { useSetting, IMixinSettingProps, Platform } from "@Context/Setting";
|
import { useSetting, IMixinSettingProps, Platform } from "@Context/Setting";
|
||||||
import { useStatus, IMixinStatusProps } from "@Context/Status";
|
import { useStatus, IMixinStatusProps } from "@Context/Status";
|
||||||
import { useElectron, IMixinElectronProps } from "@Context/Electron";
|
|
||||||
import { I18N } from "@Component/Localization/Localization";
|
import { I18N } from "@Component/Localization/Localization";
|
||||||
import * as download from "downloadjs";
|
|
||||||
|
|
||||||
interface IFileInfo {
|
interface IFileInfo {
|
||||||
fileName: string;
|
fileName: string;
|
||||||
@ -22,7 +21,7 @@ interface ICallBackProps {
|
|||||||
then: () => any;
|
then: () => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArchiveSaveDownloadView: FunctionComponent<IFileInfo & ICallBackProps> = function ArchiveSaveDownloadView(props) {
|
const ArchiveSaveDownloadView: FunctionComponent<IFileInfo & ICallBackProps> = function ArchiveSave(props) {
|
||||||
|
|
||||||
const runner = async () => {
|
const runner = async () => {
|
||||||
const file = await props.fileData();
|
const file = await props.fileData();
|
||||||
@ -39,47 +38,6 @@ const ArchiveSaveDownloadView: FunctionComponent<IFileInfo & ICallBackProps> = f
|
|||||||
|
|
||||||
const ArchiveSaveDownload = ArchiveSaveDownloadView;
|
const ArchiveSaveDownload = ArchiveSaveDownloadView;
|
||||||
|
|
||||||
const ArchiveSaveFsView: FunctionComponent<IFileInfo & ICallBackProps & IMixinElectronProps & IMixinSettingProps & IMixinStatusProps> =
|
|
||||||
function ArchiveSaveFsView(props) {
|
|
||||||
|
|
||||||
const runner = async () => {
|
|
||||||
const file = await props.fileData();
|
|
||||||
setTimeout(() => {
|
|
||||||
if (props.electron) {
|
|
||||||
props.electron.fileSave(
|
|
||||||
file,
|
|
||||||
I18N(props, "Popup.Load.Save.Select.File.Name"),
|
|
||||||
I18N(props, "Popup.Load.Save.Select.Path.Title"),
|
|
||||||
I18N(props, "Popup.Load.Save.Select.Path.Button"),
|
|
||||||
props.fileUrl
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveEvent = ({name, url, success} : {name: string, url: string, success: boolean}) => {
|
|
||||||
if (success && props.status) {
|
|
||||||
props.status.archive.fileUrl = url;
|
|
||||||
props.status.archive.fileName = name;
|
|
||||||
props.status.archive.isNewFile = false;
|
|
||||||
props.status.archive.emit("fileSave", props.status.archive);
|
|
||||||
}
|
|
||||||
props.then();
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
runner();
|
|
||||||
props.electron?.on("fileSave", saveEvent);
|
|
||||||
return () => {
|
|
||||||
props.electron?.off("fileSave", saveEvent);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return <></>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ArchiveSaveFs = useSetting(useElectron(useStatus(ArchiveSaveFsView)));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存存档文件
|
* 保存存档文件
|
||||||
*/
|
*/
|
||||||
@ -123,7 +81,7 @@ const ArchiveSaveView: FunctionComponent<IMixinSettingProps & IMixinStatusProps
|
|||||||
{
|
{
|
||||||
props.setting?.platform === Platform.web ?
|
props.setting?.platform === Platform.web ?
|
||||||
<ArchiveSaveDownload {...fileData} then={callBack}/> :
|
<ArchiveSaveDownload {...fileData} then={callBack}/> :
|
||||||
<ArchiveSaveFs {...fileData} then={callBack}/>
|
<></>
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
import { Emitter } from "@Model/Emitter";
|
|
||||||
import { superConnect, superConnectWithEvent } from "@Context/Context";
|
import { superConnect, superConnectWithEvent } from "@Context/Context";
|
||||||
import { ISimulatorAPI, IApiEmitterEvent } from "@Electron/SimulatorAPI";
|
import { ISimulatorAPI, IApiEmitterEvent } from "@Electron/SimulatorAPI";
|
||||||
|
|
||||||
@ -7,25 +6,6 @@ interface IMixinElectronProps {
|
|||||||
electron?: ISimulatorAPI;
|
electron?: ISimulatorAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getElectronAPI: () => ISimulatorAPI = () => {
|
|
||||||
const API = (window as any).API;
|
|
||||||
const mapperEmitter = new Emitter();
|
|
||||||
const ClassElectron: new () => ISimulatorAPI = function (this: Record<string, any>) {
|
|
||||||
this.resetAll = () => mapperEmitter.resetAll();
|
|
||||||
this.reset = (type: string) => mapperEmitter.reset(type);
|
|
||||||
this.on = (type: string, handel: any) => mapperEmitter.on(type, handel);
|
|
||||||
this.off = (type: string, handel: any) => mapperEmitter.off(type, handel);
|
|
||||||
this.emit = (type: string, data: any) => mapperEmitter.emit(type, data);
|
|
||||||
} as any;
|
|
||||||
ClassElectron.prototype = API;
|
|
||||||
|
|
||||||
// Emitter Mapper
|
|
||||||
API.mapEmit((...p: any) => {
|
|
||||||
mapperEmitter.emit(...p);
|
|
||||||
});
|
|
||||||
return new ClassElectron();
|
|
||||||
}
|
|
||||||
|
|
||||||
const ElectronContext = createContext<ISimulatorAPI>((window as any).API ?? {} as ISimulatorAPI);
|
const ElectronContext = createContext<ISimulatorAPI>((window as any).API ?? {} as ISimulatorAPI);
|
||||||
|
|
||||||
ElectronContext.displayName = "Electron";
|
ElectronContext.displayName = "Electron";
|
||||||
@ -39,4 +19,4 @@ const useElectron = superConnect<ISimulatorAPI>(ElectronConsumer, "electron");
|
|||||||
|
|
||||||
const useElectronWithEvent = superConnectWithEvent<ISimulatorAPI, IApiEmitterEvent>(ElectronConsumer, "electron");
|
const useElectronWithEvent = superConnectWithEvent<ISimulatorAPI, IApiEmitterEvent>(ElectronConsumer, "electron");
|
||||||
|
|
||||||
export { useElectron, ElectronProvider, IMixinElectronProps, ISimulatorAPI, useElectronWithEvent, getElectronAPI };
|
export { useElectron, ElectronProvider, IMixinElectronProps, ISimulatorAPI, useElectronWithEvent };
|
@ -161,11 +161,6 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
this.emit("labelChange");
|
this.emit("labelChange");
|
||||||
this.emit("behaviorChange");
|
this.emit("behaviorChange");
|
||||||
|
|
||||||
// 清除焦点对象
|
|
||||||
this.setBehaviorObject();
|
|
||||||
this.setFocusObject(new Set());
|
|
||||||
this.setLabelObject();
|
|
||||||
|
|
||||||
// 映射
|
// 映射
|
||||||
this.emit("fileLoad");
|
this.emit("fileLoad");
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { app, BrowserWindow, ipcMain, dialog } from "electron";
|
import { app, BrowserWindow, ipcMain } from "electron";
|
||||||
import { Service } from "@Service/Service";
|
import { Service } from "@Service/Service";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import { writeFile } from "fs";
|
|
||||||
const ENV = process.env ?? {};
|
const ENV = process.env ?? {};
|
||||||
|
|
||||||
class ElectronApp {
|
class ElectronApp {
|
||||||
@ -56,7 +55,6 @@ class ElectronApp {
|
|||||||
this.simulatorWindow.loadURL(this.serviceUrl + (ENV.LIVING_TOGETHER_WEB_PATH ?? "/resources/app.asar/"));
|
this.simulatorWindow.loadURL(this.serviceUrl + (ENV.LIVING_TOGETHER_WEB_PATH ?? "/resources/app.asar/"));
|
||||||
|
|
||||||
this.handelSimulatorWindowBehavior();
|
this.handelSimulatorWindowBehavior();
|
||||||
this.handelFileChange();
|
|
||||||
|
|
||||||
app.on('window-all-closed', function () {
|
app.on('window-all-closed', function () {
|
||||||
if (process.platform !== 'darwin') app.quit()
|
if (process.platform !== 'darwin') app.quit()
|
||||||
@ -92,56 +90,6 @@ class ElectronApp {
|
|||||||
this.simulatorWindow?.on("maximize", sendWindowsChangeMessage);
|
this.simulatorWindow?.on("maximize", sendWindowsChangeMessage);
|
||||||
this.simulatorWindow?.on("unmaximize", sendWindowsChangeMessage);
|
this.simulatorWindow?.on("unmaximize", sendWindowsChangeMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handelFileChange() {
|
|
||||||
|
|
||||||
// 文件保存
|
|
||||||
const saveFile = async (path: string, text: string) => {
|
|
||||||
return new Promise((r) => {
|
|
||||||
writeFile(path ?? "", text, {}, (e) => {
|
|
||||||
this.simulatorWindow?.webContents.send(
|
|
||||||
"windows.EndFileSave",
|
|
||||||
(path.match(/.+(\/|\\)(.+)$/) ?? [])[2],
|
|
||||||
path, !e
|
|
||||||
);
|
|
||||||
r(undefined);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理文件保存事件
|
|
||||||
ipcMain.on("windows.fileSave",
|
|
||||||
(_, text: string, name: string, title: string, button: string, url?: string) => {
|
|
||||||
|
|
||||||
// 如果没有路径,询问新的路径
|
|
||||||
if (url) {
|
|
||||||
saveFile(url, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 询问保存位置
|
|
||||||
else {
|
|
||||||
dialog.showSaveDialog(this.simulatorWindow!, {
|
|
||||||
title: title,
|
|
||||||
buttonLabel: button,
|
|
||||||
filters: [
|
|
||||||
{ name: name, extensions: ["ltss"] }
|
|
||||||
]
|
|
||||||
}).then(res => {
|
|
||||||
|
|
||||||
// 用户选择后继续保存
|
|
||||||
if (!res.canceled && res.filePath) {
|
|
||||||
saveFile(res.filePath, text);
|
|
||||||
} else {
|
|
||||||
this.simulatorWindow?.webContents.send(
|
|
||||||
"windows.EndFileSave",
|
|
||||||
undefined, undefined, false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new ElectronApp().runMainThread();
|
new ElectronApp().runMainThread();
|
@ -2,7 +2,6 @@ import { Emitter } from "@Model/Emitter";
|
|||||||
|
|
||||||
type IApiEmitterEvent = {
|
type IApiEmitterEvent = {
|
||||||
windowsSizeStateChange: void;
|
windowsSizeStateChange: void;
|
||||||
fileSave: {success: boolean, name: string, url: string};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISimulatorAPI extends Emitter<IApiEmitterEvent> {
|
interface ISimulatorAPI extends Emitter<IApiEmitterEvent> {
|
||||||
@ -31,11 +30,6 @@ interface ISimulatorAPI extends Emitter<IApiEmitterEvent> {
|
|||||||
* 是否处于最大化状态
|
* 是否处于最大化状态
|
||||||
*/
|
*/
|
||||||
minimize: () => void;
|
minimize: () => void;
|
||||||
|
|
||||||
/**
|
|
||||||
* 存档
|
|
||||||
*/
|
|
||||||
fileSave: (text: string, name: string, title: string, button: string, url?: string) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ISimulatorAPI, IApiEmitterEvent }
|
export { ISimulatorAPI, IApiEmitterEvent }
|
@ -1,11 +1,23 @@
|
|||||||
import { contextBridge, ipcRenderer } from "electron";
|
import { contextBridge, ipcRenderer } from "electron";
|
||||||
import { ISimulatorAPI } from "@Electron/SimulatorAPI";
|
import { ISimulatorAPI } from "@Electron/SimulatorAPI"
|
||||||
|
|
||||||
const emitterMap: { fn?: Function } = { fn: undefined };
|
const emitterMap: Array<[key: string, value: Function[]]> = [];
|
||||||
|
const queryEmitter = (key: string) => {
|
||||||
|
let res: (typeof emitterMap)[0] | undefined;
|
||||||
|
emitterMap.forEach((item) => {
|
||||||
|
if (item[0] === key) res = item;
|
||||||
|
});
|
||||||
|
|
||||||
const emit = (type: string, evt?: any) => {
|
if (res) {
|
||||||
if (emitterMap.fn) {
|
if (Array.isArray(res[1])) return res[1];
|
||||||
emitterMap.fn(type, evt);
|
res[1] = [];
|
||||||
|
return res[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
res = [key, []];
|
||||||
|
emitterMap.push(res);
|
||||||
|
return res[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,19 +43,22 @@ const API: ISimulatorAPI = {
|
|||||||
ipcRenderer.send("windows.minimize");
|
ipcRenderer.send("windows.minimize");
|
||||||
},
|
},
|
||||||
|
|
||||||
fileSave(text: string, name: string, title: string, button: string, url?: string) {
|
all: new Map() as any,
|
||||||
ipcRenderer.send("windows.fileSave", text, name, title, button, url);
|
|
||||||
},
|
|
||||||
|
|
||||||
mapEmit: (fn: Function) => { emitterMap.fn = fn },
|
resetAll: () => emitterMap.splice(0),
|
||||||
} as any;
|
reset: (type) => queryEmitter(type).splice(0),
|
||||||
|
on: (type, handler) => queryEmitter(type).push(handler),
|
||||||
|
off: (type, handler) => {
|
||||||
|
const handlers = queryEmitter(type);
|
||||||
|
handlers.splice(handlers.indexOf(handler!) >>> 0, 1);
|
||||||
|
},
|
||||||
|
emit: ((type: string, evt: any) => {
|
||||||
|
queryEmitter(type).slice().map((handler: any) => { handler(evt) });
|
||||||
|
}) as any,
|
||||||
|
}
|
||||||
|
|
||||||
ipcRenderer.on("windows.windowsSizeStateChange", () => {
|
ipcRenderer.on("windows.windowsSizeStateChange", () => {
|
||||||
emit("windowsSizeStateChange");
|
API.emit("windowsSizeStateChange");
|
||||||
});
|
|
||||||
|
|
||||||
ipcRenderer.on("windows.EndFileSave", (_, name: string, url: string, success: boolean) => {
|
|
||||||
emit("fileSave", {name, url, success});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld("API", API);
|
contextBridge.exposeInMainWorld("API", API);
|
@ -65,16 +65,6 @@ const EN_US = {
|
|||||||
"Popup.Delete.Behavior.Confirm": "Are you sure you want to delete this behavior? The behavior is deleted and cannot be recalled.",
|
"Popup.Delete.Behavior.Confirm": "Are you sure you want to delete this behavior? The behavior is deleted and cannot be recalled.",
|
||||||
"Popup.Restore.Behavior.Confirm": "Are you sure you want to reset all parameters of this behavior? This operation cannot be recalled.",
|
"Popup.Restore.Behavior.Confirm": "Are you sure you want to reset all parameters of this behavior? This operation cannot be recalled.",
|
||||||
"Popup.Setting.Title": "Preferences setting",
|
"Popup.Setting.Title": "Preferences setting",
|
||||||
"Popup.Load.Save.Title": "Load save",
|
|
||||||
"Popup.Load.Save.confirm": "Got it",
|
|
||||||
"Popup.Load.Save.Overwrite": "Overwrite and continue",
|
|
||||||
"Popup.Load.Save.Overwrite.Info": "The current workspace will be overwritten after the archive is loaded, and all unsaved progress will be lost. Are you sure you want to continue?",
|
|
||||||
"Popup.Load.Save.Error.Empty": "File information acquisition error. The file has been lost or moved.",
|
|
||||||
"Popup.Load.Save.Error.Type": "The file with extension name \"{ext}\" cannot be loaded temporarily",
|
|
||||||
"Popup.Load.Save.Error.Parse": "Archive parsing error, detailed reason: \n{why}",
|
|
||||||
"Popup.Load.Save.Select.Path.Title": "Please select an archive location",
|
|
||||||
"Popup.Load.Save.Select.Path.Button": "Save",
|
|
||||||
"Popup.Load.Save.Select.File.Name": "Living Together Simulator Save",
|
|
||||||
"Popup.Add.Behavior.Title": "Add behavior",
|
"Popup.Add.Behavior.Title": "Add behavior",
|
||||||
"Popup.Add.Behavior.Action.Add": "Add all select behavior",
|
"Popup.Add.Behavior.Action.Add": "Add all select behavior",
|
||||||
"Popup.Add.Behavior.Select.Counter": "Selected {count} behavior",
|
"Popup.Add.Behavior.Select.Counter": "Selected {count} behavior",
|
||||||
|
@ -65,16 +65,6 @@ const ZH_CN = {
|
|||||||
"Popup.Delete.Behavior.Confirm": "你确定要删除这个行为吗?行为被删除将无法撤回。",
|
"Popup.Delete.Behavior.Confirm": "你确定要删除这个行为吗?行为被删除将无法撤回。",
|
||||||
"Popup.Restore.Behavior.Confirm": "你确定要重置此行为的全部参数吗?此操作无法撤回。",
|
"Popup.Restore.Behavior.Confirm": "你确定要重置此行为的全部参数吗?此操作无法撤回。",
|
||||||
"Popup.Setting.Title": "首选项设置",
|
"Popup.Setting.Title": "首选项设置",
|
||||||
"Popup.Load.Save.Title": "加载存档",
|
|
||||||
"Popup.Load.Save.confirm": "我知道了",
|
|
||||||
"Popup.Load.Save.Overwrite": "覆盖并继续",
|
|
||||||
"Popup.Load.Save.Overwrite.Info": "存档加载后将覆盖当前工作区,未保存的进度将全部丢失,确定要继续吗?",
|
|
||||||
"Popup.Load.Save.Error.Empty": "文件信息获取错误,文件已丢失或已被移动",
|
|
||||||
"Popup.Load.Save.Error.Type": "暂时无法加载拓展名为 \"{ext}\" 的文件",
|
|
||||||
"Popup.Load.Save.Error.Parse": "存档解析错误,详细原因: \n{why}",
|
|
||||||
"Popup.Load.Save.Select.Path.Title": "请选择存档保存位置",
|
|
||||||
"Popup.Load.Save.Select.Path.Button": "保存",
|
|
||||||
"Popup.Load.Save.Select.File.Name": "群生共进存档",
|
|
||||||
"Popup.Add.Behavior.Title": "添加行为",
|
"Popup.Add.Behavior.Title": "添加行为",
|
||||||
"Popup.Add.Behavior.Action.Add": "添加全部选中行为",
|
"Popup.Add.Behavior.Action.Add": "添加全部选中行为",
|
||||||
"Popup.Add.Behavior.Select.Counter": "已选择 {count} 个行为",
|
"Popup.Add.Behavior.Select.Counter": "已选择 {count} 个行为",
|
||||||
|
@ -37,7 +37,7 @@ class Archive extends Emitter<IArchiveEvent> {
|
|||||||
/**
|
/**
|
||||||
* 是否保存
|
* 是否保存
|
||||||
*/
|
*/
|
||||||
public isSaved: boolean = true;
|
public isSaved: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件路径
|
* 文件路径
|
||||||
@ -100,7 +100,7 @@ class Archive extends Emitter<IArchiveEvent> {
|
|||||||
|
|
||||||
// 解析为 JSON 对象
|
// 解析为 JSON 对象
|
||||||
const archive: IArchiveObject = JSON.parse(data);
|
const archive: IArchiveObject = JSON.parse(data);
|
||||||
// console.log(archive);
|
console.log(archive);
|
||||||
|
|
||||||
// 实例化全部对象
|
// 实例化全部对象
|
||||||
const objectPool: CtrlObject[] = [];
|
const objectPool: CtrlObject[] = [];
|
||||||
@ -254,7 +254,7 @@ class Archive extends Emitter<IArchiveEvent> {
|
|||||||
* 加载文件为模型
|
* 加载文件为模型
|
||||||
* @return Model
|
* @return Model
|
||||||
*/
|
*/
|
||||||
public load(model: Model, data: string, name: string, url?: string): string | undefined {
|
public load(model: Model, data: string): string | undefined {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.loadArchiveIntoModel(model, data);
|
this.loadArchiveIntoModel(model, data);
|
||||||
@ -262,12 +262,8 @@ class Archive extends Emitter<IArchiveEvent> {
|
|||||||
return e as string;
|
return e as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit("fileLoad", this);
|
|
||||||
this.fileName = name;
|
|
||||||
this.isSaved = true;
|
this.isSaved = true;
|
||||||
this.isNewFile = false;
|
this.emit("fileLoad", this);
|
||||||
this.fileUrl = url;
|
|
||||||
this.emit("fileSave", this);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
import { Component, ReactNode } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { DndProvider } from 'react-dnd'
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend'
|
|
||||||
import { SettingProvider, Setting, Platform } from "@Context/Setting";
|
import { SettingProvider, Setting, Platform } from "@Context/Setting";
|
||||||
import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme";
|
import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme";
|
||||||
import { ISimulatorAPI } from "@Electron/SimulatorAPI";
|
import { ISimulatorAPI } from "@Electron/SimulatorAPI";
|
||||||
import { StatusProvider, Status } from "@Context/Status";
|
import { StatusProvider, Status } from "@Context/Status";
|
||||||
import { ElectronProvider, getElectronAPI } from "@Context/Electron";
|
import { ElectronProvider } from "@Context/Electron";
|
||||||
import { ClassicRenderer } from "@GLRender/ClassicRenderer";
|
import { ClassicRenderer } from "@GLRender/ClassicRenderer";
|
||||||
import { initializeIcons } from '@fluentui/font-icons-mdl2';
|
import { initializeIcons } from '@fluentui/font-icons-mdl2';
|
||||||
import { RootContainer } from "@Component/Container/RootContainer";
|
import { RootContainer } from "@Component/Container/RootContainer";
|
||||||
import { LayoutDirection } from "@Context/Layout";
|
import { LayoutDirection } from "@Context/Layout";
|
||||||
import { CommandBar } from "@Component/CommandBar/CommandBar";
|
import { CommandBar } from "@Component/CommandBar/CommandBar";
|
||||||
import { LoadFile } from "@Component/LoadFile/LoadFile";
|
|
||||||
import { HeaderBar } from "@Component/HeaderBar/HeaderBar";
|
import { HeaderBar } from "@Component/HeaderBar/HeaderBar";
|
||||||
import { Popup } from "@Component/Popup/Popup";
|
import { Popup } from "@Component/Popup/Popup";
|
||||||
import { Entry } from "../Entry/Entry";
|
import { Entry } from "../Entry/Entry";
|
||||||
|
import { Group } from "@Model/Group";
|
||||||
import "./SimulatorDesktop.scss";
|
import "./SimulatorDesktop.scss";
|
||||||
|
|
||||||
initializeIcons("./font-icon/");
|
initializeIcons("./font-icon/");
|
||||||
@ -49,12 +47,25 @@ class SimulatorDesktop extends Component {
|
|||||||
this.status.bindRenderer(classicRender);
|
this.status.bindRenderer(classicRender);
|
||||||
this.status.setting = this.setting;
|
this.status.setting = this.setting;
|
||||||
|
|
||||||
|
const randomPosition = (group: Group) => {
|
||||||
|
group.individuals.forEach((individual) => {
|
||||||
|
individual.position[0] = (Math.random() - .5) * 2;
|
||||||
|
individual.position[1] = (Math.random() - .5) * 2;
|
||||||
|
individual.position[2] = (Math.random() - .5) * 2;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
(window as any).LT = {
|
(window as any).LT = {
|
||||||
status: this.status,
|
status: this.status,
|
||||||
setting: this.setting
|
setting: this.setting
|
||||||
};
|
};
|
||||||
|
|
||||||
this.electron = getElectronAPI();
|
this.electron = {} as ISimulatorAPI;
|
||||||
|
if ((window as any).API) {
|
||||||
|
this.electron = (window as any).API;
|
||||||
|
} else {
|
||||||
|
console.error("SimulatorDesktop: Can't find electron API");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
@ -91,9 +102,7 @@ class SimulatorDesktop extends Component {
|
|||||||
return <SettingProvider value={this.setting}>
|
return <SettingProvider value={this.setting}>
|
||||||
<StatusProvider value={this.status}>
|
<StatusProvider value={this.status}>
|
||||||
<ElectronProvider value={this.electron}>
|
<ElectronProvider value={this.electron}>
|
||||||
<DndProvider backend={HTML5Backend}>
|
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</DndProvider>
|
|
||||||
</ElectronProvider>
|
</ElectronProvider>
|
||||||
</StatusProvider>
|
</StatusProvider>
|
||||||
</SettingProvider>
|
</SettingProvider>
|
||||||
@ -106,7 +115,6 @@ class SimulatorDesktop extends Component {
|
|||||||
fontLevel={FontLevel.Level3}
|
fontLevel={FontLevel.Level3}
|
||||||
>
|
>
|
||||||
<Popup/>
|
<Popup/>
|
||||||
<LoadFile>
|
|
||||||
<HeaderBar height={35}/>
|
<HeaderBar height={35}/>
|
||||||
<div className="app-root-space" style={{
|
<div className="app-root-space" style={{
|
||||||
height: `calc( 100% - ${35}px)`
|
height: `calc( 100% - ${35}px)`
|
||||||
@ -114,7 +122,6 @@ class SimulatorDesktop extends Component {
|
|||||||
<CommandBar/>
|
<CommandBar/>
|
||||||
<RootContainer/>
|
<RootContainer/>
|
||||||
</div>
|
</div>
|
||||||
</LoadFile>
|
|
||||||
</Theme>
|
</Theme>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import { Component, ReactNode } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { DndProvider } from 'react-dnd'
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend'
|
|
||||||
import { SettingProvider, Setting, Platform } from "@Context/Setting";
|
import { SettingProvider, Setting, Platform } from "@Context/Setting";
|
||||||
import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme";
|
import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme";
|
||||||
import { StatusProvider, Status } from "@Context/Status";
|
import { StatusProvider, Status } from "@Context/Status";
|
||||||
@ -9,10 +7,12 @@ import { initializeIcons } from '@fluentui/font-icons-mdl2';
|
|||||||
import { RootContainer } from "@Component/Container/RootContainer";
|
import { RootContainer } from "@Component/Container/RootContainer";
|
||||||
import { LayoutDirection } from "@Context/Layout";
|
import { LayoutDirection } from "@Context/Layout";
|
||||||
import { LoadFile } from "@Component/LoadFile/LoadFile";
|
import { LoadFile } from "@Component/LoadFile/LoadFile";
|
||||||
|
import { AllBehaviors, getBehaviorById } from "@Behavior/Behavior";
|
||||||
import { CommandBar } from "@Component/CommandBar/CommandBar";
|
import { CommandBar } from "@Component/CommandBar/CommandBar";
|
||||||
import { HeaderBar } from "@Component/HeaderBar/HeaderBar";
|
import { HeaderBar } from "@Component/HeaderBar/HeaderBar";
|
||||||
import { Popup } from "@Component/Popup/Popup";
|
import { Popup } from "@Component/Popup/Popup";
|
||||||
import { Entry } from "../Entry/Entry";
|
import { Entry } from "../Entry/Entry";
|
||||||
|
import { Group } from "@Model/Group";
|
||||||
import "./SimulatorWeb.scss";
|
import "./SimulatorWeb.scss";
|
||||||
|
|
||||||
initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/");
|
initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/");
|
||||||
@ -42,6 +42,118 @@ class SimulatorWeb extends Component {
|
|||||||
this.status.bindRenderer(classicRender);
|
this.status.bindRenderer(classicRender);
|
||||||
this.status.setting = this.setting;
|
this.status.setting = this.setting;
|
||||||
|
|
||||||
|
const randomPosition = (group: Group) => {
|
||||||
|
group.individuals.forEach((individual) => {
|
||||||
|
individual.position[0] = (Math.random() - .5) * 2;
|
||||||
|
individual.position[1] = (Math.random() - .5) * 2;
|
||||||
|
individual.position[2] = (Math.random() - .5) * 2;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// 测试代码
|
||||||
|
if (false) {
|
||||||
|
let group = this.status.newGroup();
|
||||||
|
let range = this.status.newRange();
|
||||||
|
range.color = [.1, .5, .9];
|
||||||
|
group.new(100);
|
||||||
|
group.color = [.8, .1, .6];
|
||||||
|
randomPosition(group);
|
||||||
|
this.status.model.update(0);
|
||||||
|
this.status.newLabel().name = "New Label";
|
||||||
|
this.status.newLabel().name = "Test Label 01";
|
||||||
|
let template = this.status.model.addBehavior(AllBehaviors[0]);
|
||||||
|
template.name = "Template"; template.color = [150, 20, 220];
|
||||||
|
let dynamic = this.status.model.addBehavior(AllBehaviors[1]);
|
||||||
|
dynamic.name = "Dynamic"; dynamic.color = [250, 200, 80];
|
||||||
|
let brownian = this.status.model.addBehavior(AllBehaviors[2]);
|
||||||
|
brownian.name = "Brownian"; brownian.color = [200, 80, 250];
|
||||||
|
let boundary = this.status.model.addBehavior(AllBehaviors[3]);
|
||||||
|
boundary.name = "Boundary"; boundary.color = [80, 200, 250];
|
||||||
|
boundary.parameter.range.picker = this.status.model.allRangeLabel;
|
||||||
|
group.addBehavior(template);
|
||||||
|
group.addBehavior(dynamic);
|
||||||
|
group.addBehavior(brownian);
|
||||||
|
group.addBehavior(boundary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鱼群模型测试
|
||||||
|
if (false) {
|
||||||
|
let fish1 = this.status.newGroup();
|
||||||
|
let fish2 = this.status.newGroup();
|
||||||
|
let shark = this.status.newGroup();
|
||||||
|
let range = this.status.newRange();
|
||||||
|
|
||||||
|
range.displayName = "Experimental site";
|
||||||
|
range.color = [.8, .1, .6];
|
||||||
|
|
||||||
|
fish1.new(100);
|
||||||
|
fish1.displayName = "Fish A";
|
||||||
|
fish1.color = [.1, .5, .9];
|
||||||
|
randomPosition(fish1);
|
||||||
|
|
||||||
|
fish2.new(50);
|
||||||
|
fish2.displayName = "Fish B";
|
||||||
|
fish2.color = [.3, .2, .9];
|
||||||
|
randomPosition(fish2);
|
||||||
|
|
||||||
|
shark.new(3);
|
||||||
|
shark.displayName = "Shark";
|
||||||
|
shark.color = [.8, .2, .3];
|
||||||
|
shark.renderParameter.size = 100;
|
||||||
|
shark.renderParameter.shape = "5";
|
||||||
|
randomPosition(shark);
|
||||||
|
|
||||||
|
this.status.model.update(0);
|
||||||
|
let fishLabel = this.status.newLabel();
|
||||||
|
fishLabel.name = "Fish";
|
||||||
|
fish1.addLabel(fishLabel);
|
||||||
|
fish2.addLabel(fishLabel);
|
||||||
|
|
||||||
|
let template = this.status.model.addBehavior(getBehaviorById("Template"));
|
||||||
|
template.name = "Template"; template.color = [150, 20, 220];
|
||||||
|
|
||||||
|
let dynamicFish = this.status.model.addBehavior(getBehaviorById("PhysicsDynamics"));
|
||||||
|
dynamicFish.name = "Dynamic Fish"; dynamicFish.color = [250, 200, 80];
|
||||||
|
|
||||||
|
let dynamicShark = this.status.model.addBehavior(getBehaviorById("PhysicsDynamics"));
|
||||||
|
dynamicShark.name = "Dynamic Shark"; dynamicShark.color = [250, 200, 80];
|
||||||
|
dynamicShark.parameter.maxAcceleration = 8.5;
|
||||||
|
dynamicShark.parameter.maxVelocity = 15.8;
|
||||||
|
dynamicShark.parameter.resistance = 3.6;
|
||||||
|
|
||||||
|
let brownian = this.status.model.addBehavior(getBehaviorById("Brownian"));
|
||||||
|
brownian.name = "Brownian"; brownian.color = [200, 80, 250];
|
||||||
|
|
||||||
|
let boundary = this.status.model.addBehavior(getBehaviorById("BoundaryConstraint"));
|
||||||
|
boundary.name = "Boundary"; boundary.color = [80, 200, 250];
|
||||||
|
boundary.parameter.range.picker = this.status.model.allRangeLabel;
|
||||||
|
|
||||||
|
let tracking = this.status.model.addBehavior(getBehaviorById("Tracking"));
|
||||||
|
tracking.name = "Tracking"; tracking.color = [80, 200, 250];
|
||||||
|
tracking.parameter.target.picker = fishLabel;
|
||||||
|
|
||||||
|
let attacking = this.status.model.addBehavior(getBehaviorById("ContactAttacking"));
|
||||||
|
attacking.name = "Contact Attacking"; attacking.color = [120, 100, 250];
|
||||||
|
attacking.parameter.target.picker = fishLabel;
|
||||||
|
|
||||||
|
fish1.addBehavior(dynamicFish);
|
||||||
|
fish1.addBehavior(brownian);
|
||||||
|
fish1.addBehavior(boundary);
|
||||||
|
|
||||||
|
fish2.addBehavior(dynamicFish);
|
||||||
|
fish2.addBehavior(brownian);
|
||||||
|
fish2.addBehavior(boundary);
|
||||||
|
|
||||||
|
shark.addBehavior(dynamicShark);
|
||||||
|
shark.addBehavior(boundary);
|
||||||
|
shark.addBehavior(tracking);
|
||||||
|
shark.addBehavior(attacking);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.status.model.updateBehaviorParameter();
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
|
||||||
(window as any).LT = {
|
(window as any).LT = {
|
||||||
status: this.status,
|
status: this.status,
|
||||||
setting: this.setting
|
setting: this.setting
|
||||||
@ -81,9 +193,7 @@ class SimulatorWeb extends Component {
|
|||||||
public render(): ReactNode {
|
public render(): ReactNode {
|
||||||
return <SettingProvider value={this.setting}>
|
return <SettingProvider value={this.setting}>
|
||||||
<StatusProvider value={this.status}>
|
<StatusProvider value={this.status}>
|
||||||
<DndProvider backend={HTML5Backend}>
|
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</DndProvider>
|
|
||||||
</StatusProvider>
|
</StatusProvider>
|
||||||
</SettingProvider>
|
</SettingProvider>
|
||||||
}
|
}
|
||||||
@ -94,8 +204,8 @@ class SimulatorWeb extends Component {
|
|||||||
backgroundLevel={BackgroundLevel.Level5}
|
backgroundLevel={BackgroundLevel.Level5}
|
||||||
fontLevel={FontLevel.Level3}
|
fontLevel={FontLevel.Level3}
|
||||||
>
|
>
|
||||||
|
<LoadFile/>
|
||||||
<Popup/>
|
<Popup/>
|
||||||
<LoadFile>
|
|
||||||
<HeaderBar height={45}/>
|
<HeaderBar height={45}/>
|
||||||
<div className="app-root-space" style={{
|
<div className="app-root-space" style={{
|
||||||
height: `calc( 100% - ${45}px)`
|
height: `calc( 100% - ${45}px)`
|
||||||
@ -103,7 +213,6 @@ class SimulatorWeb extends Component {
|
|||||||
<CommandBar/>
|
<CommandBar/>
|
||||||
<RootContainer/>
|
<RootContainer/>
|
||||||
</div>
|
</div>
|
||||||
</LoadFile>
|
|
||||||
</Theme>
|
</Theme>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user