Feature: support rule provider

This commit is contained in:
Dreamacro 2020-06-06 23:48:17 +08:00
parent 836b4ba7c6
commit 7be76d374a
13 changed files with 458 additions and 257 deletions

369
package-lock.json generated
View File

@ -45,12 +45,12 @@
}
},
"@babel/code-frame": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
"integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
"dev": true,
"requires": {
"@babel/highlight": "^7.8.3"
"@babel/highlight": "^7.10.1"
}
},
"@babel/compat-data": {
@ -65,19 +65,19 @@
}
},
"@babel/core": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.1.tgz",
"integrity": "sha512-u8XiZ6sMXW/gPmoP5ijonSUln4unazG291X0XAQ5h0s8qnAFr6BRRZGUEK+jtRWdmB0NTJQt7Uga25q8GetIIg==",
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz",
"integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.1",
"@babel/generator": "^7.10.1",
"@babel/generator": "^7.10.2",
"@babel/helper-module-transforms": "^7.10.1",
"@babel/helpers": "^7.10.1",
"@babel/parser": "^7.10.1",
"@babel/parser": "^7.10.2",
"@babel/template": "^7.10.1",
"@babel/traverse": "^7.10.1",
"@babel/types": "^7.10.1",
"@babel/types": "^7.10.2",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.1",
@ -88,24 +88,15 @@
"source-map": "^0.5.0"
},
"dependencies": {
"@babel/code-frame": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
"integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.1"
}
},
"@babel/highlight": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
"integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
"@babel/types": {
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz",
"integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.1",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
"lodash": "^4.17.13",
"to-fast-properties": "^2.0.0"
}
},
"debug": {
@ -126,15 +117,28 @@
}
},
"@babel/generator": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.1.tgz",
"integrity": "sha512-AT0YPLQw9DI21tliuJIdplVfLHya6mcGa8ctkv7n4Qv+hYacJrKmNWIteAK1P9iyLikFIAkwqJ7HAOqIDLFfgA==",
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz",
"integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==",
"dev": true,
"requires": {
"@babel/types": "^7.10.1",
"@babel/types": "^7.10.2",
"jsesc": "^2.5.1",
"lodash": "^4.17.13",
"source-map": "^0.5.0"
},
"dependencies": {
"@babel/types": {
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz",
"integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.1",
"lodash": "^4.17.13",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/helper-annotate-as-pure": {
@ -178,9 +182,9 @@
}
},
"@babel/helper-compilation-targets": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.1.tgz",
"integrity": "sha512-YuF8IrgSmX/+MV2plPkjEnzlC2wf+gaok8ehMNN0jodF3/sejZauExqpEVGbJua62oaWoNYIXwz4RmAsVcGyHw==",
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz",
"integrity": "sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.10.1",
@ -191,9 +195,9 @@
}
},
"@babel/helper-create-class-features-plugin": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.1.tgz",
"integrity": "sha512-bwhdehBJZt84HuPUcP1HaTLuc/EywVS8rc3FgsEPDcivg+DCW+SHuLHVkYOmcBA1ZfI+Z/oZjQc/+bPmIO7uAA==",
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.2.tgz",
"integrity": "sha512-5C/QhkGFh1vqcziq1vAL6SI9ymzUp8BCYjFpvYVhWP4DlATIb3u5q3iUd35mvlyGs8fO7hckkW7i0tmH+5+bvQ==",
"dev": true,
"requires": {
"@babel/helper-function-name": "^7.10.1",
@ -396,20 +400,20 @@
}
},
"@babel/highlight": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
"integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
"integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.1",
"chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.1.tgz",
"integrity": "sha512-AUTksaz3FqugBkbTZ1i+lDLG5qy8hIzCaAxEtttU6C0BtZZU9pkNZtWSVAht4EW9kl46YBiyTGMp9xTTGqViNg==",
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz",
"integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==",
"dev": true
},
"@babel/plugin-proposal-async-generator-functions": {
@ -1001,13 +1005,13 @@
}
},
"@babel/preset-env": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.1.tgz",
"integrity": "sha512-bGWNfjfXRLnqbN2T4lB3pMfoic8dkRrmHpVZamSFHzGy5xklyHTobZ28TVUD2grhE5WDnu67tBj8oslIhkiOMQ==",
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.2.tgz",
"integrity": "sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.10.1",
"@babel/helper-compilation-targets": "^7.10.1",
"@babel/helper-compilation-targets": "^7.10.2",
"@babel/helper-module-imports": "^7.10.1",
"@babel/helper-plugin-utils": "^7.10.1",
"@babel/plugin-proposal-async-generator-functions": "^7.10.1",
@ -1064,12 +1068,25 @@
"@babel/plugin-transform-unicode-escapes": "^7.10.1",
"@babel/plugin-transform-unicode-regex": "^7.10.1",
"@babel/preset-modules": "^0.1.3",
"@babel/types": "^7.10.1",
"@babel/types": "^7.10.2",
"browserslist": "^4.12.0",
"core-js-compat": "^3.6.2",
"invariant": "^2.2.2",
"levenary": "^1.1.1",
"semver": "^5.5.0"
},
"dependencies": {
"@babel/types": {
"version": "7.10.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz",
"integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.1",
"lodash": "^4.17.13",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/preset-modules": {
@ -1127,28 +1144,6 @@
"@babel/code-frame": "^7.10.1",
"@babel/parser": "^7.10.1",
"@babel/types": "^7.10.1"
},
"dependencies": {
"@babel/code-frame": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
"integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.1"
}
},
"@babel/highlight": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
"integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.1",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
}
}
},
"@babel/traverse": {
@ -1168,26 +1163,6 @@
"lodash": "^4.17.13"
},
"dependencies": {
"@babel/code-frame": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
"integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.1"
}
},
"@babel/highlight": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
"integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.1",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@ -1583,6 +1558,23 @@
"fastq": "^1.6.0"
}
},
"@npmcli/move-file": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz",
"integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==",
"dev": true,
"requires": {
"mkdirp": "^1.0.4"
},
"dependencies": {
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true
}
}
},
"@scarf/scarf": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.0.5.tgz",
@ -1701,9 +1693,9 @@
"dev": true
},
"@types/node": {
"version": "14.0.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.6.tgz",
"integrity": "sha512-FbNmu4F67d3oZMWBV6Y4MaPER+0EpE9eIYf2yaHhCWovc1dlXCZkqGX4NLHfVVr6umt20TNBdRzrNJIzIKfdbw==",
"version": "14.0.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.11.tgz",
"integrity": "sha512-lCvvI24L21ZVeIiyIUHZ5Oflv1hhHQ5E1S25IRlKIXaRkVgmXpJMI3wUJkmym2bTbCe+WoIibQnMVAU3FguaOg==",
"dev": true
},
"@types/normalize-package-data": {
@ -1772,9 +1764,9 @@
}
},
"@types/react-table": {
"version": "7.0.18",
"resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-7.0.18.tgz",
"integrity": "sha512-O4iKmVYVQz+6Nl9LsLtWQz9Unsmq0UySJrh5hpV5d+wrf15skhB0dqI9ocCNovJpcYxGjHrn3VbeSyAcaxHZtA==",
"version": "7.0.19",
"resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-7.0.19.tgz",
"integrity": "sha512-RYyEY7Yry6F2JsKhHeFsGdzuFF1hMqBStQrrazDzpBl4m/ECGHJxFVQjLBRzRwK+47ZKNPm79f7qEpHirbiCLA==",
"dev": true,
"requires": {
"@types/react": "*"
@ -1884,12 +1876,12 @@
}
},
"@typescript-eslint/eslint-plugin": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.0.2.tgz",
"integrity": "sha512-ER3bSS/A/pKQT/hjMGCK8UQzlL0yLjuCZ/G8CDFJFVTfl3X65fvq2lNYqOG8JPTfrPa2RULCdwfOyFjZEMNExQ==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.1.0.tgz",
"integrity": "sha512-D52KwdgkjYc+fmTZKW7CZpH5ZBJREJKZXRrveMiRCmlzZ+Rw9wRVJ1JAmHQ9b/+Ehy1ZeaylofDB9wwXUt83wg==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "3.0.2",
"@typescript-eslint/experimental-utils": "3.1.0",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
"semver": "^7.3.2",
@ -1905,33 +1897,33 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.0.2.tgz",
"integrity": "sha512-4Wc4EczvoY183SSEnKgqAfkj1eLtRgBQ04AAeG+m4RhTVyaazxc1uI8IHf0qLmu7xXe9j1nn+UoDJjbmGmuqXQ==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.1.0.tgz",
"integrity": "sha512-Zf8JVC2K1svqPIk1CB/ehCiWPaERJBBokbMfNTNRczCbQSlQXaXtO/7OfYz9wZaecNvdSvVADt6/XQuIxhC79w==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/typescript-estree": "3.0.2",
"@typescript-eslint/typescript-estree": "3.1.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.0.2.tgz",
"integrity": "sha512-80Z7s83e8QXHNUspqVlWwb4t5gdz/1bBBmafElbK1wwAwiD/yvJsFyHRxlEpNrt4rdK6eB3p+2WEFkEDHAKk9w==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.1.0.tgz",
"integrity": "sha512-NcDSJK8qTA2tPfyGiPes9HtVKLbksmuYjlgGAUs7Ld2K0swdWibnCq9IJx9kJN8JJdgUJSorFiGaPHBgH81F/Q==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "3.0.2",
"@typescript-eslint/typescript-estree": "3.0.2",
"@typescript-eslint/experimental-utils": "3.1.0",
"@typescript-eslint/typescript-estree": "3.1.0",
"eslint-visitor-keys": "^1.1.0"
}
},
"@typescript-eslint/typescript-estree": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.0.2.tgz",
"integrity": "sha512-cs84mxgC9zQ6viV8MEcigfIKQmKtBkZNDYf8Gru2M+MhnA6z9q0NFMZm2IEzKqAwN8lY5mFVd1Z8DiHj6zQ3Tw==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.1.0.tgz",
"integrity": "sha512-+4nfYauqeQvK55PgFrmBWFVYb6IskLyOosYEmhH3mSVhfBp9AIJnjExdgDmKWoOBHRcPM8Ihfm2BFpZf0euUZQ==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@ -3455,11 +3447,12 @@
"dev": true
},
"cacache": {
"version": "15.0.3",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.3.tgz",
"integrity": "sha512-bc3jKYjqv7k4pWh7I/ixIjfcjPul4V4jme/WbjvwGS5LzoPL/GzXr4C5EgPNLO/QEZl9Oi61iGitYEdwcrwLCQ==",
"version": "15.0.4",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.4.tgz",
"integrity": "sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw==",
"dev": true,
"requires": {
"@npmcli/move-file": "^1.0.1",
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"glob": "^7.1.4",
@ -3470,7 +3463,6 @@
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.2",
"mkdirp": "^1.0.3",
"move-file": "^2.0.0",
"p-map": "^4.0.0",
"promise-inflight": "^1.0.1",
"rimraf": "^3.0.2",
@ -5223,9 +5215,9 @@
"dev": true
},
"eslint": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.1.0.tgz",
"integrity": "sha512-DfS3b8iHMK5z/YLSme8K5cge168I8j8o1uiVmFCgnnjxZQbCGyraF8bMl7Ju4yfBmCuxD7shOF7eqGkcuIHfsA==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.2.0.tgz",
"integrity": "sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@ -5234,10 +5226,10 @@
"cross-spawn": "^7.0.2",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-scope": "^5.0.0",
"eslint-scope": "^5.1.0",
"eslint-utils": "^2.0.0",
"eslint-visitor-keys": "^1.1.0",
"espree": "^7.0.0",
"eslint-visitor-keys": "^1.2.0",
"espree": "^7.1.0",
"esquery": "^1.2.0",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
@ -5321,6 +5313,12 @@
"ms": "^2.1.1"
}
},
"eslint-visitor-keys": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz",
"integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==",
"dev": true
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
@ -5750,9 +5748,9 @@
"dev": true
},
"eslint-scope": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
"integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
@ -5775,14 +5773,22 @@
"dev": true
},
"espree": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.0.0.tgz",
"integrity": "sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==",
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
"integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
"dev": true,
"requires": {
"acorn": "^7.1.1",
"acorn": "^7.2.0",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
"eslint-visitor-keys": "^1.2.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz",
"integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==",
"dev": true
}
}
},
"esprima": {
@ -6502,9 +6508,9 @@
}
},
"flatted": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
"flush-write-stream": {
@ -9426,9 +9432,9 @@
}
},
"min-indent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.0.tgz",
"integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
"dev": true
},
"mini-create-react-context": {
@ -9657,23 +9663,6 @@
"run-queue": "^1.0.3"
}
},
"move-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/move-file/-/move-file-2.0.0.tgz",
"integrity": "sha512-cdkdhNCgbP5dvS4tlGxZbD+nloio9GIimP57EjqFhwLcMjnU+XJKAZzlmg/TN/AK1LuNAdTSvm3CPPP4Xkv0iQ==",
"dev": true,
"requires": {
"path-exists": "^4.0.0"
},
"dependencies": {
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
}
}
},
"mozjpeg": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-6.0.1.tgz",
@ -11511,9 +11500,9 @@
}
},
"recoil": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.0.7.tgz",
"integrity": "sha512-U/0kniHLk131hKhAX35QGdghVf3+PSkLcFIFoNBNy+yv62qCLm3TE5c3v4x4WYzuKgw1fxU3GGhKHAUYdyRnTQ=="
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.0.8.tgz",
"integrity": "sha512-lfIH6y9A0wQ6piucwWFZfpp9KNQ+mFdTPFPFL0m0sRCrfsuwz3lyVaaofHY6/O4BXekDoXyjYodPBgCSdw9HCw=="
},
"redent": {
"version": "1.0.0",
@ -11527,9 +11516,9 @@
}
},
"regenerate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
"integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
"integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==",
"dev": true
},
"regenerate-unicode-properties": {
@ -11952,9 +11941,9 @@
"dev": true
},
"sass": {
"version": "1.26.7",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.7.tgz",
"integrity": "sha512-xgNazdkr6yvgHEfNaOjKtZzhDZmKYMCmoRKMPrTDo7YvjaITIzU2DDYsIUuN/atAg7/JOxPeCQHH7TtCo5Tq2g==",
"version": "1.26.8",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.8.tgz",
"integrity": "sha512-yvtzyrKLGiXQu7H12ekXqsfoGT/aTKeMDyVzCB675k1HYuaj0py63i8Uf4SI9CHXj6apDhpfwbUr3gGOjdpu2Q==",
"dev": true,
"requires": {
"chokidar": ">=2.0.0 <4.0.0"
@ -13005,14 +12994,14 @@
"dev": true
},
"stylelint": {
"version": "13.5.0",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.5.0.tgz",
"integrity": "sha512-+Jy7ieKAWKTf2tmcAE7jgScxH39Urb87i0bjK/enScFaGWWaFn4kAPwepGOSk2b7CLUDVt/O6kwA0x0p/V7moQ==",
"version": "13.6.0",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.6.0.tgz",
"integrity": "sha512-55gG2pNjVr183JJM/tlr3KAua6vTVX7Ho/lgKKuCIWszTZ1gmrXjX4Wok53SI8wRYFPbwKAcJGULQ77OJxTcNw==",
"dev": true,
"requires": {
"@stylelint/postcss-css-in-js": "^0.37.1",
"@stylelint/postcss-markdown": "^0.36.1",
"autoprefixer": "^9.7.6",
"autoprefixer": "^9.8.0",
"balanced-match": "^1.0.0",
"chalk": "^4.0.0",
"cosmiconfig": "^6.0.0",
@ -13021,10 +13010,10 @@
"file-entry-cache": "^5.0.1",
"get-stdin": "^8.0.0",
"global-modules": "^2.0.0",
"globby": "^11.0.0",
"globby": "^11.0.1",
"globjoin": "^0.1.4",
"html-tags": "^3.1.0",
"ignore": "^5.1.4",
"ignore": "^5.1.8",
"import-lazy": "^4.0.0",
"imurmurhash": "^0.1.4",
"known-css-properties": "^0.19.0",
@ -13035,7 +13024,7 @@
"meow": "^7.0.1",
"micromatch": "^4.0.2",
"normalize-selector": "^0.2.0",
"postcss": "^7.0.30",
"postcss": "^7.0.32",
"postcss-html": "^0.36.0",
"postcss-less": "^3.1.4",
"postcss-media-query-parser": "^0.2.3",
@ -13043,7 +13032,7 @@
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-safe-parser": "^4.0.2",
"postcss-sass": "^0.4.4",
"postcss-scss": "^2.0.0",
"postcss-scss": "^2.1.1",
"postcss-selector-parser": "^6.0.2",
"postcss-syntax": "^0.36.2",
"postcss-value-parser": "^4.1.0",
@ -13056,7 +13045,7 @@
"sugarss": "^2.0.0",
"svg-tags": "^1.0.0",
"table": "^5.4.6",
"v8-compile-cache": "^2.1.0",
"v8-compile-cache": "^2.1.1",
"write-file-atomic": "^3.0.3"
},
"dependencies": {
@ -13177,9 +13166,9 @@
"dev": true
},
"globby": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz",
"integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==",
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
"integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
"dev": true,
"requires": {
"array-union": "^2.1.0",
@ -13197,9 +13186,9 @@
"dev": true
},
"ignore": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.6.tgz",
"integrity": "sha512-cgXgkypZBcCnOgSihyeqbo6gjIaIyDqPQB7Ra4vhE9m6kigdGoQDMHjviFhRZo3IMlRy6yElosoviMs5YxZXUA==",
"version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
"dev": true
},
"import-lazy": {
@ -13315,9 +13304,9 @@
"dev": true
},
"postcss": {
"version": "7.0.30",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.30.tgz",
"integrity": "sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==",
"version": "7.0.32",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
"integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
@ -13835,17 +13824,17 @@
}
},
"terser-webpack-plugin": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-3.0.2.tgz",
"integrity": "sha512-QeBHLJzKJHCnrPNlZj5EmOF6wwvzpVGDHvTrySIH8+jZEXfcKKCiriRmF6945rKzuZDnkOEU/LDv7qtPiiyP/Q==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-3.0.3.tgz",
"integrity": "sha512-bZFnotuIKq5Rqzrs+qIwFzGdKdffV9epG5vDSEbYzvKAhPeR5RbbrQysfPgbIIMhNAQtZD2hGwBfSKUXjXZZZw==",
"dev": true,
"requires": {
"cacache": "^15.0.3",
"cacache": "^15.0.4",
"find-cache-dir": "^3.3.1",
"jest-worker": "^26.0.0",
"p-limit": "^2.3.0",
"schema-utils": "^2.6.6",
"serialize-javascript": "^3.0.0",
"serialize-javascript": "^3.1.0",
"source-map": "^0.6.1",
"terser": "^4.6.13",
"webpack-sources": "^1.4.3"
@ -14247,9 +14236,9 @@
}
},
"typescript": {
"version": "3.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz",
"integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==",
"version": "3.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
"integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
"dev": true
},
"unbzip2-stream": {
@ -14622,9 +14611,9 @@
"dev": true
},
"v8-compile-cache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
"integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
"integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
"dev": true
},
"validate-npm-package-license": {

View File

@ -29,28 +29,28 @@
},
"devDependencies": {
"@babel/cli": "^7.10.1",
"@babel/core": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@babel/core": "^7.10.2",
"@babel/preset-env": "^7.10.2",
"@babel/preset-react": "^7.10.1",
"@hot-loader/react-dom": "^16.13.0",
"@types/classnames": "^2.2.10",
"@types/lodash-es": "^4.17.3",
"@types/node": "^14.0.6",
"@types/node": "^14.0.11",
"@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8",
"@types/react-router-dom": "^5.1.5",
"@types/react-table": "^7.0.18",
"@types/react-table": "^7.0.19",
"@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.2",
"@types/recoil": "0.0.0",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
"@typescript-eslint/eslint-plugin": "^3.1.0",
"@typescript-eslint/parser": "^3.1.0",
"autoprefixer": "^9.8.0",
"awesome-typescript-loader": "^5.2.1",
"babel-loader": "^8.1.0",
"babel-preset-minify": "^0.5.1",
"css-loader": "^3.5.3",
"eslint": "^7.1.0",
"eslint": "^7.2.0",
"eslint-config-standard": "^14.1.1",
"eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.20.2",
@ -65,14 +65,14 @@
"offline-plugin": "^5.0.7",
"postcss-loader": "^3.0.0",
"react-hot-loader": "^4.12.21",
"sass": "^1.26.7",
"sass": "^1.26.8",
"sass-loader": "^8.0.2",
"style-loader": "^1.2.1",
"stylelint": "^13.5.0",
"stylelint": "^13.6.0",
"stylelint-config-standard": "^20.0.0",
"stylelint-webpack-plugin": "^2.0.0",
"terser-webpack-plugin": "^3.0.2",
"typescript": "^3.9.3",
"terser-webpack-plugin": "^3.0.3",
"typescript": "^3.9.5",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-middleware": "^3.7.2",
@ -93,7 +93,7 @@
"react-table": "^7.1.0",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"recoil": "0.0.7",
"recoil": "0.0.8",
"swr": "^0.2.2",
"use-immer": "^0.4.0"
}

View File

@ -7,14 +7,15 @@ import './style.scss'
interface LoadingProps extends BaseComponentProps {
visible: boolean
spinnerClassName?: string
}
export function Loading (props: LoadingProps) {
const classname = classnames('loading', 'visible')
const classname = classnames('loading', 'visible', props.className)
return props.visible
? (
<div className={classname}>
<Spinner />
<Spinner className={props.spinnerClassName} />
</div>
)
: null

View File

@ -62,10 +62,12 @@ function ProxyGroups () {
}
function ProxyProviders () {
const { providers } = useProxyProviders()
const { providers, update } = useProxyProviders()
const { useTranslation } = useI18n()
const { t } = useTranslation('Proxies')
useSWR('providers', update)
return <>
{
providers.length !== 0 &&
@ -134,10 +136,7 @@ function Proxies () {
export default function ProxyContainer () {
const { update: updateProxy } = useProxy()
const { update: updateProvider } = useProxyProviders()
useSWR('proxies', updateProxy)
useSWR('providers', updateProvider)
return (
<div className="page">

View File

@ -0,0 +1,48 @@
import * as React from 'react'
import classnames from 'classnames'
import { Card, Tag, Icon } from '@components'
import { useI18n, useRuleProviders } from '@stores'
import { fromNow } from '@lib/date'
import { RuleProvider, updateRuleProvider } from '@lib/request'
import { useVisible } from '@lib/hook'
import './style.scss'
interface ProvidersProps {
provider: RuleProvider
}
export function Provider (props: ProvidersProps) {
const { update } = useRuleProviders()
const { useTranslation, lang } = useI18n()
const { provider } = props
const { t } = useTranslation('Proxies')
const { visible, hide, show } = useVisible()
function handleUpdate () {
show()
updateRuleProvider(provider.name).then(() => update()).finally(() => hide())
}
const updateClassnames = classnames('rule-provider-icon', { 'rule-provider-loading': visible })
return (
<Card className="rule-provider">
<div className="rule-provider-header">
<div className="rule-provider-header-part">
<span className="rule-provider-name">{ provider.name }</span>
<Tag>{ provider.vehicleType }</Tag>
<Tag className="rule-provider-behavior">{ provider.behavior }</Tag>
</div>
<div className="rule-provider-header-part">
{
provider.updatedAt &&
<span className="rule-provider-update">{ `${t('providerUpdateTime')}: ${fromNow(new Date(provider.updatedAt), lang)}`}</span>
}
<Icon className={updateClassnames} type="update" size={18} onClick={handleUpdate} />
</div>
</div>
</Card>
)
}

View File

@ -0,0 +1,79 @@
@import '~@styles/variables';
.rule-provider {
position: relative;
display: flex;
flex-direction: column;
font-size: 16px;
padding: 20px;
color: $color-black-light;
}
.rule-provider-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.rule-provider-header-part {
display: flex;
align-items: center;
}
.rule-provider-name {
width: 120px;
margin-right: 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.rule-provider-behavior {
margin-left: 12px;
background-color: $color-primary-dark;
color: #fff;
}
.rule-provider-spinner {
transform: scale(0.4);
}
.rule-provider-proxies {
list-style: none;
}
.rule-provider-item {
box-shadow: 0 0 24px 0 rgba(44, 138, 248, 0.2);
&:hover {
box-shadow: 0 0 24px 0 rgba(84, 117, 154, 0.4);
}
}
.rule-provider-update {
line-height: 14px;
font-size: 14px;
}
.rule-provider-icon {
display: block;
margin-left: 20px;
cursor: pointer;
&.rule-provider-loading::before {
color: $color-gray-darken;
cursor: not-allowed;
animation: spinner 2s infinite linear;
}
}
@media (max-width: 768px) {
.rule-provider-header {
flex-direction: column;
align-items: flex-start;
}
.rule-provider-header-part {
margin: 6px 0;
}
}

View File

@ -1,11 +1,43 @@
import React from 'react'
import React, { useLayoutEffect } from 'react'
import { Header, Card, Row, Col } from '@components'
import { useI18n, useRule } from '@stores'
import { useI18n, useRule, useRuleProviders, useVersion } from '@stores'
import { FixedSizeList as List } from 'react-window'
import AutoSizer from 'react-virtualized-auto-sizer'
import useSWR from 'swr'
import { Provider } from './Provider'
import './style.scss'
function RuleProviders () {
const { providers, update } = useRuleProviders()
const { premium } = useVersion()
const { useTranslation } = useI18n()
const { t } = useTranslation('Rules')
useLayoutEffect(() => {
if (premium) {
update()
}
}, [premium])
return <>
{
providers.length !== 0 &&
<div className="proxies-container">
<Header title={t('providerTitle')} />
<ul className="proxies-providers-list">
{
providers.map(p => (
<li className="proxies-providers-item" key={p.name}>
<Provider provider={p} />
</li>
))
}
</ul>
</div>
}
</>
}
export default function Rules () {
const { rules, update } = useRule()
const { useTranslation } = useI18n()
@ -34,6 +66,7 @@ export default function Rules () {
return (
<div className="page">
<RuleProviders />
<Header title={t('title')} />
<Card className="rules-card">
<AutoSizer className="rules">

View File

@ -4,7 +4,7 @@ import { Header, Card, Row, Col, Switch, ButtonSelect, ButtonSelectOptions, Inpu
import { useI18n, useClashXData, useAPIInfo, useGeneral, useIdentity } from '@stores'
import { updateConfig } from '@lib/request'
import { useObject } from '@lib/hook'
import { isClashX, jsBridge } from '@lib/jsBridge'
import { jsBridge } from '@lib/jsBridge'
import { Lang } from '@i18n'
import './style.scss'
@ -19,15 +19,12 @@ export default function Settings () {
const { t } = useTranslation('Settings')
const [info, set] = useObject({
socks5ProxyPort: 7891,
httpProxyPort: 7890,
isClashX: false
httpProxyPort: 7890
})
useEffect(() => {
fetchGeneral()
if (isClashX()) {
fetchClashXData().then(() => set('isClashX', true))
}
fetchClashXData()
}, [])
useEffect(() => {
@ -96,7 +93,7 @@ export default function Settings () {
<span className="label">{t('labels.startAtLogin')}</span>
</Col>
<Col span={8} className="value-column">
<Switch disabled={!info.isClashX} checked={startAtLogin} onChange={handleStartAtLoginChange} />
<Switch disabled={!clashXData.isClashX} checked={startAtLogin} onChange={handleStartAtLoginChange} />
</Col>
</Col>
<Col span={12}>
@ -115,7 +112,7 @@ export default function Settings () {
</Col>
<Col span={8} className="value-column">
<Switch
disabled={!info.isClashX}
disabled={!clashXData.isClashX}
checked={systemProxy}
onChange={handleSetSystemProxy}
/>

View File

@ -1,7 +1,7 @@
import * as React from 'react'
import { NavLink } from 'react-router-dom'
import classnames from 'classnames'
import { useI18n, useVersion } from '@stores'
import { useI18n, useVersion, useClashXData } from '@stores'
import './style.scss'
import logo from '@assets/logo.png'
@ -20,9 +20,11 @@ export default function Sidebar (props: SidebarProps) {
const { routes } = props
const { useTranslation } = useI18n()
const { version, premium, update } = useVersion()
const { data: { isClashX }, update: updateClashXData } = useClashXData()
const { t } = useTranslation('SideBar')
useSWR('version', update)
useSWR('clashx', updateClashXData)
const navlinks = routes.map(
({ path, name, exact, noMobile }) => (
@ -39,7 +41,7 @@ export default function Sidebar (props: SidebarProps) {
{ navlinks }
</ul>
<div className="sidebar-version">
<span className="sidebar-version-label">Clash { t('Version') }</span>
<span className="sidebar-version-label">Clash{ isClashX && 'X' } { t('Version') }</span>
<span className="sidebar-version-text">{ version }</span>
{ premium && <span className="sidebar-version-label">Premium</span> }
</div>

View File

@ -41,7 +41,9 @@ export default {
title: 'Logs'
},
Rules: {
title: 'Rules'
title: 'Rules',
providerTitle: 'Providers',
providerUpdateTime: 'Last updated at'
},
Connections: {
title: 'Connections',

View File

@ -41,7 +41,9 @@ export default {
title: '日志'
},
Rules: {
title: '规则'
title: '规则',
providerTitle: '规则集',
providerUpdateTime: '最后更新于'
},
Connections: {
title: '连接',

View File

@ -25,23 +25,32 @@ export interface Rule {
}
export interface Proxies {
proxies: {
[key: string]: Proxy | Group
}
proxies: Record<string, Proxy | Group>
}
export interface Provider {
name: string
proxies: Array<Group | Proxy>
type: 'Proxy' | 'Rule'
type: 'Proxy'
vehicleType: 'HTTP' | 'File' | 'Compatible'
updatedAt?: string
}
export interface RuleProvider {
name: string
type: 'Rule'
vehicleType: 'HTTP' | 'File'
behavior: string
ruleCount: number
updatedAt?: string
}
export interface RuleProviders {
providers: Record<string, RuleProvider>
}
export interface ProxyProviders {
providers: {
[key: string]: Provider
}
providers: Record<string, Provider>
}
interface History {
@ -159,11 +168,21 @@ export async function getProxyProviders () {
})
}
export async function getRuleProviders () {
const req = await getInstance()
return req.get<RuleProviders>('providers/rules')
}
export async function updateProvider (name: string) {
const req = await getInstance()
return req.put<void>(`providers/proxies/${encodeURIComponent(name)}`)
}
export async function updateRuleProvider (name: string) {
const req = await getInstance()
return req.put<void>(`providers/rules/${encodeURIComponent(name)}`)
}
export async function healthCheckProvider (name: string) {
const req = await getInstance()
return req.get<void>(`providers/proxies/${encodeURIComponent(name)}/healthcheck`)

View File

@ -7,7 +7,7 @@ import { getLanguage, setLanguage, Lang, locales, Language } from '@i18n'
import { useRecoilObjectWithImmer } from '@lib/recoil'
import * as API from '@lib/request'
import { setLocalStorageItem, partition, to } from '@lib/helper'
import { jsBridge } from '@lib/jsBridge'
import { jsBridge, isClashX } from '@lib/jsBridge'
import * as Models from '@models'
const identity = atom({
@ -62,6 +62,32 @@ export function useI18n () {
return { lang, locales, setLang, useTranslation }
}
export const version = atom({
key: 'version',
default: {
version: '',
premium: false
}
})
export function useVersion () {
const [data, set] = useRecoilState(version)
const { set: setIdentity } = useIdentity()
async function update () {
const [resp, err] = await to(API.getVersion())
setIdentity(!err)
set(
err
? { version: '', premium: false }
: { version: resp.data.version, premium: !!resp.data.premium }
)
}
return { version: data.version, premium: data.premium, update }
}
export const config = atom({
key: 'config',
default: {
@ -97,6 +123,31 @@ export function useProxyProviders () {
return { providers: data, update }
}
export const ruleProvider = atom({
key: 'ruleProvider',
default: [] as API.RuleProvider[]
})
export function useRuleProviders () {
const [data, set] = useRecoilState(ruleProvider)
const [{ premium }] = useRecoilState(version)
async function update () {
if (!premium) {
return
}
const ruleProviders = await API.getRuleProviders()
const providers = Object.keys(ruleProviders.data.providers)
.map<API.RuleProvider>(name => ruleProviders.data.providers[name])
set(providers)
}
return { providers: data, update }
}
export const general = atom({
key: 'general',
default: {} as Models.Data['general']
@ -179,35 +230,10 @@ export const proxyMapping = selector({
}
})
export const version = atom({
key: 'version',
default: {
version: '',
premium: false
}
})
export function useVersion () {
const [data, set] = useRecoilState(version)
const { set: setIdentity } = useIdentity()
async function update () {
const [resp, err] = await to(API.getVersion())
setIdentity(!err)
set(
err
? { version: '', premium: false }
: { version: resp.data.version, premium: !!resp.data.premium }
)
}
return { version: data.version, premium: data.premium, update }
}
export const clashxData = atom({
key: 'clashxData',
default: {
isClashX: false,
startAtLogin: false,
systemProxy: false
}
@ -217,10 +243,14 @@ export function useClashXData () {
const [data, set] = useRecoilState(clashxData)
async function update () {
if (!isClashX()) {
return
}
const startAtLogin = await jsBridge.getStartAtLogin()
const systemProxy = await jsBridge.isSystemProxySet()
set({ startAtLogin, systemProxy })
set({ startAtLogin, systemProxy, isClashX: true })
}
return { data, update }