diff options
-rw-r--r-- | package-lock.json | 435 | ||||
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | src/app/browser.js | 235 | ||||
-rw-r--r-- | src/app/icons/no-image.png | bin | 0 -> 1959 bytes | |||
-rw-r--r-- | src/app/index.html | 15 | ||||
-rw-r--r-- | src/app/main.css | 244 | ||||
-rw-r--r-- | src/app/main.js | 18 | ||||
-rw-r--r-- | src/index.js | 4 | ||||
-rw-r--r-- | src/lang/en.json | 10 | ||||
-rw-r--r-- | src/lang/es.json | 214 | ||||
-rw-r--r-- | src/lang/fr.json | 10 | ||||
-rw-r--r-- | src/utils.js | 130 |
12 files changed, 1155 insertions, 163 deletions
diff --git a/package-lock.json b/package-lock.json index 2a396b9..d5a6d72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,14 @@ "version": "1.0.3", "license": "GPL-3.0-or-later", "dependencies": { - "copy-dir": "^1.3.0", "electron-updater": "^4.6.1", "follow-redirects": "^1.14.7", "fs-extra": "^10.0.0", + "fuse.js": "^6.5.3", "marked": "^4.0.10", "marked-man": "^0.7.0", - "simple-vdf": "^1.1.1", + "recursive-copy": "^2.0.13", + "simple-vdf": "^1.1.1" "unzipper": "^0.10.11" }, "devDependencies": { @@ -424,6 +425,46 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "node_modules/asar": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", @@ -979,11 +1020,6 @@ "node": ">=8" } }, - "node_modules/copy-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==" - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -1078,6 +1114,31 @@ "node": ">= 0.4" } }, + "node_modules/del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dependencies": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1397,6 +1458,17 @@ "node": ">=6" } }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -1542,6 +1614,14 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "node_modules/fuse.js": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.5.3.tgz", + "integrity": "sha512-sA5etGE7yD/pOqivZRBvUBd/NaL2sjAu6QuSaFoe1H2BrJSkH/T/UXAJ8CdXdw7DvY3Hs8CXKYkDWX7RiP5KOg==", + "engines": { + "node": ">=10" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1672,6 +1752,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dependencies": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -1887,6 +1991,36 @@ "node": ">=8" } }, + "node_modules/is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dependencies": { + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd/node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -2076,6 +2210,14 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -2193,6 +2335,20 @@ "node": ">=10" } }, + "node_modules/maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "dependencies": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -2297,6 +2453,14 @@ "node": ">=4" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -2347,6 +2511,11 @@ "node": ">=0.10.0" } }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -2372,6 +2541,25 @@ "node": ">=4" } }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/plist": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz", @@ -2417,6 +2605,14 @@ "node": ">=0.4.0" } }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -2424,6 +2620,11 @@ "dev": true, "optional": true }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -2500,6 +2701,30 @@ "util-deprecate": "~1.0.1" } }, + "node_modules/recursive-copy": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.13.tgz", + "integrity": "sha512-BjmE6R/dOImStEku+017L3Z0I6u/lA+SVr1sySWbTLjmQKDTESNmJ9WBZP8wbN5FuvqNvSYvRKA/IKQhAjqnpQ==", + "dependencies": { + "del": "^2.2.0", + "errno": "^0.1.2", + "graceful-fs": "^4.1.4", + "junk": "^1.0.1", + "maximatch": "^0.1.0", + "mkdirp": "^0.5.1", + "pify": "^2.3.0", + "promise": "^7.0.1", + "slash": "^1.0.0" + } + }, + "node_modules/recursive-copy/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/registry-auth-token": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", @@ -2672,6 +2897,13 @@ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, + "node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "engines": { + "node": ">=0.10.0" + } "node_modules/simple-vdf": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/simple-vdf/-/simple-vdf-1.1.1.tgz", @@ -3547,6 +3779,34 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "asar": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", @@ -3967,11 +4227,6 @@ "xdg-basedir": "^4.0.0" } }, - "copy-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==" - }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -4043,6 +4298,27 @@ "object-keys": "^1.0.12" } }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4300,6 +4576,14 @@ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "requires": { + "prr": "~1.0.1" + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -4412,6 +4696,11 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fuse.js": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.5.3.tgz", + "integrity": "sha512-sA5etGE7yD/pOqivZRBvUBd/NaL2sjAu6QuSaFoe1H2BrJSkH/T/UXAJ8CdXdw7DvY3Hs8CXKYkDWX7RiP5KOg==" + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -4507,6 +4796,26 @@ "define-properties": "^1.1.3" } }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -4660,6 +4969,29 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "^1.0.0" + }, + "dependencies": { + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + } + } + }, "is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -4810,6 +5142,11 @@ "universalify": "^2.0.0" } }, + "junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=" + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -4898,6 +5235,17 @@ "escape-string-regexp": "^4.0.0" } }, + "maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, "mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -4975,6 +5323,11 @@ "pify": "^3.0.0" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -5013,6 +5366,11 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -5032,6 +5390,19 @@ "dev": true, "optional": true }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, "plist": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz", @@ -5067,6 +5438,14 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -5074,6 +5453,11 @@ "dev": true, "optional": true }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -5138,6 +5522,29 @@ "util-deprecate": "~1.0.1" } }, + "recursive-copy": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.13.tgz", + "integrity": "sha512-BjmE6R/dOImStEku+017L3Z0I6u/lA+SVr1sySWbTLjmQKDTESNmJ9WBZP8wbN5FuvqNvSYvRKA/IKQhAjqnpQ==", + "requires": { + "del": "^2.2.0", + "errno": "^0.1.2", + "graceful-fs": "^4.1.4", + "junk": "^1.0.1", + "maximatch": "^0.1.0", + "mkdirp": "^0.5.1", + "pify": "^2.3.0", + "promise": "^7.0.1", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "registry-auth-token": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", @@ -5277,6 +5684,10 @@ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" "simple-vdf": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/simple-vdf/-/simple-vdf-1.1.1.tgz", diff --git a/package.json b/package.json index 0eaccd8..fc0381f 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,13 @@ }, "homepage": "https://github.com/0neGal/viper#readme", "dependencies": { - "copy-dir": "^1.3.0", "electron-updater": "^4.6.1", "follow-redirects": "^1.14.7", "fs-extra": "^10.0.0", + "fuse.js": "^6.5.3", "marked": "^4.0.10", "marked-man": "^0.7.0", + "recursive-copy": "^2.0.13", "simple-vdf": "^1.1.1", "unzipper": "^0.10.11" }, diff --git a/src/app/browser.js b/src/app/browser.js new file mode 100644 index 0000000..5062d86 --- /dev/null +++ b/src/app/browser.js @@ -0,0 +1,235 @@ +const Fuse = require("fuse.js"); +var fuse; +var packages = []; + +var Browser = { + maxentries: 50, + toggle: (state) => { + if (state) { + browser.scrollTo(0, 0); + overlay.classList.add("shown") + browser.classList.add("shown") + return + } else if (! state) { + if (state != undefined) { + overlay.classList.remove("shown") + browser.classList.remove("shown") + return + } + } + + browser.scrollTo(0, 0); + overlay.classList.toggle("shown") + browser.classList.toggle("shown") + }, + loadfront: async () => { + Browser.loading(); + + if (packages.length < 1) { + packages = await (await fetch("https://northstar.thunderstore.io/api/v1/package/")).json(); + + fuse = new Fuse(packages, { + keys: ["full_name"] + }) + } + + for (let i in packages) { + if (i == Browser.maxentries) {Browser.endoflist();break} + new BrowserElFromObj(packages[i]); + } + }, + loading: (string) => { + if (string) { + browserEntries.innerHTML = `<div class="loading">${string}</div>`; + } + + if (! browserEntries.querySelector(".loading")) { + browserEntries.innerHTML = `<div class="loading">${lang('gui.browser.loading')}</div>`; + } + }, + endoflist: () => { + browserEntries.innerHTML += `<div class="message">${lang('gui.browser.endoflist')}</div>` + }, + search: (string) => { + Browser.loading(); + let res = fuse.search(string); + + if (res.length < 1) { + Browser.loading("No results...") + return + } + + for (let i = 0; i < res.length; i++) { + if (i == Browser.maxentries) {Browser.endoflist();break} + new BrowserElFromObj(res[i].item); + } + }, + setbutton: (mod, string) => { + mod = normalize(mod); + if (document.getElementById(mod)) { + let elems = document.querySelectorAll(`#${mod}`); + + for (let i = 0; i < elems.length; i++) { + elems[i].querySelector(".text button").innerHTML = string; + } + } else { + let make = (str) => { + if (document.getElementById(str)) { + return Browser.setbutton(str, string); + } else { + return false; + } + } + + setTimeout(() => { + for (let i = 0; i < modsobj.all.length; i++) { + let modname = normalize(modsobj.all[i].Name); + let modfolder = normalize(modsobj.all[i].FolderName); + + if (mod.includes(modname)) { + if (! make(modname)) { + if (modsobj.all[i].ManifestName) { + make(normalize(modsobj.all[i].ManifestName)); + } + } + } + else if (mod.includes(modfolder)) {make(modfolder);break} + } + }, 1501) + } + } +}; Browser.loadfront() + +document.body.addEventListener("keyup", (e) => { + if (e.key == "Escape") {Browser.toggle(false)} +}) + +function BrowserElFromObj(obj) { + let pkg = {...obj, ...obj.versions[0]}; + + new BrowserEl({ + title: pkg.name, + image: pkg.icon, + author: pkg.owner, + url: pkg.package_url, + download: pkg.download_url, + version: pkg.version_number, + description: pkg.description + }) +} + +function BrowserEl(properties) { + properties = { + title: "No name", + version: "1.0.0", + image: "icons/no-image.png", + author: "Unnamed Pilot", + description: "No description", + ...properties + } + + if (properties.version[0] != "v") { + properties.version = "v" + properties.version; + } + + if (browserEntries.querySelector(".loading")) { + browserEntries.innerHTML = ""; + } + + let installstr = lang("gui.browser.install"); + + if (normalize(modsdiv.innerText.split("\n")).includes(normalize(properties.title))) { + installstr = lang("gui.browser.reinstall"); + + for (let i = 0; i < modsobj.all.length; i++) { + if (normalize(modsobj.all[i].Name) == normalize(properties.title) + && "v" + modsobj.all[i].Version != properties.version) { + + installstr = lang("gui.browser.update"); + } + } + } else { + for (let i = 0; i < modsobj.all.length; i++) { + let title = normalize(properties.title); + let folder = normalize(modsobj.all[i].FolderName); + let manifestname = null; + if (modsobj.all[i].ManifestName) { + manifestname = normalize(modsobj.all[i].ManifestName); + } + + if (title.includes(folder) || title.includes(manifestname)) { + installstr = lang("gui.browser.reinstall"); + + if (folder == title + && "v" + modsobj.all[i].Version != properties.version) { + + installstr = lang("gui.browser.update"); + } + } + } + } + + browserEntries.innerHTML += ` + <div class="el" id="${normalize(properties.title)}"> + <div class="image"> + <img src="${properties.image}"> + </div> + <div class="text"> + <div class="title">${properties.title}</div> + <div class="description">${properties.description}</div> + <button onclick="installFromURL('${properties.download}')">${installstr}</button> + <button onclick="require('electron').shell.openExternal('${properties.url}')">${lang('gui.browser.info')}</button> + <button class="visual">${properties.version}</button> + <button class="visual">${lang("gui.browser.madeby")} ${properties.author}</button> + </div> + </div> + ` +} + +ipcRenderer.on("removedmod", (event, mod) => { + setButtons(true); + Browser.setbutton(mod.name, lang("gui.browser.install")); + if (mod.manifestname) { + Browser.setbutton(mod.manifestname, lang("gui.browser.install")); + } +}) + +ipcRenderer.on("installedmod", (event, modname) => { + setButtons(true); + Browser.setbutton(modname, lang("gui.browser.reinstall")); +}) + +function normalize(items) { + let main = (string) => { + return string.replaceAll(" ", "").replaceAll(".", "").replaceAll("-", "").replaceAll("_", "").toLowerCase() + } + if (typeof items == "string") { + return main(items) + } else { + let newArray = []; + for (let i = 0; i < items.length; i++) { + newArray.push(main(items[i])); + } + + return newArray; + } +} + +let searchtimeout; +let searchstr = ""; +search.addEventListener("keyup", () => { + clearTimeout(searchtimeout); + + if (searchstr != search.value) { + if (search.value.replaceAll(" ", "") == "") { + searchstr = ""; + Browser.loadfront(); + return + } + + searchtimeout = setTimeout(() => { + Browser.search(search.value); + searchstr = search.value; + }, 500) + } +}) diff --git a/src/app/icons/no-image.png b/src/app/icons/no-image.png Binary files differnew file mode 100644 index 0000000..43265d1 --- /dev/null +++ b/src/app/icons/no-image.png diff --git a/src/app/index.html b/src/app/index.html index fe383a0..b861736 100644 --- a/src/app/index.html +++ b/src/app/index.html @@ -12,6 +12,19 @@ <div id="minimize" onclick="ipcRenderer.send('minimize')"></div> <div id="close" onclick="ipcRenderer.send('exit')"></div> </div> + + <div id="overlay" onclick="Browser.toggle(false)"></div> + <div id="browser"> + <div id="misc"> + <input id="search" placeholder="%%gui.browser.search%%"> + <button id="close" onclick="Browser.toggle(false)"> + <img src="icons/close.png"> + </button> + </div> + <div id="browserEntries"> + <div class="loading">%%gui.browser.loading%%</div> + </div> + </div> <nav class="gamesContainer"> <button id="vpBtn" onclick="page(0)"></button> @@ -79,6 +92,7 @@ <button id="togglemod" onclick="selected().toggle()">%%gui.mods.toggle%%</button> <button id="toggleall" onclick="selected(true).toggle(true)">%%gui.mods.toggleall%%</button> <button id="installmod" onclick="installmod()">%%gui.mods.install%%</button> + <button id="installmod" onclick="Browser.toggle(true)">%%gui.mods.find%%</button> </div> </div> </div> @@ -102,6 +116,7 @@ <script src="lang.js"></script> <script src="main.js"></script> + <script src="browser.js"></script> <script src="launcher.js"></script> </body> </html> diff --git a/src/app/main.css b/src/app/main.css index de0db46..94ef767 100644 --- a/src/app/main.css +++ b/src/app/main.css @@ -9,7 +9,11 @@ --selbg: rgba(80, 80, 80, 0.5); --redbg: linear-gradient(45deg, var(--red), #FA4343); --bluebg: linear-gradient(45deg, var(--blue), #7380ED); +} +#browser, #modsdiv { + outline: 1px solid #444444; + border: 3px solid var(--bg); } ::-webkit-scrollbar { @@ -26,12 +30,191 @@ background: var(--red); } +::selection { + color: black; + background: var(--red); +} + +body { + margin: 0; + overflow: hidden; + user-select: none; +} + +body, button, input {font-family: "Roboto", sans-serif} + +button {outline: none} +b, strong {font-weight: 700} +body, input, button {font-weight: 500} + +button { + border: none; + color: white; + outline: none; + cursor: pointer; + font-weight: 700; + padding: 5px 10px; + border-radius: 5px; + transition: 0.2s ease-in-out; +} + .playBtn, .gamesContainer button, #winbtns div { cursor: pointer; } -#winbtns { +#browser { + --spacing: var(--padding); + + z-index: 2; + opacity: 0.0; + position: fixed; + overflow-y: scroll; + top: var(--spacing); + pointer-events: none; + left: var(--spacing); + background: var(--bg); + right: var(--spacing); + bottom: var(--spacing); + transform: scale(0.98); + backdrop-filter: blur(15px); + border-radius: calc(var(--padding) / 3); + transition: opacity 0.15s ease-in-out, transform 0.15s ease-in-out; +} + +#browser.shown { + opacity: 1.0; + pointer-events: all; + transform: scale(1.0); +} + +#overlay { + top: 0; + left: 0; + right: 0; + bottom: 0; z-index: 1; + opacity: 0.0; + position: fixed; + background: var(--bg); + pointer-events: none; + transition: opacity 0.15s ease-in-out; +} + +#overlay.shown { + opacity: 0.8; + pointer-events: all; +} + +@keyframes fadein { + 0% {opacity: 0.0} + 100% {opacity: 1.0} +} + +#browser .el, #browser #misc, #browser .loading { + --spacing: calc(var(--padding) / 2); + --height: calc(var(--padding) * 3); + --mischeight: calc(var(--padding) * 1.5); + + animation-duration: 0.15s; + animation-iteration-count: 1; + animation-name: fadein; + animation-fill-mode: forwards; + animation-timing-function: ease-in-out; + + opacity: 0.0; + transition: 0.15s ease-in-out; +} + +#browser .el, #browser #search, #browser #close { + color: white; + display: flex; + align-items: center; + height: var(--height); + margin: var(--spacing); + padding: var(--spacing); + background: var(--selbg); + border-radius: var(--spacing); + width: calc(100% - var(--spacing) * 4); +} + +#browser #misc, #browser #search { + --height: var(--mischeight); +} + +#browser #misc { + display: flex; +} + +#browser #search { + border: none; + outline: none; + transition: filter 0.15s ease-in-out; + width: calc(100% - var(--spacing) * 2); +} + +#browser #search:focus { + filter: brightness(1.5); +} + +#browser #close { + --height: calc(var(--padding) * 1.5); + + padding: 0px; + margin-left: 0px; + width: var(--height); +} + +#browser #close img { + opacity: 0.6; + width: var(--height); + height: var(--height); + transform: scale(0.6); +} + +#browser .loading { + width: 100%; + color: white; + display: flex; + text-align: center; + align-items: center; + justify-content: center; + height: calc(100% - var(--mischeight) - var(--height)); +} + +#browser .message { + color: white; + text-align: center; + margin: var(--padding); + width: calc(100% - var(--padding)); +} + +#browser .el .image, #browser .el .image img { + width: var(--height); + height: var(--height); + margin-right: var(--spacing); + border-radius: var(--spacing); +} + +#browser .el .text { + overflow: hidden; +} + +#browser .el .title, #browser .el .description { + height: 1.2em; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +#browser .el .title {font-size: 1.2em} +#browser .el .description {font-size: 0.8em} +#browser .el button { + background: var(--blue); + margin-top: var(--spacing); +} + +#winbtns { + z-index: 2; display: flex; position: fixed; top: var(--padding); @@ -54,40 +237,18 @@ #winbtns div:hover {opacity: 1.0} #winbtns div:active {transform: scale(0.98)} -body { - margin: 0; - overflow: hidden; - user-select: none; - font-family: "Roboto", sans-serif; -} - -button {outline: none} -b, strong {font-weight: 700} -body, input, button {font-weight: 500} - -button { - border: none; - color: white; - outline: none; - font-weight: 700; - padding: 5px 10px; - border-radius: 5px; - transition: 0.2s ease-in-out; -} - button:hover {filter: brightness(110%)} button:active {filter: brightness(90%)} img {pointer-events: none} #bgHolder { - top: 0; - left: 0; - right: 0; - bottom: 0; - pointer-events: none; - position: fixed; - transform: scale(1.1); + top: -5px; + left: -5px; + right: -5px; + bottom: -5px; + z-index: -1; + position: absolute; background-size: cover; background-position: center; background-repeat: no-repeat; @@ -162,7 +323,7 @@ img {pointer-events: none} } .contentContainer { - width: 90%; + width: 85%; color: white; flex-grow: 1; opacity: 1.0; @@ -346,6 +507,12 @@ button:disabled { pointer-events: none; } +button.visual { + opacity: 1.0; + pointer-events: none; + background: transparent !important; +} + code { font-size: 16px; padding: 2px 5px; @@ -385,16 +552,27 @@ code { } .modbtns button { - margin-left: calc(var(--padding) / 3); + margin-left: var(--spacing); + --spacing: calc(var(--padding) / 3); + margin-top: calc(var(--spacing) / 2); + margin-bottom: calc(var(--spacing) / 2); } /* drag control */ -#bgHolder { +#bgHolder, +.contentContainer, +.gamesContainer { user-select: none; -webkit-app-region: drag; } -a, button, .contentMenu, #close, #nsRelease, #vpReleaseNotes, .mod { +#overlay.shown ~ #bgHolder, +#overlay.shown ~ .contentContainer, +#overlay.shown ~ .gamesContainer { + -webkit-app-region: no-drag; +} + +a, button, #close, #nsRelease, #vpReleaseNotes, .mod, #overlay, #modsdiv, #winbtns, .contentMenu { -webkit-app-region: no-drag; } diff --git a/src/app/main.js b/src/app/main.js index 19f6c9e..169f86f 100644 --- a/src/app/main.js +++ b/src/app/main.js @@ -3,6 +3,7 @@ const path = require("path"); const { ipcRenderer, shell } = require("electron"); const lang = require("../lang"); +var modsobj = {}; let shouldInstallNorthstar = false; // Base settings @@ -66,6 +67,15 @@ function log(msg) { // updating/installing Northstar. function setButtons(state) { playNsBtn.disabled = !state; + + let disablearray = (array) => { + for (let i = 0; i < array.length; i++) { + array[i].disabled = !state; + } + } + + disablearray(document.querySelectorAll("#nsMods .buttons.modbtns button")) + disablearray(document.querySelectorAll("#browser #browserEntries .text button")) } // Frontend part of updating Northstar @@ -148,9 +158,16 @@ function selected(all) { // Tells the main process to install a mod function installmod() { + setButtons(false); ipcRenderer.send("installmod") } +// Tells the main process to install a mod from a URL +function installFromURL(url) { + setButtons(false); + ipcRenderer.send("installfromurl", url) +} + // Frontend part of settings a new game path ipcRenderer.on("newpath", (event, newpath) => { settings.gamepath = newpath; @@ -163,6 +180,7 @@ ipcRenderer.on("alert", (event, msg) => {alert(msg)}) // Updates the installed mods ipcRenderer.on("mods", (event, mods) => { + modsobj = mods; if (! mods) {return} modcount.innerHTML = `${lang("gui.mods.count")} ${mods.all.length}`; diff --git a/src/index.js b/src/index.js index c8bfc53..a06cf69 100644 --- a/src/index.js +++ b/src/index.js @@ -43,9 +43,13 @@ function start() { ipcMain.on("exit", () => {process.exit(0)}) ipcMain.on("minimize", () => {win.minimize()}) + ipcMain.on("installfromurl", (event, url) => {utils.mods.installFromURL(url)}) ipcMain.on("winLog", (event, ...args) => {win.webContents.send("log", ...args)}); ipcMain.on("winAlert", (event, ...args) => {win.webContents.send("alert", ...args)}); ipcMain.on("ns-update-event", (event) => win.webContents.send("ns-update-event", event)); + ipcMain.on("failedmod", (event, modname) => {win.webContents.send("failedmod", modname)}); + ipcMain.on("removedmod", (event, modname) => {win.webContents.send("removedmod", modname)}); + ipcMain.on("installedmod", (event, modname) => {win.webContents.send("installedmod", modname)}); ipcMain.on("guigetmods", (event, ...args) => {win.webContents.send("mods", utils.mods.list())}); win.webContents.on("dom-ready", () => { diff --git a/src/lang/en.json b/src/lang/en.json index fe9b0b0..a9eb47f 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -49,6 +49,7 @@ "gui.mods.count": "Mods Installed:", "gui.mods.disabledtag": "Disabled", "gui.mods.install": "Install Mod", + "gui.mods.find": "Find Mods", "gui.mods.toggle": "Toggle Mod", "gui.mods.toggleall": "Toggle All", "gui.mods.remove": "Remove Mod", @@ -62,6 +63,15 @@ "gui.mods.installing": "Installing mod...", "gui.mods.installedmod": "Installed mod!", + "gui.browser.info": "Info", + "gui.browser.madeby": "by", + "gui.browser.search": "Search...", + "gui.browser.update": "Update", + "gui.browser.install": "Install", + "gui.browser.reinstall": "Re-Install", + "gui.browser.loading": "Loading mods...", + "gui.browser.endoflist": "Maximum packages has been loaded.<br>Use the search for finding other packages!", + "gui.update.downloading": "Downloading...", "gui.update.extracting": "Extracting update...", "gui.update.finished": "Done! Ready to play!", diff --git a/src/lang/es.json b/src/lang/es.json index c6e282d..9eac2b0 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -1,102 +1,112 @@ -{
- "cli.help.help": "muestra este mensaje de ayuda",
- "cli.help.debug": "habre las herramientas de desarrollador/depuración ",
- "cli.help.version": "muestra la información de la versión",
- "cli.help.cli": "obliga la linea de comandos a habilitarse",
- "cli.help.update": "actualiza Northstar desde la ruta de juego establecida",
- "cli.help.setpath": "establece la ruta del juego",
- "cli.help.updatevp": "actualiza Viper si es soportado",
- "cli.help.installmod": "instala una modificación, desde una carpeta o zip",
- "cli.help.removemod": "remueve una modificación",
- "cli.help.togglemod": "alterna el estado de la modificación",
-
- "cli.setpath.noarg": "No se ha proporcionado ningún argumento para --setpath",
-
- "cli.update.current": "Versión actual:",
- "cli.update.downloading": "Descargando...",
- "cli.update.checking": "Buscando actualizaciones...",
- "cli.update.downloaddone": "¡Descarga completa! Extrayendo...",
- "cli.update.finished": "Instalación/Actualización completada!",
- "cli.update.uptodate": "La ultima versión (%s) ya está instalada, omitiendo actualización.",
- "cli.update.uptodate.short": "Está actualizado",
-
- "cli.autoupdates.checking": "Buscando actualizaciones de Northstar...",
- "cli.autoupdates.available": "¡Actualización de Northsar disponible!",
- "cli.autoupdates.gamerunning": "El juego se está ejecutando, no se puede actualizar Northstar",
- "cli.autoupdates.updatingns": "Lanzando proceso de actualización...",
- "cli.autoupdates.noupdate": "No hay actualizaciones de Northstar disponibles.",
-
- "cli.launch.linuxerror": "La ejecución del juego en Linux aun no está implementada",
-
- "cli.mods.failed": "¡Fallo al instalar el mod!",
- "cli.mods.removed": "¡Modificación removida exitosamente!",
- "cli.mods.toggled": "¡El estado de la modificación ha cambiado exitosamente!",
- "cli.mods.installed": "¡Modificiación instalada exitosamente!",
- "cli.mods.cantfind": "¡No se encuentra una modificación con ese nombre!",
- "cli.mods.notamod": "La carpeta o el archivo seleccionado no es una modificación",
- "cli.mods.toggledall": "¡Estado de todas las modiciaciones ha sido cambiado exitosamente!",
- "cli.mods.improperjson": "%s's mod.json tiene errores de formato",
-
- "gui.welcome": "Bienvenido a Viper!",
- "gui.versions.viper": "Versión de Viper",
- "gui.versions.northstar": "Versión de Northstar",
- "gui.exit": "Salir",
- "gui.update": "Actualizar",
- "gui.setpath": "Cambiar la ruta del juego",
-
- "gui.update.check": "Buscar actualizaciones",
- "gui.mods": "Modificaciones (Mods)",
- "gui.mods.count": "Modificaciones instaladas:",
- "gui.mods.disabledtag": "Deshabilitado",
- "gui.mods.install": "Instalar modificación",
- "gui.mods.toggle": "Alternar modificación",
- "gui.mods.toggleall": "Alternar todo",
- "gui.mods.remove": "Remover modificación",
- "gui.mods.removeall": "Remover todo",
- "gui.mods.nothingselected": "No has seleccionado una modificación.",
- "gui.mods.toggleall.confirm": "Alternar todo podría deshabilitar las modificaciones requeridas para que Northstar funcione. ¿Está seguro?",
- "gui.mods.removeall.confirm": "Eliminar todas las modificaciones generalmente requerirá que reinstales Northstar. ¿Está seguro?",
- "gui.mods.required.confirm": "Ha seleccionado un mod esencial, es posible que Northstar no funcione sin él. ¿Está seguro?",
- "gui.mods.notamod": "¡No es una modificación!",
- "gui.mods.extracting": "Extrayendo modificación...",
- "gui.mods.installing": "Instalando modificación...",
- "gui.mods.installedmod": "¡Modificación instalada!",
-
- "gui.update.downloading": "Descargando...",
- "gui.update.extracting": "Extrayendo actualización...",
- "gui.update.finished": "¡Hecho! ¡Está listo para jugar!",
- "gui.update.uptodate": "¡Ya está actualizado!",
- "gui.update.available": "Hay una actualización disponible para Viper, ¿desea reiniciar y aplicarla?",
-
- "gui.nsupdate.gaming.title": "¡Actualización de Northstar disponible!",
- "gui.nsupdate.gaming.body": "Una actualización de northstar está disponible.\nPuedes forzar su instalación despues de cerrar el juego.",
-
- "gui.launch": "Ejecutar",
- "gui.launchvanilla": "Vanilla",
- "gui.launchnorthstar": "Northstar",
- "gui.installnorthstar": "Instalar",
-
- "gui.selectpath": "Por favor, ¡elija la ruta del juego!",
- "gui.gamepath.must": "La ruta del juego debe establecerse para ejecutar Viper.",
- "gui.gamepath.wrong": "Esta carpeta no es una ruta válida para el juego.",
-
- "viper.menu.main": "Viper",
- "viper.menu.release": "Notas de la versión",
- "viper.menu.info": "Extras",
- "viper.menu.info.links": "Links",
- "viper.menu.info.credits": "Creditos",
-
- "viper.info.discord": "Unete al Discord:",
- "viper.info.issues": "Reporta problemas de Viper:",
-
- "ns.menu.main": "Northstar Launcher",
- "ns.menu.mods": "Modificiaciones",
- "ns.menu.release": "Notas de actualización",
-
- "general.mods.enabled": "Modificaciones habilitadas:",
- "general.mods.disabled": "Modificaciones deshabilitadas:",
- "general.mods.installed": "Modificiaciones intaladas:",
- "general.missingpath": "¡La ruta del jueno no se ha podido encontrar automaticamente! ¡Por favor, elige la ruta manualmente!",
- "general.notinstalled": "¡Northstar no se ha instalado!",
- "general.launching": "Ejecutando"
-}
+{ + "cli.help.help": "muestra este mensaje de ayuda", + "cli.help.debug": "habre las herramientas de desarrollador/depuración ", + "cli.help.version": "muestra la información de la versión", + "cli.help.cli": "obliga la linea de comandos a habilitarse", + "cli.help.update": "actualiza Northstar desde la ruta de juego establecida", + "cli.help.setpath": "establece la ruta del juego", + "cli.help.updatevp": "actualiza Viper si es soportado", + "cli.help.installmod": "instala una modificación, desde una carpeta o zip", + "cli.help.removemod": "remueve una modificación", + "cli.help.togglemod": "alterna el estado de la modificación", + + "cli.setpath.noarg": "No se ha proporcionado ningún argumento para --setpath", + + "cli.update.current": "Versión actual:", + "cli.update.downloading": "Descargando...", + "cli.update.checking": "Buscando actualizaciones...", + "cli.update.downloaddone": "¡Descarga completa! Extrayendo...", + "cli.update.finished": "Instalación/Actualización completada!", + "cli.update.uptodate": "La ultima versión (%s) ya está instalada, omitiendo actualización.", + "cli.update.uptodate.short": "Está actualizado", + + "cli.autoupdates.checking": "Buscando actualizaciones de Northstar...", + "cli.autoupdates.available": "¡Actualización de Northsar disponible!", + "cli.autoupdates.gamerunning": "El juego se está ejecutando, no se puede actualizar Northstar", + "cli.autoupdates.updatingns": "Lanzando proceso de actualización...", + "cli.autoupdates.noupdate": "No hay actualizaciones de Northstar disponibles.", + + "cli.launch.linuxerror": "La ejecución del juego en Linux aun no está implementada", + + "cli.mods.failed": "¡Fallo al instalar el mod!", + "cli.mods.removed": "¡Modificación removida exitosamente!", + "cli.mods.toggled": "¡El estado de la modificación ha cambiado exitosamente!", + "cli.mods.installed": "¡Modificiación instalada exitosamente!", + "cli.mods.cantfind": "¡No se encuentra una modificación con ese nombre!", + "cli.mods.notamod": "La carpeta o el archivo seleccionado no es una modificación", + "cli.mods.toggledall": "¡Estado de todas las modiciaciones ha sido cambiado exitosamente!", + "cli.mods.improperjson": "%s's mod.json tiene errores de formato", + + "gui.welcome": "Bienvenido a Viper!", + "gui.versions.viper": "Versión de Viper", + "gui.versions.northstar": "Versión de Northstar", + "gui.exit": "Salir", + "gui.update": "Actualizar", + "gui.setpath": "Cambiar la ruta del juego", + + "gui.update.check": "Buscar actualizaciones", + "gui.mods": "Modificaciones (Mods)", + "gui.mods.count": "Modificaciones instaladas:", + "gui.mods.disabledtag": "Deshabilitado", + "gui.mods.install": "Instalar modificación", + "gui.mods.find": "Encontrar modificaciones", + "gui.mods.toggle": "Alternar modificación", + "gui.mods.toggleall": "Alternar todo", + "gui.mods.remove": "Remover modificación", + "gui.mods.removeall": "Remover todo", + "gui.mods.nothingselected": "No has seleccionado una modificación.", + "gui.mods.toggleall.confirm": "Alternar todo podría deshabilitar las modificaciones requeridas para que Northstar funcione. ¿Está seguro?", + "gui.mods.removeall.confirm": "Eliminar todas las modificaciones generalmente requerirá que reinstales Northstar. ¿Está seguro?", + "gui.mods.required.confirm": "Ha seleccionado un mod esencial, es posible que Northstar no funcione sin él. ¿Está seguro?", + "gui.mods.notamod": "¡No es una modificación!", + "gui.mods.extracting": "Extrayendo modificación...", + "gui.mods.installing": "Instalando modificación...", + "gui.mods.installedmod": "¡Modificación instalada!", + + "gui.browser.info": "Información", + "gui.browser.madeby": "por", + "gui.browser.search": "Buscar...", + "gui.browser.update": "Actualizar", + "gui.browser.install": "Instalar", + "gui.browser.reinstall": "Re-Instalar", + "gui.browser.loading": "Cargando modificaciones...", + "gui.browser.endoflist": "Se ha cargado el máximo de paquetes.<br>¡Usa la búsqueda para encontrar otros paquetes!", + + "gui.update.downloading": "Descargando...", + "gui.update.extracting": "Extrayendo actualización...", + "gui.update.finished": "¡Hecho! ¡Está listo para jugar!", + "gui.update.uptodate": "¡Ya está actualizado!", + "gui.update.available": "Hay una actualización disponible para Viper, ¿desea reiniciar y aplicarla?", + + "gui.nsupdate.gaming.title": "¡Actualización de Northstar disponible!", + "gui.nsupdate.gaming.body": "Una actualización de northstar está disponible.\nPuedes forzar su instalación despues de cerrar el juego.", + + "gui.launch": "Ejecutar", + "gui.launchvanilla": "Vainilla", + "gui.launchnorthstar": "Northstar", + "gui.installnorthstar": "Instalar", + + "gui.selectpath": "Por favor, ¡elija la ruta del juego!", + "gui.gamepath.must": "La ruta del juego debe establecerse para ejecutar Viper.", + "gui.gamepath.wrong": "Esta carpeta no es una ruta válida para el juego.", + + "viper.menu.main": "Viper", + "viper.menu.release": "Notas de la versión", + "viper.menu.info": "Extras", + "viper.menu.info.links": "Links", + "viper.menu.info.credits": "Creditos", + + "viper.info.discord": "Unete al Discord:", + "viper.info.issues": "Reporta problemas de Viper:", + + "ns.menu.main": "Northstar Launcher", + "ns.menu.mods": "Modificiaciones", + "ns.menu.release": "Notas de actualización", + + "general.mods.enabled": "Modificaciones habilitadas:", + "general.mods.disabled": "Modificaciones deshabilitadas:", + "general.mods.installed": "Modificiaciones intaladas:", + "general.missingpath": "¡La ruta del jueno no se ha podido encontrar automaticamente! ¡Por favor, elige la ruta manualmente!", + "general.notinstalled": "¡Northstar no se ha instalado!", + "general.launching": "Ejecutando" +}
\ No newline at end of file diff --git a/src/lang/fr.json b/src/lang/fr.json index 2fbc89a..4e6103a 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -49,6 +49,7 @@ "gui.mods.count": "Mods installés :", "gui.mods.disabledtag": "Désactivé", "gui.mods.install": "Installer le mod", + "gui.mods.find": "Chercher des mods", "gui.mods.toggle": "Activer/désactiver le mod", "gui.mods.toggleall": "Activer/désactiver tous les mods", "gui.mods.remove": "Supprimer le mod", @@ -62,6 +63,15 @@ "gui.mods.installing": "Installation du mod...", "gui.mods.installedmod": "Mod installé !", + "gui.browser.info": "Info", + "gui.browser.madeby": "par", + "gui.browser.search": "Rechercher", + "gui.browser.update": "Mise à jour", + "gui.browser.install": "Installer", + "gui.browser.reinstall": "Réinstaller", + "gui.browser.loading": "Chargement des mods...", + "gui.browser.endoflist": "Fin de la liste de mods.<br>Utilisez la barre de recherche pour en trouver davantage !", + "gui.update.downloading": "Téléchargement de la mise à jour...", "gui.update.extracting": "Extraction des fichiers...", "gui.update.finished": "Terminé, vous pouvez jouer !", diff --git a/src/utils.js b/src/utils.js index 0507921..1887dd1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ const path = require("path"); const fs = require("fs-extra"); -const copy = require("copy-dir"); +const copy = require("recursive-copy"); const { app, dialog, ipcMain, Notification } = require("electron"); const Emitter = require("events"); @@ -374,9 +374,14 @@ const mods = { try { mods.push({...require(path.join(modpath, file, "mod.json")), FolderName: file, Disabled: false}) }catch(err) { - console.log("error: " + lang("cli.mods.improperjson"), file) + if (cli.hasArgs()) {console.log("error: " + lang("cli.mods.improperjson"), file)} mods.push({Name: file, FolderName: file, Version: "unknown", Disabled: false}) } + + let manifest = path.join(modpath, file, "manifest.json"); + if (fs.existsSync(manifest)) { + mods[mods.length - 1].ManifestName = require(manifest).name; + } } } }) @@ -393,10 +398,15 @@ const mods = { try { disabled.push({...require(path.join(disabledPath, file, "mod.json")), FolderName: file, Disabled: true}) }catch(err) { - console.log("error: " + lang("cli.mods.improperjson"), file) + if (cli.hasArgs()) {console.log("error: " + lang("cli.mods.improperjson"), file)} disabled.push({Name: file, FolderName: file, Version: "unknown", Disabled: true}) } } + + let manifest = path.join(modpath, file, "manifest.json"); + if (fs.existsSync(manifest)) { + mods[mods.length - 1].ManifestName = require(manifest).name; + } } }) @@ -439,8 +449,8 @@ const mods = { // Either a zip or folder is supported, we'll also try to search // inside the zip or folder to see if buried in another folder or // not, as sometimes that's the case. - install: (mod) => { - let modpath = path.join(settings.gamepath, "R2Northstar/mods"); + install: (mod, destname, manifestfile) => { + let modname = mod.replace(/^.*(\\|\/|\:)/, ""); if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) @@ -461,6 +471,16 @@ const mods = { cli.exit(); winLog(lang("gui.mods.installedmod")) + + if (modname == "mods") { + let manifest = path.join(app.getPath("userData"), "Archives/manifest.json") + + if (fs.existsSync(manifest)) { + modname = require(manifest).name; + } + } + + ipcMain.emit("installedmod", "", modname); ipcMain.emit("guigetmods"); return true; } @@ -469,14 +489,17 @@ const mods = { if (fs.statSync(mod).isDirectory()) { winLog(lang("gui.mods.installing")) + files = fs.readdirSync(mod); if (fs.existsSync(path.join(mod, "mod.json")) && fs.statSync(path.join(mod, "mod.json")).isFile()) { - copy.sync(mod, path.join(modpath, mod.replace(/^.*(\\|\/|\:)/, "")), { - mode: true, - cover: true, - utimes: true, - }); + if (fs.existsSync(path.join(modpath, modname))) { + fs.rmSync(path.join(modpath, modname), {recursive: true}); + } + let copydest = path.join(modpath, modname); + if (typeof destname == "string") {copydest = path.join(modpath, destname)} + copy(mod, copydest) + copy(manifestfile, path.join(copydest, "manifest.json")) return installed(); } else { @@ -487,6 +510,7 @@ const mods = { if (fs.existsSync(path.join(mod, files[i], "mod.json")) && fs.statSync(path.join(mod, files[i], "mod.json")).isFile()) { + console.log(mods.install(path.join(mod, files[i]))) if (mods.install(path.join(mod, files[i]))) {return true}; } } @@ -500,21 +524,84 @@ const mods = { let cache = path.join(app.getPath("userData"), "Archives"); if (fs.existsSync(cache)) { fs.rmSync(cache, {recursive: true}); - fs.mkdirSync(cache); + fs.mkdirSync(path.join(cache, "mods"), {recursive: true}); } else { - fs.mkdirSync(cache); + fs.mkdirSync(path.join(cache, "mods"), {recursive: true}); } try { fs.createReadStream(mod).pipe(unzip.Extract({path: cache})) .on("finish", () => { - if (mods.install(cache)) { - installed(); - } else {return notamod()} + setTimeout(() => { + let manifest = path.join(cache, "manifest.json"); + if (fs.existsSync(manifest)) { + files = fs.readdirSync(path.join(cache, "mods")); + + if (fs.existsSync(path.join(cache, "mods/mod.json"))) { + if (mods.install(path.join(cache, "mods"), require(manifest).name, manifest)) { + return true; + } + } else { + for (let i = 0; i < files.length; i++) { + let mod = path.join(cache, "mods", files[i]); + if (fs.statSync(mod).isDirectory()) { + setTimeout(() => { + if (mods.install(mod, false, manifest)) {return true}; + }, 1000) + } + } + } + + return notamod(); + } + + if (mods.install(cache)) { + installed(); + } else {return notamod()} + }, 1000) }); }catch(err) {return notamod()} } }, + + // Installs mods from URL's + // + // This'll simply download the file that the URL points to and then + // install it with mods.install() + installFromURL: (url) => { + https.get(url, (res) => { + let tmp = path.join(app.getPath("cache"), "vipertmp"); + let modlocation = path.join(tmp, "/mod.zip"); + + if (fs.existsSync(tmp)) { + if (! fs.statSync(tmp).isDirectory()) { + fs.rmSync(tmp) + } + } else { + fs.mkdirSync(tmp) + if (fs.existsSync(modlocation)) { + fs.rmSync(modlocation) + } + } + + let stream = fs.createWriteStream(modlocation); + res.pipe(stream); + + // let received = 0; + // // Progress messages, we should probably switch this to + // // percentage instead of how much is downloaded. + // res.on("data", (chunk) => { + // received += chunk.length; + // ipcMain.emit("ns-update-event", lang("gui.update.downloading") + " " + (received / 1024 / 1024).toFixed(1) + "mb"); + // }) + + stream.on("finish", () => { + stream.close(); + mods.install(modlocation) + }) + }) + }, + // Removes mods // // Takes in the names of the mod then removes it, no confirmation, @@ -556,10 +643,19 @@ const mods = { } if (fs.statSync(modPath).isDirectory()) { + let manifestname = null; + if (fs.existsSync(path.join(modPath, "manifest.json"))) { + manifestname = require(path.join(modPath, "manifest.json")).name; + } + fs.rmSync(modPath, {recursive: true}); console.log(lang("cli.mods.removed")); cli.exit(); ipcMain.emit("guigetmods"); + ipcMain.emit("removedmod", "", { + name: mod.replace(/^.*(\\|\/|\:)/, ""), + manifestname: manifestname + }); } else { cli.exit(1); } @@ -621,6 +717,10 @@ const mods = { } }; +setInterval(() => { + ipcMain.emit("guigetmods"); +}, 1500) + module.exports = { mods, lang, |