mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-09 17:23:53 +01:00
Merge pull request #2044 from Rez855/feature/multi-tab-script-editor
Script Editor Refactor
This commit is contained in:
commit
53ce11c33a
207
package-lock.json
generated
207
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "SEE LICENSE IN license.txt",
|
"license": "SEE LICENSE IN license.txt",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -22,6 +22,7 @@
|
|||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
"@types/react": "^17.0.21",
|
"@types/react": "^17.0.21",
|
||||||
|
"@types/react-beautiful-dnd": "^13.1.2",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
"@types/react-resizable": "^1.7.3",
|
"@types/react-resizable": "^1.7.3",
|
||||||
"acorn": "^8.4.1",
|
"acorn": "^8.4.1",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-beautiful-dnd": "^13.1.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.4",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.4",
|
||||||
@ -3984,6 +3986,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
||||||
@ -4062,6 +4073,14 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-beautiful-dnd": {
|
||||||
|
"version": "13.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz",
|
||||||
|
"integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "17.0.9",
|
"version": "17.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
||||||
@ -4078,6 +4097,17 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-redux": {
|
||||||
|
"version": "7.1.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz",
|
||||||
|
"integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.0",
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
|
"redux": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-resizable": {
|
"node_modules/@types/react-resizable": {
|
||||||
"version": "1.7.4",
|
"version": "1.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz",
|
||||||
@ -6659,6 +6689,14 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-box-model": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tiny-invariant": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/css-select": {
|
"node_modules/css-select": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
||||||
@ -14566,6 +14604,11 @@
|
|||||||
"node": ">= 4.0.0"
|
"node": ">= 4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/memoize-one": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
|
},
|
||||||
"node_modules/memory-fs": {
|
"node_modules/memory-fs": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||||
@ -16303,6 +16346,11 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/raf-schd": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
|
||||||
|
},
|
||||||
"node_modules/ramda": {
|
"node_modules/ramda": {
|
||||||
"version": "0.27.1",
|
"version": "0.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
||||||
@ -16429,6 +16477,24 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-beautiful-dnd": {
|
||||||
|
"version": "13.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
|
||||||
|
"integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.9.2",
|
||||||
|
"css-box-model": "^1.2.0",
|
||||||
|
"memoize-one": "^5.1.1",
|
||||||
|
"raf-schd": "^4.0.2",
|
||||||
|
"react-redux": "^7.2.0",
|
||||||
|
"redux": "^4.0.4",
|
||||||
|
"use-memo-one": "^1.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.5 || ^17.0.0",
|
||||||
|
"react-dom": "^16.8.5 || ^17.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"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",
|
||||||
@ -16460,6 +16526,30 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-redux": {
|
||||||
|
"version": "7.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
|
||||||
|
"integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.15.4",
|
||||||
|
"@types/react-redux": "^7.1.20",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-is": "^17.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.3 || ^17"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.10.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
|
||||||
@ -16625,6 +16715,14 @@
|
|||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redux": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regenerate": {
|
"node_modules/regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@ -19143,6 +19241,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-invariant": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg=="
|
||||||
|
},
|
||||||
"node_modules/tiny-warning": {
|
"node_modules/tiny-warning": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||||
@ -19717,6 +19820,14 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-memo-one": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util": {
|
"node_modules/util": {
|
||||||
"version": "0.11.1",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||||
@ -24597,6 +24708,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/istanbul-lib-coverage": {
|
"@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
||||||
@ -24675,6 +24795,14 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-beautiful-dnd": {
|
||||||
|
"version": "13.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz",
|
||||||
|
"integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-dom": {
|
"@types/react-dom": {
|
||||||
"version": "17.0.9",
|
"version": "17.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
||||||
@ -24691,6 +24819,17 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-redux": {
|
||||||
|
"version": "7.1.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz",
|
||||||
|
"integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.0",
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
|
"redux": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-resizable": {
|
"@types/react-resizable": {
|
||||||
"version": "1.7.4",
|
"version": "1.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz",
|
||||||
@ -26762,6 +26901,14 @@
|
|||||||
"randomfill": "^1.0.3"
|
"randomfill": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"css-box-model": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
||||||
|
"requires": {
|
||||||
|
"tiny-invariant": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"css-select": {
|
"css-select": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
||||||
@ -32913,6 +33060,11 @@
|
|||||||
"fs-monkey": "1.0.3"
|
"fs-monkey": "1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"memoize-one": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
|
},
|
||||||
"memory-fs": {
|
"memory-fs": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||||
@ -34288,6 +34440,11 @@
|
|||||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"raf-schd": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
|
||||||
|
},
|
||||||
"ramda": {
|
"ramda": {
|
||||||
"version": "0.27.1",
|
"version": "0.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
||||||
@ -34384,6 +34541,20 @@
|
|||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-beautiful-dnd": {
|
||||||
|
"version": "13.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
|
||||||
|
"integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.9.2",
|
||||||
|
"css-box-model": "^1.2.0",
|
||||||
|
"memoize-one": "^5.1.1",
|
||||||
|
"raf-schd": "^4.0.2",
|
||||||
|
"react-redux": "^7.2.0",
|
||||||
|
"redux": "^4.0.4",
|
||||||
|
"use-memo-one": "^1.1.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",
|
||||||
@ -34408,6 +34579,19 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
},
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"version": "7.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
|
||||||
|
"integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.15.4",
|
||||||
|
"@types/react-redux": "^7.1.20",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-is": "^17.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-refresh": {
|
"react-refresh": {
|
||||||
"version": "0.10.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
|
||||||
@ -34537,6 +34721,14 @@
|
|||||||
"picomatch": "^2.2.1"
|
"picomatch": "^2.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redux": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@ -36569,6 +36761,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||||
},
|
},
|
||||||
|
"tiny-invariant": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg=="
|
||||||
|
},
|
||||||
"tiny-warning": {
|
"tiny-warning": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||||
@ -37025,6 +37222,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
||||||
},
|
},
|
||||||
|
"use-memo-one": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.11.1",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
"@types/react": "^17.0.21",
|
"@types/react": "^17.0.21",
|
||||||
|
"@types/react-beautiful-dnd": "^13.1.2",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
"@types/react-resizable": "^1.7.3",
|
"@types/react-resizable": "^1.7.3",
|
||||||
"acorn": "^8.4.1",
|
"acorn": "^8.4.1",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-beautiful-dnd": "^13.1.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.4",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.4",
|
||||||
|
@ -15,7 +15,7 @@ import { TextFile } from "../../TextFile";
|
|||||||
import { calculateRamUsage, checkInfiniteLoop } from "../../Script/RamCalculations";
|
import { calculateRamUsage, checkInfiniteLoop } from "../../Script/RamCalculations";
|
||||||
import { RamCalculationErrorCode } from "../../Script/RamCalculationErrorCodes";
|
import { RamCalculationErrorCode } from "../../Script/RamCalculationErrorCodes";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { CursorPositions } from "../CursorPositions";
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
import { NetscriptFunctions } from "../../NetscriptFunctions";
|
import { NetscriptFunctions } from "../../NetscriptFunctions";
|
||||||
import { WorkerScript } from "../../Netscript/WorkerScript";
|
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||||
@ -27,20 +27,31 @@ import { loadThemes } from "./themes";
|
|||||||
import { GetServer } from "../../Server/AllServers";
|
import { GetServer } from "../../Server/AllServers";
|
||||||
|
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Link from "@mui/material/Link";
|
import Link from "@mui/material/Link";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import SettingsIcon from "@mui/icons-material/Settings";
|
import SettingsIcon from "@mui/icons-material/Settings";
|
||||||
|
import { PromptEvent } from "../../ui/React/PromptManager";
|
||||||
|
|
||||||
import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts";
|
import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts";
|
||||||
|
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
filename: string;
|
||||||
|
code: string;
|
||||||
|
hostname: string;
|
||||||
|
player: IPlayer;
|
||||||
|
router: IRouter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: try to removve global symbols
|
||||||
let symbolsLoaded = false;
|
let symbolsLoaded = false;
|
||||||
let symbols: string[] = [];
|
let symbols: string[] = [];
|
||||||
export function SetupTextEditor(): void {
|
export function SetupTextEditor(): void {
|
||||||
const ns = NetscriptFunctions({} as WorkerScript);
|
const ns = NetscriptFunctions({} as WorkerScript);
|
||||||
|
|
||||||
|
// Populates symbols for text editor
|
||||||
function populate(ns: any): string[] {
|
function populate(ns: any): string[] {
|
||||||
let symbols: string[] = [];
|
let symbols: string[] = [];
|
||||||
const keys = Object.keys(ns);
|
const keys = Object.keys(ns);
|
||||||
@ -53,36 +64,19 @@ export function SetupTextEditor(): void {
|
|||||||
symbols.push(key);
|
symbols.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return symbols;
|
return symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
symbols = populate(ns);
|
symbols = populate(ns);
|
||||||
|
|
||||||
const exclude = ["heart", "break", "exploit", "bypass", "corporation", "alterReality"];
|
const exclude = ["heart", "break", "exploit", "bypass", "corporation", "alterReality"];
|
||||||
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol)).sort();
|
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol)).sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
filename: string;
|
|
||||||
code: string;
|
|
||||||
hostname: string;
|
|
||||||
player: IPlayer;
|
|
||||||
router: IRouter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// How to load function definition in monaco
|
|
||||||
// https://github.com/Microsoft/monaco-editor/issues/1415
|
|
||||||
// https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html
|
|
||||||
// https://www.npmjs.com/package/@monaco-editor/react#development-playground
|
|
||||||
// https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
|
||||||
// https://github.com/threehams/typescript-error-guide/blob/master/stories/components/Editor.tsx#L11-L39
|
|
||||||
// https://blog.checklyhq.com/customizing-monaco/
|
|
||||||
|
|
||||||
// Holds all the data for a open script
|
// Holds all the data for a open script
|
||||||
class openScript {
|
class OpenScript {
|
||||||
fileName: string;
|
fileName: string;
|
||||||
code: string;
|
code: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
@ -98,17 +92,23 @@ class openScript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const openScripts = new Array<openScript>(); // Holds all open scripts
|
// Called every time script editor is opened
|
||||||
let currentScript = {} as openScript; // Script currently being viewed
|
|
||||||
|
|
||||||
export function Root(props: IProps): React.ReactElement {
|
export function Root(props: IProps): React.ReactElement {
|
||||||
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
||||||
const monacoRef = useRef<Monaco | null>(null);
|
const monacoRef = useRef<Monaco | null>(null);
|
||||||
const [filename] = useState(props.filename);
|
|
||||||
const [code] = useState<string>(props.code);
|
const [openScripts, setOpenScripts] = useState<OpenScript[]>(
|
||||||
const [decorations, setDecorations] = useState<string[]>([]);
|
window.localStorage.getItem('scriptEditorOpenScripts') !== null ? JSON.parse(window.localStorage.getItem('scriptEditorOpenScripts')!) : []
|
||||||
|
);
|
||||||
|
|
||||||
|
const [currentScript, setCurrentScript] = useState<OpenScript | null>(
|
||||||
|
window.localStorage.getItem('scriptEditorCurrentScript') !== null ? JSON.parse(window.localStorage.getItem('scriptEditorCurrentScript')!) : null
|
||||||
|
);
|
||||||
|
|
||||||
const [ram, setRAM] = useState("RAM: ???");
|
const [ram, setRAM] = useState("RAM: ???");
|
||||||
const [updatingRam, setUpdatingRam] = useState(false);
|
const [updatingRam, setUpdatingRam] = useState(false);
|
||||||
|
const [decorations, setDecorations] = useState<string[]>([]);
|
||||||
|
|
||||||
const [optionsOpen, setOptionsOpen] = useState(false);
|
const [optionsOpen, setOptionsOpen] = useState(false);
|
||||||
const [options, setOptions] = useState<Options>({
|
const [options, setOptions] = useState<Options>({
|
||||||
theme: Settings.MonacoTheme,
|
theme: Settings.MonacoTheme,
|
||||||
@ -116,6 +116,53 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
fontSize: Settings.MonacoFontSize,
|
fontSize: Settings.MonacoFontSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Save currentScript
|
||||||
|
window.localStorage.setItem('scriptEditorCurrentScript', JSON.stringify(currentScript, (key, value) => {
|
||||||
|
if (key == 'model') return undefined;
|
||||||
|
return value;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Save openScripts
|
||||||
|
window.localStorage.setItem('scriptEditorOpenScripts', JSON.stringify(openScripts, (key, value) => {
|
||||||
|
if (key == 'model') return undefined;
|
||||||
|
return value;
|
||||||
|
}))
|
||||||
|
}, [currentScript, openScripts])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentScript !== null) {
|
||||||
|
updateRAM(currentScript.code);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function maybeSave(event: KeyboardEvent): void {
|
||||||
|
if (Settings.DisableHotkeys) return;
|
||||||
|
//Ctrl + b
|
||||||
|
if (event.keyCode == 66 && (event.ctrlKey || event.metaKey)) {
|
||||||
|
event.preventDefault();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CTRL/CMD + S
|
||||||
|
if (event.code == `KeyS` && (event.ctrlKey || event.metaKey)) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener("keydown", maybeSave);
|
||||||
|
return () => document.removeEventListener("keydown", maybeSave);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Generates a new model for the script
|
||||||
|
function regenerateModel(script: OpenScript): void {
|
||||||
|
if (monacoRef.current !== null) {
|
||||||
|
script.model = monacoRef.current.editor.createModel(script.code, "javascript");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const debouncedSetRAM = useMemo(
|
const debouncedSetRAM = useMemo(
|
||||||
() =>
|
() =>
|
||||||
debounce((s) => {
|
debounce((s) => {
|
||||||
@ -125,7 +172,225 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function updateRAM(newCode: string): Promise<void> {
|
||||||
|
setUpdatingRam(true);
|
||||||
|
const codeCopy = newCode + "";
|
||||||
|
const ramUsage = await calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts);
|
||||||
|
if (ramUsage > 0) {
|
||||||
|
debouncedSetRAM("RAM: " + numeralWrapper.formatRAM(ramUsage));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (ramUsage) {
|
||||||
|
case RamCalculationErrorCode.ImportError: {
|
||||||
|
debouncedSetRAM("RAM: Import Error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RamCalculationErrorCode.URLImportError: {
|
||||||
|
debouncedSetRAM("RAM: HTTP Import Error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RamCalculationErrorCode.SyntaxError:
|
||||||
|
default: {
|
||||||
|
debouncedSetRAM("RAM: Syntax Error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Promise<void>(() => undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats the code
|
||||||
|
function beautify(): void {
|
||||||
|
if (editorRef.current === null) return;
|
||||||
|
editorRef.current.getAction("editor.action.formatDocument").run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// How to load function definition in monaco
|
||||||
|
// https://github.com/Microsoft/monaco-editor/issues/1415
|
||||||
|
// https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html
|
||||||
|
// https://www.npmjs.com/package/@monaco-editor/react#development-playground
|
||||||
|
// https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
||||||
|
// https://github.com/threehams/typescript-error-guide/blob/master/stories/components/Editor.tsx#L11-L39
|
||||||
|
// https://blog.checklyhq.com/customizing-monaco/
|
||||||
|
// Before the editor is mounted
|
||||||
|
function beforeMount(monaco: any): void {
|
||||||
|
if (symbolsLoaded) return;
|
||||||
|
// Setup monaco auto completion
|
||||||
|
symbolsLoaded = true;
|
||||||
|
monaco.languages.registerCompletionItemProvider("javascript", {
|
||||||
|
provideCompletionItems: () => {
|
||||||
|
const suggestions = [];
|
||||||
|
for (const symbol of symbols) {
|
||||||
|
suggestions.push({
|
||||||
|
label: symbol,
|
||||||
|
kind: monaco.languages.CompletionItemKind.Function,
|
||||||
|
insertText: symbol,
|
||||||
|
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { suggestions: suggestions };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
// We have to improve the default js language otherwise theme sucks
|
||||||
|
const l = await monaco.languages
|
||||||
|
.getLanguages()
|
||||||
|
.find((l: any) => l.id === "javascript")
|
||||||
|
.loader();
|
||||||
|
l.language.tokenizer.root.unshift(["ns", { token: "ns" }]);
|
||||||
|
for (const symbol of symbols) l.language.tokenizer.root.unshift([symbol, { token: "netscriptfunction" }]);
|
||||||
|
const otherKeywords = ["let", "const", "var", "function"];
|
||||||
|
const otherKeyvars = ["true", "false", "null", "undefined"];
|
||||||
|
otherKeywords.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeywords" }]));
|
||||||
|
otherKeyvars.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeyvars" }]));
|
||||||
|
l.language.tokenizer.root.unshift(["this", { token: "this" }]);
|
||||||
|
})();
|
||||||
|
|
||||||
|
const source = (libSource + "").replace(/export /g, "");
|
||||||
|
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
|
||||||
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
|
||||||
|
loadThemes(monaco);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// When the editor is mounted
|
||||||
|
function onMount(editor: IStandaloneCodeEditor, monaco: Monaco) {
|
||||||
|
editorRef.current = editor;
|
||||||
|
monacoRef.current = monaco;
|
||||||
|
|
||||||
|
if (editorRef.current === null || monacoRef.current === null) return;
|
||||||
|
|
||||||
|
if (props.filename) {
|
||||||
|
// Check if file is already opened
|
||||||
|
let openScriptIndex = openScripts.findIndex(script => script.fileName === props.filename && script.hostname === props.hostname);
|
||||||
|
if (openScriptIndex !== -1) {
|
||||||
|
// Script is already opened
|
||||||
|
if (openScripts[openScriptIndex].model === undefined || openScripts[openScriptIndex].model === null || openScripts[openScriptIndex].model.isDisposed()) {
|
||||||
|
regenerateModel(openScripts[openScriptIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentScript(openScripts[openScriptIndex]);
|
||||||
|
editorRef.current.setModel(openScripts[openScriptIndex].model);
|
||||||
|
editorRef.current.setPosition(openScripts[openScriptIndex].lastPosition);
|
||||||
|
editorRef.current.revealLineInCenter(openScripts[openScriptIndex].lastPosition.lineNumber);
|
||||||
|
updateRAM(openScripts[openScriptIndex].code);
|
||||||
|
} else {
|
||||||
|
// Open script
|
||||||
|
var newScript = new OpenScript(props.filename, props.code, props.hostname, new monacoRef.current.Position(0, 0), monacoRef.current.editor.createModel(props.code, 'javascript'));
|
||||||
|
setOpenScripts(oldArray => [...oldArray, newScript]);
|
||||||
|
setCurrentScript({ ...newScript });
|
||||||
|
editorRef.current.setModel(newScript.model);
|
||||||
|
updateRAM(newScript.code);
|
||||||
|
}
|
||||||
|
} else if (currentScript !== null) {
|
||||||
|
// Open currentscript
|
||||||
|
regenerateModel(currentScript);
|
||||||
|
editorRef.current.setModel(currentScript.model);
|
||||||
|
editorRef.current.setPosition(currentScript.lastPosition);
|
||||||
|
editorRef.current.revealLineInCenter(currentScript.lastPosition.lineNumber);
|
||||||
|
updateRAM(currentScript.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function infLoop(newCode: string): void {
|
||||||
|
if (editorRef.current === null || currentScript === null) return;
|
||||||
|
if (!currentScript.fileName.endsWith(".ns") && !currentScript.fileName.endsWith(".js")) return;
|
||||||
|
const awaitWarning = checkInfiniteLoop(newCode);
|
||||||
|
if (awaitWarning !== -1) {
|
||||||
|
const newDecorations = editorRef.current.deltaDecorations(decorations, [
|
||||||
|
{
|
||||||
|
range: {
|
||||||
|
startLineNumber: awaitWarning,
|
||||||
|
startColumn: 1,
|
||||||
|
endLineNumber: awaitWarning,
|
||||||
|
endColumn: 10,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
isWholeLine: true,
|
||||||
|
glyphMarginClassName: "myGlyphMarginClass",
|
||||||
|
glyphMarginHoverMessage: {
|
||||||
|
value: "Possible infinite loop, await something.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
setDecorations(newDecorations);
|
||||||
|
} else {
|
||||||
|
const newDecorations = editorRef.current.deltaDecorations(decorations, []);
|
||||||
|
setDecorations(newDecorations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the code is updated within the editor
|
||||||
|
function updateCode(newCode?: string) {
|
||||||
|
if (newCode === undefined) return;
|
||||||
|
updateRAM(newCode);
|
||||||
|
if (editorRef.current !== null) {
|
||||||
|
var newPos = editorRef.current.getPosition();
|
||||||
|
if (newPos === null) return;
|
||||||
|
setCurrentScript(oldScript => ({ ...oldScript!, code: newCode, lastPosition: newPos! }))
|
||||||
|
if (currentScript !== null) {
|
||||||
|
let curIndex = openScripts.findIndex(script => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname);
|
||||||
|
let newArr = [...openScripts];
|
||||||
|
let tempScript = currentScript;
|
||||||
|
tempScript.code = newCode;
|
||||||
|
newArr[curIndex] = tempScript;
|
||||||
|
setOpenScripts([...newArr]);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
infLoop(newCode);
|
||||||
|
} catch (err) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveScript(scriptToSave: OpenScript): void {
|
||||||
|
const server = GetServer(scriptToSave.hostname);
|
||||||
|
if (server === null) throw new Error("Server should not be null but it is.");
|
||||||
|
if (isScriptFilename(scriptToSave.fileName)) {
|
||||||
|
//If the current script already exists on the server, overwrite it
|
||||||
|
for (let i = 0; i < server.scripts.length; i++) {
|
||||||
|
if (scriptToSave.fileName == server.scripts[i].filename) {
|
||||||
|
server.scripts[i].saveScript(
|
||||||
|
scriptToSave.fileName,
|
||||||
|
scriptToSave.code,
|
||||||
|
props.player.currentServer,
|
||||||
|
server.scripts,
|
||||||
|
);
|
||||||
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
props.router.toTerminal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the current script does NOT exist, create a new one
|
||||||
|
const script = new Script();
|
||||||
|
script.saveScript(scriptToSave.fileName, scriptToSave.code, props.player.currentServer, server.scripts);
|
||||||
|
server.scripts.push(script);
|
||||||
|
} else if (scriptToSave.fileName.endsWith(".txt")) {
|
||||||
|
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||||
|
if (server.textFiles[i].fn === scriptToSave.fileName) {
|
||||||
|
server.textFiles[i].write(scriptToSave.code);
|
||||||
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
props.router.toTerminal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const textFile = new TextFile(scriptToSave.fileName, scriptToSave.code);
|
||||||
|
server.textFiles.push(textFile);
|
||||||
|
} else {
|
||||||
|
dialogBoxCreate("Invalid filename. Must be either a script (.script, .js, or .ns) or " + " or text file (.txt)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
props.router.toTerminal();
|
||||||
|
}
|
||||||
|
|
||||||
function save(): void {
|
function save(): void {
|
||||||
|
if (currentScript === null) {
|
||||||
|
console.log("currentScript is null when it shouldn't be. Unabel to save script");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// this is duplicate code with saving later.
|
// this is duplicate code with saving later.
|
||||||
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
||||||
//Make sure filename + code properly follow tutorial
|
//Make sure filename + code properly follow tutorial
|
||||||
@ -172,6 +437,7 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
server.scripts,
|
server.scripts,
|
||||||
);
|
);
|
||||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
props.router.toTerminal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,6 +451,7 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
if (server.textFiles[i].fn === currentScript.fileName) {
|
if (server.textFiles[i].fn === currentScript.fileName) {
|
||||||
server.textFiles[i].write(currentScript.code);
|
server.textFiles[i].write(currentScript.code);
|
||||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
props.router.toTerminal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,407 +463,97 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
props.router.toTerminal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function beautify(): void {
|
function reorder(list: Array<OpenScript>, startIndex: number, endIndex: number) {
|
||||||
if (editorRef.current === null) return;
|
const result = Array.from(list);
|
||||||
editorRef.current.getAction("editor.action.formatDocument").run();
|
const [removed] = result.splice(startIndex, 1);
|
||||||
|
result.splice(endIndex, 0, removed);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function infLoop(newCode: string): void {
|
function onDragEnd(result: any) {
|
||||||
if (editorRef.current === null) return;
|
// Dropped outside of the list
|
||||||
if (!currentScript.fileName.endsWith(".ns") && !currentScript.fileName.endsWith(".js")) return;
|
if (!result.destination) {
|
||||||
const awaitWarning = checkInfiniteLoop(newCode);
|
result
|
||||||
if (awaitWarning !== -1) {
|
|
||||||
const newDecorations = editorRef.current.deltaDecorations(decorations, [
|
|
||||||
{
|
|
||||||
range: {
|
|
||||||
startLineNumber: awaitWarning,
|
|
||||||
startColumn: 1,
|
|
||||||
endLineNumber: awaitWarning,
|
|
||||||
endColumn: 10,
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
isWholeLine: true,
|
|
||||||
glyphMarginClassName: "myGlyphMarginClass",
|
|
||||||
glyphMarginHoverMessage: {
|
|
||||||
value: "Possible infinite loop, await something.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
setDecorations(newDecorations);
|
|
||||||
} else {
|
|
||||||
const newDecorations = editorRef.current.deltaDecorations(decorations, []);
|
|
||||||
setDecorations(newDecorations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateCode(newCode?: string): void {
|
|
||||||
if (newCode === undefined) return;
|
|
||||||
updateRAM(newCode);
|
|
||||||
currentScript.code = newCode;
|
|
||||||
try {
|
|
||||||
if (editorRef.current !== null) {
|
|
||||||
infLoop(newCode);
|
|
||||||
}
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate it once the first time the file is loaded.
|
|
||||||
useEffect(() => {
|
|
||||||
updateRAM(currentScript.code);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
async function updateRAM(newCode: string): Promise<void> {
|
|
||||||
setUpdatingRam(true);
|
|
||||||
const codeCopy = newCode + "";
|
|
||||||
const ramUsage = await calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts);
|
|
||||||
if (ramUsage > 0) {
|
|
||||||
debouncedSetRAM("RAM: " + numeralWrapper.formatRAM(ramUsage));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (ramUsage) {
|
|
||||||
case RamCalculationErrorCode.ImportError: {
|
const items = reorder(openScripts, result.source.index, result.destination.index);
|
||||||
debouncedSetRAM("RAM: Import Error");
|
|
||||||
break;
|
setOpenScripts(items);
|
||||||
}
|
|
||||||
case RamCalculationErrorCode.URLImportError: {
|
|
||||||
debouncedSetRAM("RAM: HTTP Import Error");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case RamCalculationErrorCode.SyntaxError:
|
|
||||||
default: {
|
|
||||||
debouncedSetRAM("RAM: Syntax Error");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Promise<void>(() => undefined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
function onTabClick(index: number) {
|
||||||
function maybeSave(event: KeyboardEvent): void {
|
|
||||||
if (Settings.DisableHotkeys) return;
|
|
||||||
|
|
||||||
// CTRL/CMD + S
|
|
||||||
if (event.code == `KeyS` && (event.ctrlKey || event.metaKey)) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener("keydown", maybeSave);
|
|
||||||
return () => document.removeEventListener("keydown", maybeSave);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generates a new model for the script
|
|
||||||
function regenerateModel(script: openScript): void {
|
|
||||||
if (monacoRef.current !== null) {
|
|
||||||
script.model = monacoRef.current.editor.createModel(script.code, "javascript");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the currently viewed script
|
|
||||||
function setCurrentScript(script: openScript): void {
|
|
||||||
// Update last position
|
|
||||||
if (editorRef.current !== null) {
|
|
||||||
if (currentScript !== null) {
|
if (currentScript !== null) {
|
||||||
const currentPosition = editorRef.current.getPosition();
|
// Save currentScript to openScripts
|
||||||
if (currentPosition !== null) {
|
let curIndex = openScripts.findIndex(script => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname);
|
||||||
currentScript.lastPosition = currentPosition;
|
openScripts[curIndex] = currentScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentScript({ ...openScripts[index] });
|
||||||
|
|
||||||
|
if (editorRef.current !== null && openScripts[index] !== null) {
|
||||||
|
if (openScripts[index].model === undefined || openScripts[index].model.isDisposed()) {
|
||||||
|
regenerateModel(openScripts[index]);
|
||||||
|
}
|
||||||
|
editorRef.current.setModel(openScripts[index].model);
|
||||||
|
|
||||||
|
editorRef.current.setPosition(openScripts[index].lastPosition);
|
||||||
|
editorRef.current.revealLineInCenter(openScripts[index].lastPosition.lineNumber);
|
||||||
|
updateRAM(openScripts[index].code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editorRef.current.setModel(script.model);
|
async function onTabClose(index: number) {
|
||||||
currentScript = script;
|
// See if the script on the server is up to date
|
||||||
editorRef.current.setPosition(currentScript.lastPosition);
|
let closingScript = openScripts[index];
|
||||||
editorRef.current.revealLine(currentScript.lastPosition.lineNumber);
|
let savedOpenScripts: Array<OpenScript> = JSON.parse(window.localStorage.getItem('scriptEditorOpenScripts')!);
|
||||||
updateRAM(currentScript.code);
|
let savedScriptIndex = savedOpenScripts.findIndex(script => script.fileName === closingScript.fileName && script.hostname === closingScript.hostname);
|
||||||
}
|
let savedScriptCode = '';
|
||||||
|
if (savedScriptIndex !== -1) {
|
||||||
|
savedScriptCode = savedOpenScripts[savedScriptIndex].code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a currently opened script
|
let serverScriptIndex = GetServer(closingScript.hostname)?.scripts.findIndex(script => script.filename === closingScript.fileName);
|
||||||
function getOpenedScript(fileName: string, hostname: string): openScript | null {
|
if (serverScriptIndex === -1 || savedScriptCode !== GetServer(closingScript.hostname)?.scripts[serverScriptIndex as number].code) {
|
||||||
for (const script of openScripts) {
|
PromptEvent.emit({
|
||||||
if (script.fileName === fileName && script.hostname === hostname) {
|
txt: 'Do you want to save changes to ' + closingScript.fileName + '?',
|
||||||
return script;
|
resolve: (result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
// Save changes
|
||||||
|
closingScript.code = savedScriptCode;
|
||||||
|
saveScript(closingScript);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
if (openScripts.length > 1) {
|
||||||
|
setOpenScripts(oldScripts => oldScripts.filter((value, i) => i !== index));
|
||||||
|
|
||||||
|
let indexOffset = -1;
|
||||||
|
if (openScripts[index + indexOffset] === undefined) {
|
||||||
|
indexOffset = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveScript(script: openScript): void {
|
// Change current script if we closed it
|
||||||
const server = GetServer(script.hostname);
|
setCurrentScript(openScripts[index + indexOffset]);
|
||||||
if (server === null) throw new Error("Server should not be null but it is.");
|
if (editorRef.current !== null) {
|
||||||
let found = false;
|
if (openScripts[index + indexOffset].model === undefined || openScripts[index + indexOffset].model === null || openScripts[index + indexOffset].model.isDisposed()) {
|
||||||
for (let i = 0; i < server.scripts.length; i++) {
|
regenerateModel(openScripts[index + indexOffset]);
|
||||||
if (script.fileName == server.scripts[i].filename) {
|
|
||||||
server.scripts[i].saveScript(script.fileName, script.code, script.hostname, server.scripts);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
editorRef.current.setModel(openScripts[index + indexOffset].model);
|
||||||
const newScript = new Script();
|
editorRef.current.setPosition(openScripts[index + indexOffset].lastPosition);
|
||||||
newScript.saveScript(script.fileName, script.code, script.hostname, server.scripts);
|
editorRef.current.revealLineInCenter(openScripts[index + indexOffset].lastPosition.lineNumber)
|
||||||
server.scripts.push(newScript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMount(editor: IStandaloneCodeEditor, monaco: Monaco): void {
|
|
||||||
editorRef.current = editor;
|
|
||||||
monacoRef.current = monaco;
|
|
||||||
if (editorRef.current === null) return;
|
|
||||||
const position = CursorPositions.getCursor(filename);
|
|
||||||
if (position.row !== -1)
|
|
||||||
editorRef.current.setPosition({
|
|
||||||
lineNumber: position.row,
|
|
||||||
column: position.column,
|
|
||||||
});
|
|
||||||
editorRef.current.focus();
|
|
||||||
|
|
||||||
const script = getOpenedScript(filename, props.player.getCurrentServer().hostname);
|
|
||||||
|
|
||||||
// Check if script is already opened, if so switch to that model
|
|
||||||
if (script !== null) {
|
|
||||||
if (script.model.isDisposed()) {
|
|
||||||
regenerateModel(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentScript(script);
|
|
||||||
} else {
|
|
||||||
if (filename !== undefined) {
|
|
||||||
// Create new model
|
|
||||||
if (monacoRef.current !== null) {
|
|
||||||
const newScript = new openScript(
|
|
||||||
filename,
|
|
||||||
code,
|
|
||||||
props.player.getCurrentServer().hostname,
|
|
||||||
new monaco.Position(0, 0),
|
|
||||||
monacoRef.current.editor.createModel(code, "javascript"),
|
|
||||||
);
|
|
||||||
setCurrentScript(newScript);
|
|
||||||
openScripts.push(newScript);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Script Editor was opened by the sidebar button
|
// No more scripts are open
|
||||||
if (currentScript.model !== undefined) {
|
setOpenScripts([]);
|
||||||
if (currentScript.model.isDisposed()) {
|
setCurrentScript(null);
|
||||||
// Create new model, old one was disposed of
|
|
||||||
regenerateModel(currentScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentScript(currentScript);
|
|
||||||
} else {
|
|
||||||
// Create a new temporary file
|
|
||||||
if (monacoRef.current !== null) {
|
|
||||||
const newScript = new openScript(
|
|
||||||
"newfile.script",
|
|
||||||
"",
|
|
||||||
props.player.getCurrentServer().hostname,
|
|
||||||
new monaco.Position(0, 0),
|
|
||||||
monacoRef.current.editor.createModel("", "javascript"),
|
|
||||||
);
|
|
||||||
setCurrentScript(newScript);
|
|
||||||
openScripts.push(newScript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function beforeMount(monaco: any): void {
|
|
||||||
if (symbolsLoaded) return;
|
|
||||||
symbolsLoaded = true;
|
|
||||||
monaco.languages.registerCompletionItemProvider("javascript", {
|
|
||||||
provideCompletionItems: () => {
|
|
||||||
const suggestions = [];
|
|
||||||
for (const symbol of symbols) {
|
|
||||||
suggestions.push({
|
|
||||||
label: symbol,
|
|
||||||
kind: monaco.languages.CompletionItemKind.Function,
|
|
||||||
insertText: symbol,
|
|
||||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return { suggestions: suggestions };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
(async function () {
|
|
||||||
// We have to improve the default js language otherwise theme sucks
|
|
||||||
const l = await monaco.languages
|
|
||||||
.getLanguages()
|
|
||||||
.find((l: any) => l.id === "javascript")
|
|
||||||
.loader();
|
|
||||||
l.language.tokenizer.root.unshift(["ns", { token: "ns" }]);
|
|
||||||
for (const symbol of symbols) l.language.tokenizer.root.unshift([symbol, { token: "netscriptfunction" }]);
|
|
||||||
const otherKeywords = ["let", "const", "var", "function"];
|
|
||||||
const otherKeyvars = ["true", "false", "null", "undefined"];
|
|
||||||
otherKeywords.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeywords" }]));
|
|
||||||
otherKeyvars.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeyvars" }]));
|
|
||||||
l.language.tokenizer.root.unshift(["this", { token: "this" }]);
|
|
||||||
})();
|
|
||||||
|
|
||||||
const source = (libSource + "").replace(/export /g, "");
|
|
||||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
|
|
||||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
|
|
||||||
loadThemes(monaco);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change tab highlight from old tab to new tab
|
|
||||||
function changeTabButtonColor(
|
|
||||||
oldButtonFileName: string,
|
|
||||||
oldButtonHostname: string,
|
|
||||||
newButtonFileName: string,
|
|
||||||
newButtonHostname: string,
|
|
||||||
): void {
|
|
||||||
const oldTabButton = document.getElementById("tabButton" + oldButtonFileName + oldButtonHostname);
|
|
||||||
if (oldTabButton !== null) {
|
|
||||||
oldTabButton.style.backgroundColor = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldTabCloseButton = document.getElementById("tabCloseButton" + oldButtonFileName + oldButtonHostname);
|
|
||||||
if (oldTabCloseButton !== null) {
|
|
||||||
oldTabCloseButton.style.backgroundColor = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const newTabButton = document.getElementById("tabButton" + newButtonFileName + newButtonHostname);
|
|
||||||
if (newTabButton !== null) {
|
|
||||||
newTabButton.style.backgroundColor = "#666";
|
|
||||||
}
|
|
||||||
|
|
||||||
const newTabCloseButton = document.getElementById("tabCloseButton" + newButtonFileName + newButtonHostname);
|
|
||||||
if (newTabCloseButton !== null) {
|
|
||||||
newTabCloseButton.style.backgroundColor = "#666";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when a script tab was clicked
|
|
||||||
function onTabButtonClick(e: React.MouseEvent<HTMLButtonElement>): void {
|
|
||||||
const valSplit = e.currentTarget.value.split(":");
|
|
||||||
const fileName = valSplit[0];
|
|
||||||
const hostname = valSplit[1];
|
|
||||||
|
|
||||||
// Change tab highlight from old tab to new tab
|
|
||||||
changeTabButtonColor(currentScript.fileName, currentScript.hostname, fileName, hostname);
|
|
||||||
|
|
||||||
// Update current script
|
|
||||||
const clickedScript = getOpenedScript(fileName, hostname);
|
|
||||||
|
|
||||||
if (clickedScript !== null) {
|
|
||||||
if (clickedScript.model.isDisposed()) {
|
|
||||||
regenerateModel(clickedScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentScript(clickedScript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when a script tab close button was clicked
|
|
||||||
function onCloseButtonClick(e: React.MouseEvent<HTMLButtonElement>): void {
|
|
||||||
const valSplit = e.currentTarget.value.split(":");
|
|
||||||
const fileName = valSplit[0];
|
|
||||||
const hostname = valSplit[1];
|
|
||||||
|
|
||||||
const scriptToClose = getOpenedScript(fileName, hostname);
|
|
||||||
|
|
||||||
// Save and remove script from openScripts
|
|
||||||
if (scriptToClose !== null) {
|
|
||||||
saveScript(scriptToClose);
|
|
||||||
|
|
||||||
openScripts.splice(openScripts.indexOf(scriptToClose), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (openScripts.length === 0) {
|
|
||||||
// No other scripts are open, create a new temporary file
|
|
||||||
if (monacoRef.current !== null) {
|
|
||||||
const newScript = new openScript(
|
|
||||||
"newfile.script",
|
|
||||||
"",
|
|
||||||
props.player.getCurrentServer().hostname,
|
|
||||||
new monacoRef.current.Position(0, 0),
|
|
||||||
monacoRef.current.editor.createModel("", "javascript"),
|
|
||||||
);
|
|
||||||
|
|
||||||
setCurrentScript(newScript);
|
|
||||||
openScripts.push(newScript);
|
|
||||||
|
|
||||||
// Modify button for temp file
|
|
||||||
const parent = e.currentTarget.parentElement;
|
|
||||||
if (parent !== null) {
|
|
||||||
(parent.children[0] as HTMLButtonElement).value = "newfile.script:home";
|
|
||||||
(parent.children[0] as HTMLButtonElement).textContent = "newfile.script";
|
|
||||||
e.currentTarget.value = "newfile.script:home";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (openScripts[0].model.isDisposed()) {
|
|
||||||
regenerateModel(openScripts[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
changeTabButtonColor(
|
|
||||||
currentScript.fileName,
|
|
||||||
currentScript.hostname,
|
|
||||||
openScripts[0].fileName,
|
|
||||||
openScripts[0].hostname,
|
|
||||||
);
|
|
||||||
|
|
||||||
setCurrentScript(openScripts[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a button for each open script
|
|
||||||
const scriptButtons = [];
|
|
||||||
for (let i = 0; i < openScripts.length; i++) {
|
|
||||||
if (openScripts[i].fileName !== "") {
|
|
||||||
const fileName2 = openScripts[i].fileName;
|
|
||||||
const hostname = openScripts[i].hostname;
|
|
||||||
if (openScripts[i].fileName === currentScript.fileName && openScripts[i].hostname === currentScript.hostname) {
|
|
||||||
// Set special background color for current script tab button
|
|
||||||
scriptButtons.push(
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
{hostname}:~/{fileName2}
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div key={fileName2 + hostname} style={{ paddingRight: "5px" }}>
|
|
||||||
<Button style={{ backgroundColor: "#666" }} value={fileName2 + ":" + hostname} onClick={onTabButtonClick}>
|
|
||||||
{openScripts[i].fileName}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
value={fileName2 + ":" + hostname}
|
|
||||||
onClick={onCloseButtonClick}
|
|
||||||
style={{ maxWidth: "20px", minWidth: "20px", backgroundColor: "#666" }}
|
|
||||||
>
|
|
||||||
x
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Tooltip>,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
scriptButtons.push(
|
|
||||||
<div id={"scriptEditorTab" + fileName2 + hostname} key={"tabButton" + i} style={{ paddingRight: "5px" }}>
|
|
||||||
<Button
|
|
||||||
id={"tabButton" + openScripts[i].fileName + openScripts[i].hostname}
|
|
||||||
value={fileName2 + ":" + hostname}
|
|
||||||
onClick={onTabButtonClick}
|
|
||||||
>
|
|
||||||
{openScripts[i].fileName}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
id={"tabCloseButton" + openScripts[i].fileName + openScripts[i].hostname}
|
|
||||||
value={fileName2 + ":" + hostname}
|
|
||||||
onClick={onCloseButtonClick}
|
|
||||||
style={{ maxWidth: "20px", minWidth: "20px" }}
|
|
||||||
>
|
|
||||||
x
|
|
||||||
</Button>
|
|
||||||
</div>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,16 +562,65 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
const p = 11000 / -window.innerHeight + 100;
|
const p = 11000 / -window.innerHeight + 100;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box display="flex" flexDirection="row" alignItems="center" paddingBottom="5px">
|
<div style={{ display: currentScript !== null ? 'block' : 'none', height: '100%', width: '100%' }}>
|
||||||
{scriptButtons}
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
|
<Droppable droppableId='tabs' direction='horizontal'>
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<Box
|
||||||
|
maxWidth="1640px"
|
||||||
|
display="flex"
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.droppableProps}
|
||||||
|
style={{ backgroundColor: snapshot.isDraggingOver ? '#1F2022' : Settings.theme.backgroundprimary, overflowX: 'scroll' }}
|
||||||
|
>
|
||||||
|
{openScripts.map(({ fileName, hostname }, index) => (
|
||||||
|
<Draggable key={fileName + hostname} draggableId={fileName + hostname} index={index} disableInteractiveElementBlocking={true}>
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
style={{
|
||||||
|
...provided.draggableProps.style,
|
||||||
|
marginRight: '5px',
|
||||||
|
flexShrink: 0
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
id={"tabButton" + fileName + hostname}
|
||||||
|
onClick={() => onTabClick(index)}
|
||||||
|
style={{ background: currentScript?.fileName === openScripts[index].fileName ? Settings.theme.secondarydark : '' }}
|
||||||
|
>
|
||||||
|
{hostname}:~/{fileName}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
id={"tabCloseButton" + fileName + hostname}
|
||||||
|
onClick={() => onTabClose(index)}
|
||||||
|
style={{ maxWidth: "20px", minWidth: "20px", background: currentScript?.fileName === openScripts[index].fileName ? Settings.theme.secondarydark : '' }}
|
||||||
|
>
|
||||||
|
x
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
))}
|
||||||
|
{provided.placeholder}
|
||||||
</Box>
|
</Box>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
<div style={{ paddingBottom: '5px' }} />
|
||||||
<Editor
|
<Editor
|
||||||
beforeMount={beforeMount}
|
beforeMount={beforeMount}
|
||||||
onMount={onMount}
|
onMount={onMount}
|
||||||
loading={<Typography>Loading script editor!</Typography>}
|
loading={<Typography>Loading script editor!</Typography>}
|
||||||
height={p + "%"}
|
height={p + "%"}
|
||||||
defaultLanguage="javascript"
|
defaultLanguage="javascript"
|
||||||
defaultValue={code}
|
defaultValue={''}
|
||||||
onChange={updateCode}
|
onChange={updateCode}
|
||||||
theme={options.theme}
|
theme={options.theme}
|
||||||
options={{ ...options, glyphMargin: true }}
|
options={{ ...options, glyphMargin: true }}
|
||||||
@ -624,7 +630,7 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
<Typography color={updatingRam ? "secondary" : "primary"} sx={{ mx: 1 }}>
|
<Typography color={updatingRam ? "secondary" : "primary"} sx={{ mx: 1 }}>
|
||||||
{ram}
|
{ram}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button onClick={save}>Save (CTRL/CMD + S)</Button>
|
<Button onClick={save}>Save & Close (Ctrl/Cmd + s)</Button>
|
||||||
<Typography sx={{ mx: 1 }}>
|
<Typography sx={{ mx: 1 }}>
|
||||||
{" "}
|
{" "}
|
||||||
Documentation:{" "}
|
Documentation:{" "}
|
||||||
@ -658,6 +664,10 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
Settings.MonacoFontSize = options.fontSize;
|
Settings.MonacoFontSize = options.fontSize;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: currentScript !== null ? 'none' : 'flex', height: '100%', width: '100%', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<p style={{ color: Settings.theme.primary, fontSize: '20px', textAlign: 'center' }}><h1>No open files</h1><h5>Use "nano [File Name]" in the terminal to open files</h5></p>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,10 @@ export function PromptManager(): React.ReactElement {
|
|||||||
{prompt != null && (
|
{prompt != null && (
|
||||||
<Modal open={true} onClose={close}>
|
<Modal open={true} onClose={close}>
|
||||||
<Typography>{prompt.txt}</Typography>
|
<Typography>{prompt.txt}</Typography>
|
||||||
<Button onClick={yes}>Yes</Button>
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', paddingTop: '10px' }}>
|
||||||
|
<Button style={{ marginRight: 'auto' }} onClick={yes}>Yes</Button>
|
||||||
<Button onClick={no}>No</Button>
|
<Button onClick={no}>No</Button>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
Loading…
Reference in New Issue
Block a user