diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 8e94654..0000000 --- a/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 2 -insert_final_newline = true - -[*.rs] -charset = utf-8 -end_of_line = lf -indent_size = 4 -insert_final_newline = true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 6749373..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "[BUG]" -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Information** - - OS: [e.g. macOS] - - Clash Verge Version: [e.g. 1.3.4] - - Clash Core: [e.g. Clash or Clash Meta] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 6269982..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[Feature]" -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/alpha.yml b/.github/workflows/alpha.yml deleted file mode 100644 index 91eeb6c..0000000 --- a/.github/workflows/alpha.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Alpha CI - -on: - workflow_dispatch: - inputs: - debug: - type: boolean - default: false - -env: - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: short - -jobs: - release: - strategy: - fail-fast: false - matrix: - os: [windows-latest, ubuntu-20.04, macos-latest] - runs-on: ${{ matrix.os }} - if: startsWith(github.repository, 'zzzgydi') - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - with: - workspaces: src-tauri - - - name: Install Node - uses: actions/setup-node@v4 - with: - node-version: "16" - cache: "yarn" - - - name: Delete current release assets - if: startsWith(matrix.os, 'ubuntu-') - uses: mknejp/delete-release-assets@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - tag: alpha - fail-if-no-assets: false - fail-if-no-release: false - assets: | - *.zip - *.gz - *.AppImage - *.deb - *.dmg - *.msi - *.sig - *.exe - - - name: Install Dependencies (ubuntu only) - if: startsWith(matrix.os, 'ubuntu-') - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf openssl - - - name: Yarn install and check - run: | - yarn install --network-timeout 1000000 --frozen-lockfile - yarn run check - - - name: Tauri build - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - with: - tagName: alpha - releaseName: "Clash Verge Alpha" - releaseBody: "Alpha Version (include debug)" - releaseDraft: false - prerelease: true - includeDebug: ${{ github.event.inputs.debug }} - - - name: Portable Bundle - if: startsWith(matrix.os, 'windows-') - run: | - yarn build - yarn run portable - env: - TAG_NAME: alpha - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - VITE_WIN_PORTABLE: 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 1fce34f..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Release CI - -on: - workflow_dispatch: - push: - tags: - - v** - -env: - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: short - -jobs: - release: - strategy: - matrix: - os: [windows-latest, ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - if: startsWith(github.repository, 'zzzgydi') - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - with: - workspaces: src-tauri - - - name: Install Node - uses: actions/setup-node@v4 - with: - node-version: "16" - cache: "yarn" - - - name: Install Dependencies (ubuntu only) - if: startsWith(matrix.os, 'ubuntu-') - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf openssl - - - name: Yarn install and check - run: | - yarn install --network-timeout 1000000 --frozen-lockfile - yarn run check - - - name: Tauri build - uses: tauri-apps/tauri-action@v0 - # enable cache even though failed - # continue-on-error: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - with: - tagName: v__VERSION__ - releaseName: "Clash Verge v__VERSION__" - releaseBody: "More new features are now supported." - releaseDraft: false - prerelease: true - - - name: Portable Bundle - if: startsWith(matrix.os, 'windows-') - # rebuild with env settings - run: | - yarn build - yarn run portable - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - VITE_WIN_PORTABLE: 1 - - release-update: - needs: release - runs-on: ubuntu-latest - if: | - startsWith(github.repository, 'zzzgydi') && - startsWith(github.ref, 'refs/tags/v') - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install Node - uses: actions/setup-node@v4 - with: - node-version: "16" - cache: "yarn" - - - name: Yarn install - run: yarn install --network-timeout 1000000 --frozen-lockfile - - - name: Release updater file - run: yarn run updater - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/compatible.yml b/.github/workflows/compatible.yml deleted file mode 100644 index abbbbb6..0000000 --- a/.github/workflows/compatible.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Compatible CI - -on: - workflow_dispatch: - # push: - # tags: - # - v** - -env: - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: short - -jobs: - build: - strategy: - fail-fast: false - matrix: - targets: - - tag: macOS-10.15 - os: macos-10.15 - - tag: Ubuntu18 - os: ubuntu-18.04 - - tag: Ubuntu22 - os: ubuntu-22.04 - - runs-on: ${{ matrix.targets.os }} - if: startsWith(github.repository, 'zzzgydi') - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - with: - workspaces: src-tauri - - - name: Install Node - uses: actions/setup-node@v1 - with: - node-version: 16 - - # - name: Install Dependencies (ubuntu18 only) - # if: matrix.targets.os == 'ubuntu-18.04' - # run: | - # sudo apt-get update - # sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libappindicator3-dev librsvg2-dev libayatana-appindicator3-dev - - - name: Install Dependencies (ubuntu22 only) - if: startsWith(matrix.targets.os, 'ubuntu-') - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf - - - name: Get yarn cache dir path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - name: Yarn Cache - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Yarn install and check - run: | - yarn install --network-timeout 1000000 - yarn run check - - - name: Tauri build - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - with: - tagName: ${{ matrix.targets.tag }} - releaseName: "Compatible For ${{ matrix.targets.tag }}" - releaseBody: "More new features are now supported." - releaseDraft: false - prerelease: false - - # - name: Portable Bundle - # if: matrix.os == 'windows-latest' - # # rebuild with env settings - # run: | - # yarn build - # yarn run portable - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - # TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - # VITE_WIN_PORTABLE: 1 diff --git a/.github/workflows/meta.yml b/.github/workflows/meta.yml deleted file mode 100644 index a26d9f0..0000000 --- a/.github/workflows/meta.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Meta CI - -on: - workflow_dispatch: - push: - tags: - - v** - -env: - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: short - -jobs: - release: - strategy: - fail-fast: false - matrix: - os: [windows-latest, ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - if: startsWith(github.repository, 'zzzgydi') - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - with: - workspaces: src-tauri - - - name: Install Node - uses: actions/setup-node@v1 - with: - node-version: 16 - - - name: Delete current release assets - if: matrix.os == 'ubuntu-latest' - uses: mknejp/delete-release-assets@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - tag: meta - fail-if-no-assets: false - fail-if-no-release: false - assets: | - *.zip - *.gz - *.AppImage - *.deb - *.dmg - *.msi - *.sig - - - name: Install Dependencies (ubuntu only) - if: startsWith(matrix.os, 'ubuntu-') - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf openssl - - - name: Get yarn cache dir path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - name: Yarn Cache - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Yarn install and check - run: | - yarn install --network-timeout 1000000 - yarn run check - - - name: Tauri build - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - with: - tagName: meta - releaseName: "Clash Verge Meta" - releaseBody: "" - releaseDraft: false - prerelease: true - args: -f default-meta - - - name: Portable Bundle - if: matrix.os == 'windows-latest' - run: | - yarn build -f default-meta - yarn run portable - env: - TAG_NAME: meta - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - VITE_WIN_PORTABLE: 1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 3576f5c..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Test CI - -on: - workflow_dispatch: - inputs: - os: - description: "Runs on OS" - required: true - default: windows-latest - type: choice - options: - - windows-latest - - ubuntu-latest - - macos-latest - - ubuntu-18.04 - - ubuntu-20.04 - - ubuntu-22.04 - - macos-10.15 - - macos-11 - - macos-12 - - windows-2019 - - windows-2022 - -env: - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: short - -jobs: - release: - runs-on: ${{ github.event.inputs.os }} - if: startsWith(github.repository, 'zzzgydi') - steps: - - name: System Version - run: | - echo ${{ github.event.inputs.os }} - - - name: Checkout repository - uses: actions/checkout@v4 - - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - with: - workspaces: src-tauri - - - name: Install Node - uses: actions/setup-node@v4 - with: - node-version: "16" - cache: "yarn" - - - name: Install Dependencies (ubuntu only) - if: startsWith(github.event.inputs.os, 'ubuntu-') - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - - - name: Yarn install and check - run: | - yarn install --network-timeout 1000000 --frozen-lockfile - yarn run check - - - name: Tauri build - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - with: - tagName: alpha - releaseName: "Clash Verge Alpha" - releaseBody: "Alpha Version (include debug)" - releaseDraft: false - includeUpdaterJson: false diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml deleted file mode 100644 index 7c21078..0000000 --- a/.github/workflows/updater.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Updater CI - -on: workflow_dispatch - -jobs: - release-update: - runs-on: ubuntu-latest - if: startsWith(github.repository, 'zzzgydi') - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install Node - uses: actions/setup-node@v4 - with: - node-version: "16" - cache: "yarn" - - - name: Yarn install - run: yarn install --network-timeout 1000000 --frozen-lockfile - - - name: Release updater file - run: yarn run updater - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index c9e2fb9..0000000 --- a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -.DS_Store -dist -dist-ssr -*.local -update.json -scripts/_env.sh -.vscode diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index f3a6796..0000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -yarn pretty-quick --staged diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md index d78bc47..4c3e5e5 100644 --- a/README.md +++ b/README.md @@ -1,158 +1 @@ -

- Clash -
- Clash Verge -
-

- -

-A Clash GUI based on tauri. -

- -## Features - -- Full `clash` config supported, Partial `clash premium` config supported. -- Profiles management and enhancement (by yaml and Javascript). [Doc](https://github.com/zzzgydi/clash-verge/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97) -- Simple UI and supports custom theme color. -- Built-in support [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta) core. -- System proxy setting and guard. - -## Promotion - -[狗狗加速 —— 技术流机场 Doggygo VPN](https://dg1.top) - -- High-performance overseas VPN, free trial, discounted packages, unlock streaming media, the world's first to support Hysteria protocol. -- 高性能海外机场,免费试用,优惠套餐,解锁流媒体,全球首家支持 Hysteria 协议。 -- 使用 Clash Verge 专属邀请链接注册送 15 天,每天 1G 流量免费试用:https://panel.dg1.top/#/register?code=sFCDayZf - -
-Promotion Detail - -- Clash Verge 专属 8 折优惠码: verge20 (仅有 500 份) -- 优惠套餐每月仅需 15.8 元,160G 流量,年付 8 折 -- 海外团队,无跑路风险,高达 50% 返佣 -- 集群负载均衡设计,高速专线(兼容老客户端),极低延迟,无视晚高峰,4K 秒开 -- 全球首家 Hysteria 协议机场,将在今年 10 月上线更快的 `tuic` 协议(Clash Verge 客户端最佳搭配) -- 解锁流媒体及 ChatGPT -- 官网:https://dg1.top - -
- -
- -[EEVPN —— 海外运营机场 ※ 支持 ChatGPT](https://www.eejsq.net/#/register?code=yRr6qBO3) - -- 年付低至 9.99 元,价格低,速度不减 - -
-Promotion Detail - -- 中国大陆 BGP 网络接入 -- IEPL 专线网络 -- 最高 2500Mbps 速率可用 -- 不限制在线客户端 -- 解锁流媒体及 ChatGPT -- 海外运营 数据安全 - -
- -## Install - -Download from [release](https://github.com/zzzgydi/clash-verge/releases). Supports Windows x64, Linux x86_64 and macOS 11+ - -- [Windows x64](https://github.com/zzzgydi/clash-verge/releases/download/v1.3.8/Clash.Verge_1.3.8_x64_en-US.msi) -- [macOS intel](https://github.com/zzzgydi/clash-verge/releases/download/v1.3.8/Clash.Verge_1.3.8_x64.dmg) -- [macOS arm](https://github.com/zzzgydi/clash-verge/releases/download/v1.3.8/Clash.Verge_1.3.8_aarch64.dmg) -- [Linux AppImage](https://github.com/zzzgydi/clash-verge/releases/download/v1.3.8/clash-verge_1.3.8_amd64.AppImage) -- [Linux deb](https://github.com/zzzgydi/clash-verge/releases/download/v1.3.8/clash-verge_1.3.8_amd64.deb) -- [Fedora Linux](https://github.com/zzzgydi/clash-verge/issues/352) - -Or you can build it yourself. Supports Windows, Linux and macOS 10.15+ - -Notes: If you could not start the app on Windows, please check that you have [Webview2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section) installed. - -### FAQ - -#### 1. **macOS** "Clash Verge" is damaged and can't be opened - -open the terminal and run `sudo xattr -r -d com.apple.quarantine /Applications/Clash\ Verge.app` - -## Development - -You should install Rust and Nodejs, see [here](https://tauri.app/v1/guides/getting-started/prerequisites) for more details. Then install Nodejs packages. - -```shell -yarn install -``` - -Then download the clash binary... Or you can download it from [clash premium release](https://github.com/Dreamacro/clash/releases/tag/premium) and rename it according to [tauri config](https://tauri.studio/docs/api/config/#tauri.bundle.externalBin). - -```shell -# force update to latest version -# yarn run check --force - -yarn run check -``` - -Then run - -```shell -yarn dev - -# run it in another way if app instance exists -yarn dev:diff -``` - -Or you can build it - -```shell -yarn build -``` - -## Todos - -> This keng is a little big... - -## Screenshots - -
- demo1 - demo2 - demo3 - demo4 - demo5 - demo6 -
- -### Custom Theme - -
- demo1 - demo2 - demo3 - demo4 - demo5 - demo6 -
- -## Disclaimer - -This is a learning project for Rust practice. - -## Contributions - -Issue and PR welcome! - -## Acknowledgement - -Clash Verge was based on or inspired by these projects and so on: - -- [tauri-apps/tauri](https://github.com/tauri-apps/tauri): Build smaller, faster, and more secure desktop applications with a web frontend. -- [Dreamacro/clash](https://github.com/Dreamacro/clash): A rule-based tunnel in Go. -- [MetaCubeX/Clash.Meta](https://github.com/MetaCubeX/Clash.Meta): A rule-based tunnel in Go. -- [Fndroid/clash_for_windows_pkg](https://github.com/Fndroid/clash_for_windows_pkg): A Windows/macOS GUI based on Clash. -- [vitejs/vite](https://github.com/vitejs/vite): Next generation frontend tooling. It's fast! - -## License - -GPL-3.0 License. See [License here](./LICENSE) for details. +Removed diff --git a/UPDATELOG.md b/UPDATELOG.md deleted file mode 100644 index a08a86e..0000000 --- a/UPDATELOG.md +++ /dev/null @@ -1,472 +0,0 @@ -## v1.3.8 - -### Features - -- update clash meta core -- add default valid keys -- adjust the delay display interval and color - -### Bug Fixes - -- fix connections page undefined exception - ---- - -## v1.3.7 - -### Features - -- update clash and clash meta core -- profiles page add paste button -- subscriptions url textfield use multi lines -- set min window size -- add check for updates buttons -- add open dashboard to the hotkey list - -### Bug Fixes - -- fix profiles page undefined exception - ---- - -## v1.3.6 - -### Features - -- add russian translation -- support to show connection detail -- support clash meta memory usage display -- support proxy provider update ui -- update geo data file from meta repo -- adjust setting page - -### Bug Fixes - -- center the window when it is out of screen -- use `sudo` when `pkexec` not found (Linux) -- reconnect websocket when window focus - -### Notes - -- The current version of the Linux installation package is built by Ubuntu 20.04 (Github Action). - ---- - -## v1.3.5 - -### Features - -- update clash core - -### Bug Fixes - -- fix blurry system tray icon (Windows) -- fix v1.3.4 wintun.dll not found (Windows) -- fix v1.3.4 clash core not found (macOS, Linux) - ---- - -## v1.3.4 - -### Features - -- update clash and clash meta core -- optimize traffic graph high CPU usage when window hidden -- use polkit to elevate permission (Linux) -- support app log level setting -- support copy environment variable -- overwrite resource file according to file modified -- save window size and position - -### Bug Fixes - -- remove fallback group select status -- enable context menu on editable element (Windows) - ---- - -## v1.3.3 - -### Features - -- update clash and clash meta core -- show tray icon variants in different system proxy status (Windows) -- close all connections when mode changed - -### Bug Fixes - -- encode controller secret into uri -- error boundary for each page - ---- - -## v1.3.2 - -### Features - -- update clash and clash meta core - -### Bug Fixes - -- fix import url issue -- fix profile undefined issue - ---- - -## v1.3.1 - -### Features - -- update clash and clash meta core - -### Bug Fixes - -- fix open url issue -- fix appimage path panic -- fix grant root permission in macOS -- fix linux system proxy default bypass - ---- - -## v1.3.0 - -### Features - -- update clash and clash meta -- support opening dir on tray -- support updating all profiles with one click -- support granting root permission to clash core(Linux, macOS) -- support enable/disable clash fields filter, feel free to experience the latest features of Clash Meta - -### Bug Fixes - -- deb add openssl depend(Linux) -- fix the AppImage auto launch path(Linux) -- fix get the default network service(macOS) -- remove the esc key listener in macOS, cmd+w instead(macOS) -- fix infinite retry when websocket error - ---- - -## v1.2.3 - -### Features - -- update clash -- adjust macOS window style -- profile supports UTF8 with BOM - -### Bug Fixes - -- fix selected proxy -- fix error log - ---- - -## v1.2.2 - -### Features - -- update clash meta -- recover clash core after panic -- use system window decorations(Linux) - -### Bug Fixes - -- flush system proxy settings(Windows) -- fix parse log panic -- fix ui bug - ---- - -## v1.2.1 - -### Features - -- update clash version -- proxy groups support multi columns -- optimize ui - -### Bug Fixes - -- fix ui websocket connection -- adjust delay check concurrency -- avoid setting login item repeatedly(macOS) - ---- - -## v1.2.0 - -### Features - -- update clash meta version -- support to change external-controller -- support to change default latency test URL -- close all connections when proxy changed or profile changed -- check the config by using the core -- increase the robustness of the program -- optimize windows service mode (need to reinstall) -- optimize ui - -### Bug Fixes - -- invalid hotkey cause panic -- invalid theme setting cause panic -- fix some other glitches - ---- - -## v1.1.2 - -### Features - -- the system tray follows i18n -- change the proxy group ui of global mode -- support to update profile with the system proxy/clash proxy -- check the remote profile more strictly - -### Bug Fixes - -- use app version as default user agent -- the clash not exit in service mode -- reset the system proxy when quit the app -- fix some other glitches - ---- - -## v1.1.1 - -### Features - -- optimize clash config feedback -- hide macOS dock icon -- use clash meta compatible version (Linux) - -### Bug Fixes - -- fix some other glitches - ---- - -## v1.1.0 - -### Features - -- add rule page -- supports proxy providers delay check -- add proxy delay check loading status -- supports hotkey/shortcut management -- supports displaying connections data in table layout(refer to yacd) - -### Bug Fixes - -- supports yaml merge key in clash config -- detect the network interface and set the system proxy(macOS) -- fix some other glitches - ---- - -## v1.0.6 - -### Features - -- update clash and clash.meta - -### Bug Fixes - -- only script profile display console -- automatic configuration update on demand at launch - ---- - -## v1.0.5 - -### Features - -- reimplement profile enhanced mode with quick-js -- optimize the runtime config generation process -- support web ui management -- support clash field management -- support viewing the runtime config -- adjust some pages style - -### Bug Fixes - -- fix silent start -- fix incorrectly reset system proxy on exit - ---- - -## v1.0.4 - -### Features - -- update clash core and clash meta version -- support switch clash mode on system tray -- theme mode support follows system - -### Bug Fixes - -- config load error on first use - ---- - -## v1.0.3 - -### Features - -- save some states such as URL test, filter, etc -- update clash core and clash-meta core -- new icon for macOS - ---- - -## v1.0.2 - -### Features - -- supports for switching clash core -- supports release UI processes -- supports script mode setting - -### Bug Fixes - -- fix service mode bug (Windows) - ---- - -## v1.0.1 - -### Features - -- adjust default theme settings -- reduce gpu usage of traffic graph when hidden -- supports more remote profile response header setting -- check remote profile data format when imported - -### Bug Fixes - -- service mode install and start issue (Windows) -- fix launch panic (Some Windows) - ---- - -## v1.0.0 - -### Features - -- update clash core -- optimize traffic graph animation -- supports interval update profiles -- supports service mode (Windows) - -### Bug Fixes - -- reset system proxy when exit from dock (macOS) -- adjust clash dns config process strategy - ---- - -## v0.0.29 - -### Features - -- sort proxy node -- custom proxy test url -- logs page filter -- connections page filter -- default user agent for subscription -- system tray add tun mode toggle -- enable to change the config dir (Windows only) - ---- - -## v0.0.28 - -### Features - -- enable to use clash config fields (UI) - -### Bug Fixes - -- remove the character -- fix some icon color - ---- - -## v0.0.27 - -### Features - -- supports custom theme color -- tun mode setting control the final config - -### Bug Fixes - -- fix transition flickers (macOS) -- reduce proxy page render - ---- - -## v0.0.26 - -### Features - -- silent start -- profile editor -- profile enhance mode supports more fields -- optimize profile enhance mode strategy - -### Bug Fixes - -- fix csp restriction on macOS -- window controllers on Linux - ---- - -## v0.0.25 - -### Features - -- update clash core version - -### Bug Fixes - -- app updater error -- display window controllers on Linux - -### Notes - -If you can't update the app properly, please consider downloading the latest version from github release. - ---- - -## v0.0.24 - -### Features - -- Connections page -- add wintun.dll (Windows) -- supports create local profile with selected file (Windows) -- system tray enable set system proxy - -### Bug Fixes - -- open dir error -- auto launch path (Windows) -- fix some clash config error -- reduce the impact of the enhanced mode - ---- - -## v0.0.23 - -### Features - -- i18n supports -- Remote profile User Agent supports - -### Bug Fixes - -- clash config file case ignore -- clash `external-controller` only port diff --git a/docs/color1.png b/docs/color1.png deleted file mode 100644 index 9c24fb8..0000000 Binary files a/docs/color1.png and /dev/null differ diff --git a/docs/color2.png b/docs/color2.png deleted file mode 100644 index 8d6d935..0000000 Binary files a/docs/color2.png and /dev/null differ diff --git a/docs/color3.png b/docs/color3.png deleted file mode 100644 index 247b841..0000000 Binary files a/docs/color3.png and /dev/null differ diff --git a/docs/color4.png b/docs/color4.png deleted file mode 100644 index 3ecb750..0000000 Binary files a/docs/color4.png and /dev/null differ diff --git a/docs/color5.png b/docs/color5.png deleted file mode 100644 index 65e916a..0000000 Binary files a/docs/color5.png and /dev/null differ diff --git a/docs/color6.png b/docs/color6.png deleted file mode 100644 index 5067320..0000000 Binary files a/docs/color6.png and /dev/null differ diff --git a/docs/demo1.png b/docs/demo1.png deleted file mode 100644 index b18450f..0000000 Binary files a/docs/demo1.png and /dev/null differ diff --git a/docs/demo2.png b/docs/demo2.png deleted file mode 100644 index a2919b6..0000000 Binary files a/docs/demo2.png and /dev/null differ diff --git a/docs/demo3.png b/docs/demo3.png deleted file mode 100644 index 55267b5..0000000 Binary files a/docs/demo3.png and /dev/null differ diff --git a/docs/demo4.png b/docs/demo4.png deleted file mode 100644 index ef9b90a..0000000 Binary files a/docs/demo4.png and /dev/null differ diff --git a/docs/demo5.png b/docs/demo5.png deleted file mode 100644 index a7eac54..0000000 Binary files a/docs/demo5.png and /dev/null differ diff --git a/docs/demo6.png b/docs/demo6.png deleted file mode 100644 index fe53e2b..0000000 Binary files a/docs/demo6.png and /dev/null differ diff --git a/package.json b/package.json deleted file mode 100644 index 8249427..0000000 --- a/package.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "clash-verge", - "version": "1.3.8", - "license": "GPL-3.0", - "scripts": { - "dev": "tauri dev", - "dev:diff": "tauri dev -f verge-dev", - "build": "tauri build", - "tauri": "tauri", - "web:dev": "vite", - "web:build": "tsc && vite build", - "web:serve": "vite preview", - "aarch": "node scripts/aarch.mjs", - "check": "node scripts/check.mjs", - "updater": "node scripts/updater.mjs", - "publish": "node scripts/publish.mjs", - "portable": "node scripts/portable.mjs", - "prepare": "husky install" - }, - "dependencies": { - "@emotion/react": "^11.10.5", - "@emotion/styled": "^11.10.5", - "@juggle/resize-observer": "^3.4.0", - "@mui/icons-material": "^5.10.9", - "@mui/material": "^5.10.13", - "@mui/x-data-grid": "^5.17.11", - "@tauri-apps/api": "^1.3.0", - "ahooks": "^3.7.2", - "axios": "^1.1.3", - "dayjs": "1.11.5", - "i18next": "^22.0.4", - "lodash-es": "^4.17.21", - "monaco-editor": "^0.34.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-error-boundary": "^3.1.4", - "react-hook-form": "^7.39.5", - "react-i18next": "^12.0.0", - "react-router-dom": "^6.4.3", - "react-virtuoso": "^3.1.3", - "recoil": "^0.7.6", - "snarkdown": "^2.0.0", - "swr": "^1.3.0" - }, - "devDependencies": { - "@actions/github": "^5.0.3", - "@tauri-apps/cli": "^1.3.1", - "@types/fs-extra": "^9.0.13", - "@types/js-cookie": "^3.0.2", - "@types/lodash": "^4.14.180", - "@types/lodash-es": "^4.17.7", - "@types/react-dom": "^18.0.11", - "@vitejs/plugin-react": "^2.0.1", - "adm-zip": "^0.5.9", - "cross-env": "^7.0.3", - "fs-extra": "^10.0.0", - "https-proxy-agent": "^5.0.1", - "husky": "^7.0.0", - "node-fetch": "^3.2.6", - "prettier": "^2.7.1", - "pretty-quick": "^3.1.3", - "sass": "^1.54.0", - "typescript": "^4.7.4", - "vite": "^3.2.5", - "vite-plugin-monaco-editor": "^1.1.0", - "vite-plugin-svgr": "^2.2.1" - }, - "prettier": { - "tabWidth": 2, - "semi": true, - "singleQuote": false, - "endOfLine": "lf" - } -} diff --git a/scripts/aarch.mjs b/scripts/aarch.mjs deleted file mode 100644 index 989e774..0000000 --- a/scripts/aarch.mjs +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Build and upload assets - * for macOS(aarch) - */ -import fs from "fs-extra"; -import path from "path"; -import { exit } from "process"; -import { execSync } from "child_process"; -import { createRequire } from "module"; -import { getOctokit, context } from "@actions/github"; - -// to `meta` tag -const META = process.argv.includes("--meta"); -// to `alpha` tag -const ALPHA = process.argv.includes("--alpha"); - -const require = createRequire(import.meta.url); - -async function resolve() { - if (!process.env.GITHUB_TOKEN) { - throw new Error("GITHUB_TOKEN is required"); - } - if (!process.env.GITHUB_REPOSITORY) { - throw new Error("GITHUB_REPOSITORY is required"); - } - if (!process.env.TAURI_PRIVATE_KEY) { - throw new Error("TAURI_PRIVATE_KEY is required"); - } - if (!process.env.TAURI_KEY_PASSWORD) { - throw new Error("TAURI_KEY_PASSWORD is required"); - } - - const { version } = require("../package.json"); - - const tag = META ? "meta" : ALPHA ? "alpha" : `v${version}`; - const buildCmd = META ? `yarn build -f default-meta` : `yarn build`; - - console.log(`[INFO]: Upload to tag "${tag}"`); - console.log(`[INFO]: Building app. "${buildCmd}"`); - - execSync(buildCmd); - - const cwd = process.cwd(); - const bundlePath = path.join(cwd, "src-tauri/target/release/bundle"); - const join = (p) => path.join(bundlePath, p); - - const appPathList = [ - join("macos/Clash Verge.aarch64.app.tar.gz"), - join("macos/Clash Verge.aarch64.app.tar.gz.sig"), - ]; - - for (const appPath of appPathList) { - if (fs.pathExistsSync(appPath)) { - fs.removeSync(appPath); - } - } - - fs.copyFileSync(join("macos/Clash Verge.app.tar.gz"), appPathList[0]); - fs.copyFileSync(join("macos/Clash Verge.app.tar.gz.sig"), appPathList[1]); - - const options = { owner: context.repo.owner, repo: context.repo.repo }; - const github = getOctokit(process.env.GITHUB_TOKEN); - - const { data: release } = await github.rest.repos.getReleaseByTag({ - ...options, - tag, - }); - - if (!release.id) throw new Error("failed to find the release"); - - await uploadAssets(release.id, [ - join(`dmg/Clash Verge_${version}_aarch64.dmg`), - ...appPathList, - ]); -} - -// From tauri-apps/tauri-action -// https://github.com/tauri-apps/tauri-action/blob/dev/packages/action/src/upload-release-assets.ts -async function uploadAssets(releaseId, assets) { - const github = getOctokit(process.env.GITHUB_TOKEN); - - // Determine content-length for header to upload asset - const contentLength = (filePath) => fs.statSync(filePath).size; - - for (const assetPath of assets) { - const headers = { - "content-type": "application/zip", - "content-length": contentLength(assetPath), - }; - - const ext = path.extname(assetPath); - const filename = path.basename(assetPath).replace(ext, ""); - const assetName = path.dirname(assetPath).includes(`target${path.sep}debug`) - ? `${filename}-debug${ext}` - : `${filename}${ext}`; - - console.log(`[INFO]: Uploading ${assetName}...`); - - try { - await github.rest.repos.uploadReleaseAsset({ - headers, - name: assetName, - data: fs.readFileSync(assetPath), - owner: context.repo.owner, - repo: context.repo.repo, - release_id: releaseId, - }); - } catch (error) { - console.log(error.message); - } - } -} - -if (process.platform === "darwin" && process.arch === "arm64") { - resolve(); -} else { - console.error("invalid"); - exit(1); -} diff --git a/scripts/check.mjs b/scripts/check.mjs deleted file mode 100644 index 5b7aceb..0000000 --- a/scripts/check.mjs +++ /dev/null @@ -1,332 +0,0 @@ -import fs from "fs-extra"; -import zlib from "zlib"; -import path from "path"; -import AdmZip from "adm-zip"; -import fetch from "node-fetch"; -import proxyAgent from "https-proxy-agent"; -import { execSync } from "child_process"; - -const cwd = process.cwd(); -const TEMP_DIR = path.join(cwd, "node_modules/.verge"); -const FORCE = process.argv.includes("--force"); - -const SIDECAR_HOST = execSync("rustc -vV") - .toString() - .match(/(?<=host: ).+(?=\s*)/g)[0]; - -/* ======= clash ======= */ -const CLASH_STORAGE_PREFIX = "https://release.dreamacro.workers.dev/"; -const CLASH_URL_PREFIX = - "https://github.com/Dreamacro/clash/releases/download/premium/"; -const CLASH_LATEST_DATE = "2023.08.17"; - -const CLASH_MAP = { - "win32-x64": "clash-windows-amd64", - "darwin-x64": "clash-darwin-amd64", - "darwin-arm64": "clash-darwin-arm64", - "linux-x64": "clash-linux-amd64", - "linux-arm64": "clash-linux-arm64", -}; - -/* ======= clash meta ======= */ -const META_URL_PREFIX = `https://github.com/MetaCubeX/Clash.Meta/releases/download/`; -const META_VERSION = "v1.16.0"; - -const META_MAP = { - "win32-x64": "clash.meta-windows-amd64-compatible", - "darwin-x64": "clash.meta-darwin-amd64", - "darwin-arm64": "clash.meta-darwin-arm64", - "linux-x64": "clash.meta-linux-amd64-compatible", - "linux-arm64": "clash.meta-linux-arm64", -}; - -/** - * check available - */ - -const { platform, arch } = process; -if (!CLASH_MAP[`${platform}-${arch}`]) { - throw new Error(`clash unsupported platform "${platform}-${arch}"`); -} -if (!META_MAP[`${platform}-${arch}`]) { - throw new Error(`clash meta unsupported platform "${platform}-${arch}"`); -} - -function clash() { - const name = CLASH_MAP[`${platform}-${arch}`]; - - const isWin = platform === "win32"; - const urlExt = isWin ? "zip" : "gz"; - const downloadURL = `${CLASH_URL_PREFIX}${name}-${CLASH_LATEST_DATE}.${urlExt}`; - const exeFile = `${name}${isWin ? ".exe" : ""}`; - const zipFile = `${name}.${urlExt}`; - - return { - name: "clash", - targetFile: `clash-${SIDECAR_HOST}${isWin ? ".exe" : ""}`, - exeFile, - zipFile, - downloadURL, - }; -} - -function clashS3() { - const name = CLASH_MAP[`${platform}-${arch}`]; - - const isWin = platform === "win32"; - const urlExt = isWin ? "zip" : "gz"; - const downloadURL = `${CLASH_STORAGE_PREFIX}${CLASH_LATEST_DATE}/${name}-${CLASH_LATEST_DATE}.${urlExt}`; - const exeFile = `${name}${isWin ? ".exe" : ""}`; - const zipFile = `${name}.${urlExt}`; - - return { - name: "clash", - targetFile: `clash-${SIDECAR_HOST}${isWin ? ".exe" : ""}`, - exeFile, - zipFile, - downloadURL, - }; -} - -function clashMeta() { - const name = META_MAP[`${platform}-${arch}`]; - const isWin = platform === "win32"; - const urlExt = isWin ? "zip" : "gz"; - const downloadURL = `${META_URL_PREFIX}${META_VERSION}/${name}-${META_VERSION}.${urlExt}`; - const exeFile = `${name}${isWin ? ".exe" : ""}`; - const zipFile = `${name}-${META_VERSION}.${urlExt}`; - - return { - name: "clash-meta", - targetFile: `clash-meta-${SIDECAR_HOST}${isWin ? ".exe" : ""}`, - exeFile, - zipFile, - downloadURL, - }; -} - -/** - * download sidecar and rename - */ -async function resolveSidecar(binInfo) { - const { name, targetFile, zipFile, exeFile, downloadURL } = binInfo; - - const sidecarDir = path.join(cwd, "src-tauri", "sidecar"); - const sidecarPath = path.join(sidecarDir, targetFile); - - await fs.mkdirp(sidecarDir); - if (!FORCE && (await fs.pathExists(sidecarPath))) return; - - const tempDir = path.join(TEMP_DIR, name); - const tempZip = path.join(tempDir, zipFile); - const tempExe = path.join(tempDir, exeFile); - - await fs.mkdirp(tempDir); - try { - if (!(await fs.pathExists(tempZip))) { - await downloadFile(downloadURL, tempZip); - } - - if (zipFile.endsWith(".zip")) { - const zip = new AdmZip(tempZip); - zip.getEntries().forEach((entry) => { - console.log(`[DEBUG]: "${name}" entry name`, entry.entryName); - }); - zip.extractAllTo(tempDir, true); - await fs.rename(tempExe, sidecarPath); - console.log(`[INFO]: "${name}" unzip finished`); - } else { - // gz - const readStream = fs.createReadStream(tempZip); - const writeStream = fs.createWriteStream(sidecarPath); - await new Promise((resolve, reject) => { - const onError = (error) => { - console.error(`[ERROR]: "${name}" gz failed:`, error.message); - reject(error); - }; - readStream - .pipe(zlib.createGunzip().on("error", onError)) - .pipe(writeStream) - .on("finish", () => { - console.log(`[INFO]: "${name}" gunzip finished`); - execSync(`chmod 755 ${sidecarPath}`); - console.log(`[INFO]: "${name}" chmod binary finished`); - resolve(); - }) - .on("error", onError); - }); - } - } catch (err) { - // 需要删除文件 - await fs.remove(sidecarPath); - throw err; - } finally { - // delete temp dir - await fs.remove(tempDir); - } -} - -/** - * prepare clash core - * if the core version is not updated in time, use S3 storage as a backup. - */ -async function resolveClash() { - try { - return await resolveSidecar(clash()); - } catch { - console.log(`[WARN]: clash core needs to be updated`); - return await resolveSidecar(clashS3()); - } -} - -/** - * only Windows - * get the wintun.dll (not required) - */ -async function resolveWintun() { - const { platform } = process; - - if (platform !== "win32") return; - - const url = "https://www.wintun.net/builds/wintun-0.14.1.zip"; - - const tempDir = path.join(TEMP_DIR, "wintun"); - const tempZip = path.join(tempDir, "wintun.zip"); - - const wintunPath = path.join(tempDir, "wintun/bin/amd64/wintun.dll"); - const targetPath = path.join(cwd, "src-tauri/resources", "wintun.dll"); - - if (!FORCE && (await fs.pathExists(targetPath))) return; - - await fs.mkdirp(tempDir); - - if (!(await fs.pathExists(tempZip))) { - await downloadFile(url, tempZip); - } - - // unzip - const zip = new AdmZip(tempZip); - zip.extractAllTo(tempDir, true); - - if (!(await fs.pathExists(wintunPath))) { - throw new Error(`path not found "${wintunPath}"`); - } - - await fs.rename(wintunPath, targetPath); - await fs.remove(tempDir); - - console.log(`[INFO]: resolve wintun.dll finished`); -} - -/** - * download the file to the resources dir - */ -async function resolveResource(binInfo) { - const { file, downloadURL } = binInfo; - - const resDir = path.join(cwd, "src-tauri/resources"); - const targetPath = path.join(resDir, file); - - if (!FORCE && (await fs.pathExists(targetPath))) return; - - await fs.mkdirp(resDir); - await downloadFile(downloadURL, targetPath); - - console.log(`[INFO]: ${file} finished`); -} - -/** - * download file and save to `path` - */ -async function downloadFile(url, path) { - const options = {}; - - const httpProxy = - process.env.HTTP_PROXY || - process.env.http_proxy || - process.env.HTTPS_PROXY || - process.env.https_proxy; - - if (httpProxy) { - options.agent = proxyAgent(httpProxy); - } - - const response = await fetch(url, { - ...options, - method: "GET", - headers: { "Content-Type": "application/octet-stream" }, - }); - const buffer = await response.arrayBuffer(); - await fs.writeFile(path, new Uint8Array(buffer)); - - console.log(`[INFO]: download finished "${url}"`); -} - -/** - * main - */ -const SERVICE_URL = - "https://github.com/zzzgydi/clash-verge-service/releases/download/latest"; - -const resolveService = () => - resolveResource({ - file: "clash-verge-service.exe", - downloadURL: `${SERVICE_URL}/clash-verge-service.exe`, - }); -const resolveInstall = () => - resolveResource({ - file: "install-service.exe", - downloadURL: `${SERVICE_URL}/install-service.exe`, - }); -const resolveUninstall = () => - resolveResource({ - file: "uninstall-service.exe", - downloadURL: `${SERVICE_URL}/uninstall-service.exe`, - }); -const resolveMmdb = () => - resolveResource({ - file: "Country.mmdb", - downloadURL: `https://github.com/Dreamacro/maxmind-geoip/releases/download/20230812/Country.mmdb`, - }); -const resolveGeosite = () => - resolveResource({ - file: "geosite.dat", - downloadURL: `https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat`, - }); -const resolveGeoIP = () => - resolveResource({ - file: "geoip.dat", - downloadURL: `https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat`, - }); - -const tasks = [ - { name: "clash", func: resolveClash, retry: 5 }, - { name: "clash-meta", func: () => resolveSidecar(clashMeta()), retry: 5 }, - { name: "wintun", func: resolveWintun, retry: 5, winOnly: true }, - { name: "service", func: resolveService, retry: 5, winOnly: true }, - { name: "install", func: resolveInstall, retry: 5, winOnly: true }, - { name: "uninstall", func: resolveUninstall, retry: 5, winOnly: true }, - { name: "mmdb", func: resolveMmdb, retry: 5 }, - { name: "geosite", func: resolveGeosite, retry: 5 }, - { name: "geoip", func: resolveGeoIP, retry: 5 }, -]; - -async function runTask() { - const task = tasks.shift(); - if (!task) return; - if (task.winOnly && process.platform !== "win32") return runTask(); - - for (let i = 0; i < task.retry; i++) { - try { - await task.func(); - break; - } catch (err) { - console.error(`[ERROR]: task::${task.name} try ${i} ==`, err.message); - if (i === task.retry - 1) throw err; - } - } - return runTask(); -} - -runTask(); -runTask(); diff --git a/scripts/portable.mjs b/scripts/portable.mjs deleted file mode 100644 index b523a50..0000000 --- a/scripts/portable.mjs +++ /dev/null @@ -1,59 +0,0 @@ -import fs from "fs-extra"; -import path from "path"; -import AdmZip from "adm-zip"; -import { createRequire } from "module"; -import { getOctokit, context } from "@actions/github"; - -/// Script for ci -/// 打包绿色版/便携版 (only Windows) -async function resolvePortable() { - if (process.platform !== "win32") return; - - const releaseDir = "./src-tauri/target/release"; - - if (!(await fs.pathExists(releaseDir))) { - throw new Error("could not found the release dir"); - } - - const zip = new AdmZip(); - - zip.addLocalFile(path.join(releaseDir, "Clash Verge.exe")); - zip.addLocalFile(path.join(releaseDir, "clash.exe")); - zip.addLocalFile(path.join(releaseDir, "clash-meta.exe")); - zip.addLocalFolder(path.join(releaseDir, "resources"), "resources"); - - const require = createRequire(import.meta.url); - const packageJson = require("../package.json"); - const { version } = packageJson; - - const zipFile = `Clash.Verge_${version}_x64_portable.zip`; - zip.writeZip(zipFile); - - console.log("[INFO]: create portable zip successfully"); - - // push release assets - if (process.env.GITHUB_TOKEN === undefined) { - throw new Error("GITHUB_TOKEN is required"); - } - - const options = { owner: context.repo.owner, repo: context.repo.repo }; - const github = getOctokit(process.env.GITHUB_TOKEN); - - console.log("[INFO]: upload to ", process.env.TAG_NAME || `v${version}`); - - const { data: release } = await github.rest.repos.getReleaseByTag({ - ...options, - tag: process.env.TAG_NAME || `v${version}`, - }); - - console.log(release.name); - - await github.rest.repos.uploadReleaseAsset({ - ...options, - release_id: release.id, - name: zipFile, - data: zip.toBuffer(), - }); -} - -resolvePortable().catch(console.error); diff --git a/scripts/publish.mjs b/scripts/publish.mjs deleted file mode 100644 index 523ad18..0000000 --- a/scripts/publish.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import fs from "fs-extra"; -import { createRequire } from "module"; -import { execSync } from "child_process"; -import { resolveUpdateLog } from "./updatelog.mjs"; - -const require = createRequire(import.meta.url); - -// publish -async function resolvePublish() { - const flag = process.argv[2] ?? "patch"; - const packageJson = require("../package.json"); - const tauriJson = require("../src-tauri/tauri.conf.json"); - - let [a, b, c] = packageJson.version.split(".").map(Number); - - if (flag === "major") { - a += 1; - b = 0; - c = 0; - } else if (flag === "minor") { - b += 1; - c = 0; - } else if (flag === "patch") { - c += 1; - } else throw new Error(`invalid flag "${flag}"`); - - const nextVersion = `${a}.${b}.${c}`; - packageJson.version = nextVersion; - tauriJson.package.version = nextVersion; - - // 发布更新前先写更新日志 - const nextTag = `v${nextVersion}`; - await resolveUpdateLog(nextTag); - - await fs.writeFile( - "./package.json", - JSON.stringify(packageJson, undefined, 2) - ); - await fs.writeFile( - "./src-tauri/tauri.conf.json", - JSON.stringify(tauriJson, undefined, 2) - ); - - execSync("git add ./package.json"); - execSync("git add ./src-tauri/tauri.conf.json"); - execSync(`git commit -m "v${nextVersion}"`); - execSync(`git tag -a v${nextVersion} -m "v${nextVersion}"`); - execSync(`git push`); - execSync(`git push origin v${nextVersion}`); - console.log(`Publish Successfully...`); -} - -resolvePublish(); diff --git a/scripts/updatelog.mjs b/scripts/updatelog.mjs deleted file mode 100644 index fae7f62..0000000 --- a/scripts/updatelog.mjs +++ /dev/null @@ -1,44 +0,0 @@ -import fs from "fs-extra"; -import path from "path"; - -const UPDATE_LOG = "UPDATELOG.md"; - -// parse the UPDATELOG.md -export async function resolveUpdateLog(tag) { - const cwd = process.cwd(); - - const reTitle = /^## v[\d\.]+/; - const reEnd = /^---/; - - const file = path.join(cwd, UPDATE_LOG); - - if (!(await fs.pathExists(file))) { - throw new Error("could not found UPDATELOG.md"); - } - - const data = await fs.readFile(file).then((d) => d.toString("utf8")); - - const map = {}; - let p = ""; - - data.split("\n").forEach((line) => { - if (reTitle.test(line)) { - p = line.slice(3).trim(); - if (!map[p]) { - map[p] = []; - } else { - throw new Error(`Tag ${p} dup`); - } - } else if (reEnd.test(line)) { - p = ""; - } else if (p) { - map[p].push(line); - } - }); - - if (!map[tag]) { - throw new Error(`could not found "${tag}" in UPDATELOG.md`); - } - - return map[tag].join("\n").trim(); -} diff --git a/scripts/updater.mjs b/scripts/updater.mjs deleted file mode 100644 index 2a3a8ee..0000000 --- a/scripts/updater.mjs +++ /dev/null @@ -1,177 +0,0 @@ -import fetch from "node-fetch"; -import { getOctokit, context } from "@actions/github"; -import { resolveUpdateLog } from "./updatelog.mjs"; - -const UPDATE_TAG_NAME = "updater"; -const UPDATE_JSON_FILE = "update.json"; -const UPDATE_JSON_PROXY = "update-proxy.json"; - -/// generate update.json -/// upload to update tag's release asset -async function resolveUpdater() { - if (process.env.GITHUB_TOKEN === undefined) { - throw new Error("GITHUB_TOKEN is required"); - } - - const options = { owner: context.repo.owner, repo: context.repo.repo }; - const github = getOctokit(process.env.GITHUB_TOKEN); - - const { data: tags } = await github.rest.repos.listTags({ - ...options, - per_page: 10, - page: 1, - }); - - // get the latest publish tag - const tag = tags.find((t) => t.name.startsWith("v")); - - console.log(tag); - console.log(); - - const { data: latestRelease } = await github.rest.repos.getReleaseByTag({ - ...options, - tag: tag.name, - }); - - const updateData = { - name: tag.name, - notes: await resolveUpdateLog(tag.name), // use updatelog.md - pub_date: new Date().toISOString(), - platforms: { - win64: { signature: "", url: "" }, // compatible with older formats - linux: { signature: "", url: "" }, // compatible with older formats - darwin: { signature: "", url: "" }, // compatible with older formats - "darwin-aarch64": { signature: "", url: "" }, - "darwin-intel": { signature: "", url: "" }, - "darwin-x86_64": { signature: "", url: "" }, - "linux-x86_64": { signature: "", url: "" }, - "windows-x86_64": { signature: "", url: "" }, - "windows-i686": { signature: "", url: "" }, // no supported - }, - }; - - const promises = latestRelease.assets.map(async (asset) => { - const { name, browser_download_url } = asset; - - // win64 url - if (name.endsWith(".msi.zip") && name.includes("en-US")) { - updateData.platforms.win64.url = browser_download_url; - updateData.platforms["windows-x86_64"].url = browser_download_url; - } - // win64 signature - if (name.endsWith(".msi.zip.sig") && name.includes("en-US")) { - const sig = await getSignature(browser_download_url); - updateData.platforms.win64.signature = sig; - updateData.platforms["windows-x86_64"].signature = sig; - } - - // darwin url (intel) - if (name.endsWith(".app.tar.gz") && !name.includes("aarch")) { - updateData.platforms.darwin.url = browser_download_url; - updateData.platforms["darwin-intel"].url = browser_download_url; - updateData.platforms["darwin-x86_64"].url = browser_download_url; - } - // darwin signature (intel) - if (name.endsWith(".app.tar.gz.sig") && !name.includes("aarch")) { - const sig = await getSignature(browser_download_url); - updateData.platforms.darwin.signature = sig; - updateData.platforms["darwin-intel"].signature = sig; - updateData.platforms["darwin-x86_64"].signature = sig; - } - - // darwin url (aarch) - if (name.endsWith("aarch64.app.tar.gz")) { - updateData.platforms["darwin-aarch64"].url = browser_download_url; - } - // darwin signature (aarch) - if (name.endsWith("aarch64.app.tar.gz.sig")) { - const sig = await getSignature(browser_download_url); - updateData.platforms["darwin-aarch64"].signature = sig; - } - - // linux url - if (name.endsWith(".AppImage.tar.gz")) { - updateData.platforms.linux.url = browser_download_url; - updateData.platforms["linux-x86_64"].url = browser_download_url; - } - // linux signature - if (name.endsWith(".AppImage.tar.gz.sig")) { - const sig = await getSignature(browser_download_url); - updateData.platforms.linux.signature = sig; - updateData.platforms["linux-x86_64"].signature = sig; - } - }); - - await Promise.allSettled(promises); - console.log(updateData); - - // maybe should test the signature as well - // delete the null field - Object.entries(updateData.platforms).forEach(([key, value]) => { - if (!value.url) { - console.log(`[Error]: failed to parse release for "${key}"`); - delete updateData.platforms[key]; - } - }); - - // 生成一个代理github的更新文件 - // 使用 https://hub.fastgit.xyz/ 做github资源的加速 - const updateDataNew = JSON.parse(JSON.stringify(updateData)); - - Object.entries(updateDataNew.platforms).forEach(([key, value]) => { - if (value.url) { - updateDataNew.platforms[key].url = "https://ghproxy.com/" + value.url; - } else { - console.log(`[Error]: updateDataNew.platforms.${key} is null`); - } - }); - - // update the update.json - const { data: updateRelease } = await github.rest.repos.getReleaseByTag({ - ...options, - tag: UPDATE_TAG_NAME, - }); - - // delete the old assets - for (let asset of updateRelease.assets) { - if (asset.name === UPDATE_JSON_FILE) { - await github.rest.repos.deleteReleaseAsset({ - ...options, - asset_id: asset.id, - }); - } - - if (asset.name === UPDATE_JSON_PROXY) { - await github.rest.repos - .deleteReleaseAsset({ ...options, asset_id: asset.id }) - .catch(console.error); // do not break the pipeline - } - } - - // upload new assets - await github.rest.repos.uploadReleaseAsset({ - ...options, - release_id: updateRelease.id, - name: UPDATE_JSON_FILE, - data: JSON.stringify(updateData, null, 2), - }); - - await github.rest.repos.uploadReleaseAsset({ - ...options, - release_id: updateRelease.id, - name: UPDATE_JSON_PROXY, - data: JSON.stringify(updateDataNew, null, 2), - }); -} - -// get the signature file content -async function getSignature(url) { - const response = await fetch(url, { - method: "GET", - headers: { "Content-Type": "application/octet-stream" }, - }); - - return response.text(); -} - -resolveUpdater().catch(console.error); diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore deleted file mode 100644 index 7b128ff..0000000 --- a/src-tauri/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -/target/ -WixTools -resources -sidecar diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock deleted file mode 100644 index 9b1c0ec..0000000 --- a/src-tauri/Cargo.lock +++ /dev/null @@ -1,5658 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.9", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" - -[[package]] -name = "arc-swap" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" - -[[package]] -name = "async-channel" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-fs" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" -dependencies = [ - "async-lock", - "autocfg", - "blocking", - "futures-lite", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log 0.4.17", - "parking", - "polling", - "rustix", - "slab", - "socket2", - "waker-fn", -] - -[[package]] -name = "async-lock" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-net" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" -dependencies = [ - "async-io", - "autocfg", - "blocking", - "futures-lite", -] - -[[package]] -name = "async-process" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" -dependencies = [ - "async-io", - "async-lock", - "autocfg", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "signal-hook 0.3.15", - "windows-sys 0.48.0", -] - -[[package]] -name = "async-task" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" - -[[package]] -name = "async-trait" -version = "0.1.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "atk" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" -dependencies = [ - "atk-sys", - "bitflags", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.1.0", -] - -[[package]] -name = "atomic-waker" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" - -[[package]] -name = "attohttpc" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcf00bc6d5abb29b5f97e3c61a90b6d3caa12f3faf897d4a3e3607c050a35a7" -dependencies = [ - "flate2", - "http", - "log 0.4.17", - "native-tls", - "serde", - "serde_json", - "serde_urlencoded", - "url", -] - -[[package]] -name = "auto-launch" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f012b8cc0c850f34117ec8252a44418f2e34a2cf501de89e29b241ae5f79471" -dependencies = [ - "dirs 4.0.0", - "thiserror", - "winreg 0.10.1", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blocking" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "log 0.4.17", -] - -[[package]] -name = "brotli" -version = "3.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bstr" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bytemuck" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" -dependencies = [ - "serde", -] - -[[package]] -name = "cairo-rs" -version = "0.15.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" -dependencies = [ - "bitflags", - "cairo-sys-rs", - "glib", - "libc", - "thiserror", -] - -[[package]] -name = "cairo-sys-rs" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" -dependencies = [ - "glib-sys", - "libc", - "system-deps 6.1.0", -] - -[[package]] -name = "cargo_toml" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497049e9477329f8f6a559972ee42e117487d01d1e8c2cc9f836ea6fa23a9e1a" -dependencies = [ - "serde", - "toml 0.5.11", -] - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfb" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" -dependencies = [ - "byteorder", - "fnv", - "uuid", -] - -[[package]] -name = "cfg-expr" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" -dependencies = [ - "smallvec", -] - -[[package]] -name = "cfg-expr" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8790cf1286da485c72cf5fc7aeba308438800036ec67d89425924c4807268c9" -dependencies = [ - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-integer", - "num-traits", - "serde", - "time 0.1.45", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "clash-verge" -version = "0.1.0" -dependencies = [ - "anyhow", - "auto-launch", - "chrono", - "ctrlc", - "deelevate", - "delay_timer", - "dirs 5.0.1", - "dunce", - "log 0.4.17", - "log4rs", - "nanoid", - "once_cell", - "open 4.1.0", - "parking_lot", - "port_scanner", - "reqwest", - "rquickjs", - "runas", - "serde", - "serde_json", - "serde_yaml 0.9.21", - "sysinfo", - "sysproxy", - "tauri", - "tauri-build", - "tokio", - "warp", - "which", - "window-shadows", - "window-vibrancy", - "windows-sys 0.48.0", - "winreg 0.50.0", - "wry", -] - -[[package]] -name = "cocoa" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation", - "core-graphics", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" -dependencies = [ - "bitflags", - "block", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "combine" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "concat-idents" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fe0e1d9f7de897d18e590a7496b5facbe87813f746cf4b8db596ba77e07e832" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "concurrent-queue" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation", - "foreign-types", - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "cron_clock" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8699d8ed16e3db689f8ae04d8dc3c6666a4ba7e724e5a157884b7cc385d16b" -dependencies = [ - "chrono", - "nom 7.1.3", - "once_cell", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset 0.8.0", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "cssparser" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa 0.4.8", - "matches", - "phf 0.8.0", - "proc-macro2", - "quote", - "smallvec", - "syn 1.0.109", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ctrlc" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7394a21d012ce5c850497fb774b167d81b99f060025fbf06ee92b9848bd97eb2" -dependencies = [ - "nix 0.26.2", - "windows-sys 0.48.0", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "darling" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.18", -] - -[[package]] -name = "darling_macro" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "dashmap" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" -dependencies = [ - "cfg-if", - "num_cpus", -] - -[[package]] -name = "deelevate" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7397f8c48906dd9b5afc75001368c979418e5dff5575998a831eb2319b424e" -dependencies = [ - "lazy_static 1.4.0", - "pathsearch", - "rand 0.8.5", - "shared_library", - "termwiz", - "winapi", -] - -[[package]] -name = "delay_timer" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e3040b73d9397711697558109c983a2dc6fc63e98785ffbefd3ece57b46b67" -dependencies = [ - "anyhow", - "async-trait", - "autocfg", - "concat-idents", - "cron_clock", - "dashmap", - "event-listener", - "futures", - "log 0.4.17", - "lru", - "once_cell", - "rs-snowflake", - "rustc_version 0.2.3", - "smol", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 1.0.109", -] - -[[package]] -name = "destructure_traitobject" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "crypto-common", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dtoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" - -[[package]] -name = "dtoa-short" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" -dependencies = [ - "dtoa", -] - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "either" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - -[[package]] -name = "embed_plist" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" - -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fdeflate" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "field-offset" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535" -dependencies = [ - "memoffset 0.8.0", - "rustc_version 0.4.0", -] - -[[package]] -name = "filedescriptor" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" -dependencies = [ - "libc", - "thiserror", - "winapi", -] - -[[package]] -name = "filetime" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", -] - -[[package]] -name = "flate2" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gdk" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" -dependencies = [ - "bitflags", - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.15.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" -dependencies = [ - "bitflags", - "gdk-pixbuf-sys", - "gio", - "glib", - "libc", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.1.0", -] - -[[package]] -name = "gdk-sys" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps 6.1.0", -] - -[[package]] -name = "gdkwayland-sys" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca49a59ad8cfdf36ef7330fe7bdfbe1d34323220cc16a0de2679ee773aee2c2" -dependencies = [ - "gdk-sys", - "glib-sys", - "gobject-sys", - "libc", - "pkg-config", - "system-deps 6.1.0", -] - -[[package]] -name = "gdkx11-sys" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7f8c7a84b407aa9b143877e267e848ff34106578b64d1e0a24bf550716178" -dependencies = [ - "gdk-sys", - "glib-sys", - "libc", - "system-deps 6.1.0", - "x11", -] - -[[package]] -name = "generator" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e123d9ae7c02966b4d892e550bdc32164f05853cd40ab570650ad600596a8a" -dependencies = [ - "cc", - "libc", - "log 0.4.17", - "rustversion", - "windows 0.48.0", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "gio" -version = "0.15.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" -dependencies = [ - "bitflags", - "futures-channel", - "futures-core", - "futures-io", - "gio-sys", - "glib", - "libc", - "once_cell", - "thiserror", -] - -[[package]] -name = "gio-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.1.0", - "winapi", -] - -[[package]] -name = "glib" -version = "0.15.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" -dependencies = [ - "bitflags", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "once_cell", - "smallvec", - "thiserror", -] - -[[package]] -name = "glib-macros" -version = "0.15.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" -dependencies = [ - "anyhow", - "heck 0.4.1", - "proc-macro-crate", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "glib-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" -dependencies = [ - "libc", - "system-deps 6.1.0", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "globset" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" -dependencies = [ - "aho-corasick 0.7.20", - "bstr", - "fnv", - "log 0.4.17", - "regex 1.8.3", -] - -[[package]] -name = "gobject-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" -dependencies = [ - "glib-sys", - "libc", - "system-deps 6.1.0", -] - -[[package]] -name = "gtk" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" -dependencies = [ - "atk", - "bitflags", - "cairo-rs", - "field-offset", - "futures-channel", - "gdk", - "gdk-pixbuf", - "gio", - "glib", - "gtk-sys", - "gtk3-macros", - "libc", - "once_cell", - "pango", - "pkg-config", -] - -[[package]] -name = "gtk-sys" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps 6.1.0", -] - -[[package]] -name = "gtk3-macros" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684c0456c086e8e7e9af73ec5b84e35938df394712054550e81558d21c44ab0d" -dependencies = [ - "anyhow", - "proc-macro-crate", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "h2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "handlebars" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc" -dependencies = [ - "lazy_static 0.2.11", - "log 0.3.9", - "pest 0.3.3", - "quick-error", - "regex 0.2.11", - "serde", - "serde_json", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] - -[[package]] -name = "headers" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" -dependencies = [ - "base64 0.13.1", - "bitflags", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "html5ever" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" -dependencies = [ - "log 0.4.17", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.6", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "http-range" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.6", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" -dependencies = [ - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows 0.48.0", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ico" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae" -dependencies = [ - "byteorder", - "png", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "ignore" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" -dependencies = [ - "crossbeam-utils", - "globset", - "lazy_static 1.4.0", - "log 0.4.17", - "memchr", - "regex 1.8.3", - "same-file", - "thread_local 1.1.7", - "walkdir", - "winapi-util", -] - -[[package]] -name = "image" -version = "0.24.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-rational", - "num-traits", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", - "serde", -] - -[[package]] -name = "infer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f178e61cdbfe084aa75a2f4f7a25a5bb09701a47ae1753608f194b15783c937a" -dependencies = [ - "cfb", -] - -[[package]] -name = "infer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a898e4b7951673fce96614ce5751d13c40fc5674bc2d759288e46c3ab62598b3" -dependencies = [ - "cfb", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "interfaces" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec8f50a973916cac3da5057c986db05cd3346f38c78e9bc24f64cc9f6a3978f" -dependencies = [ - "bitflags", - "cc", - "handlebars", - "lazy_static 1.4.0", - "libc", - "nix 0.23.2", - "serde", - "serde_derive", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "ipnet" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" - -[[package]] -name = "is-docker" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" -dependencies = [ - "once_cell", -] - -[[package]] -name = "is-wsl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" -dependencies = [ - "is-docker", - "once_cell", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" - -[[package]] -name = "javascriptcore-rs" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" -dependencies = [ - "bitflags", - "glib", - "javascriptcore-rs-sys", -] - -[[package]] -name = "javascriptcore-rs-sys" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "905fbb87419c5cde6e3269537e4ea7d46431f3008c5d057e915ef3f115e7793c" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 5.0.0", -] - -[[package]] -name = "jni" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log 0.4.17", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "js-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "json-patch" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3fa5a61630976fc4c353c70297f2e93f1930e3ccee574d59d618ccbd5154ce" -dependencies = [ - "serde", - "serde_json", - "treediff 3.0.2", -] - -[[package]] -name = "json-patch" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f54898088ccb91df1b492cc80029a6fdf1c48ca0db7c6822a8babad69c94658" -dependencies = [ - "serde", - "serde_json", - "thiserror", - "treediff 4.0.2", -] - -[[package]] -name = "kuchiki" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" -dependencies = [ - "cssparser", - "html5ever", - "matches", - "selectors", -] - -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libappindicator" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" -dependencies = [ - "glib", - "gtk", - "gtk-sys", - "libappindicator-sys", - "log 0.4.17", -] - -[[package]] -name = "libappindicator-sys" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" -dependencies = [ - "gtk-sys", - "libloading", - "once_cell", -] - -[[package]] -name = "libc" -version = "0.2.144" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "line-wrap" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.17", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", - "serde", -] - -[[package]] -name = "log-mdc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" - -[[package]] -name = "log4rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36ca1786d9e79b8193a68d480a0907b612f109537115c6ff655a3a1967533fd" -dependencies = [ - "anyhow", - "arc-swap", - "chrono", - "derivative", - "fnv", - "humantime", - "libc", - "log 0.4.17", - "log-mdc", - "parking_lot", - "serde", - "serde-value", - "serde_json", - "serde_yaml 0.8.26", - "thiserror", - "thread-id", - "typemap-ors", - "winapi", -] - -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "lru" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "markup5ever" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" -dependencies = [ - "log 0.4.17", - "phf 0.8.0", - "phf_codegen 0.8.0", - "string_cache", - "string_cache_codegen", - "tendril", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memmem" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "minisign-verify" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" -dependencies = [ - "libc", - "log 0.4.17", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", -] - -[[package]] -name = "multer" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http", - "httparse", - "log 0.4.17", - "memchr", - "mime", - "spin 0.9.8", - "version_check", -] - -[[package]] -name = "nanoid" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" -dependencies = [ - "rand 0.8.5", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static 1.4.0", - "libc", - "log 0.4.17", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "ndk" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nix" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" -dependencies = [ - "bitflags", - "cc", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "static_assertions", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "once_cell" -version = "1.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "open" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" -dependencies = [ - "pathdiff", - "windows-sys 0.42.0", -] - -[[package]] -name = "open" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16814a067484415fda653868c9be0ac5f2abd2ef5d951082a5f2fe1b3662944" -dependencies = [ - "is-wsl", - "pathdiff", -] - -[[package]] -name = "openssl" -version = "0.10.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "111.25.3+1.1.1t" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924757a6a226bf60da5f7dd0311a34d2b52283dd82ddeb103208ddc66362f80c" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "os_pipe" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "pango" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" -dependencies = [ - "bitflags", - "glib", - "libc", - "once_cell", - "pango-sys", -] - -[[package]] -name = "pango-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.1.0", -] - -[[package]] -name = "parking" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "windows-sys 0.45.0", -] - -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - -[[package]] -name = "pathsearch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da983bc5e582ab17179c190b4b66c7d76c5943a69c6d34df2a2b6bf8a2977b05" -dependencies = [ - "anyhow", - "libc", -] - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "pest" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" - -[[package]] -name = "pest" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_macros 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" -dependencies = [ - "phf_shared 0.11.1", -] - -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", -] - -[[package]] -name = "phf_codegen" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" -dependencies = [ - "phf_generator 0.11.1", - "phf_shared 0.11.1", -] - -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", -] - -[[package]] -name = "phf_generator" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" -dependencies = [ - "phf_shared 0.11.1", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "phf_macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "plist" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" -dependencies = [ - "base64 0.21.2", - "indexmap", - "line-wrap", - "quick-xml", - "serde", - "time 0.3.15", -] - -[[package]] -name = "png" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags", - "cfg-if", - "concurrent-queue", - "libc", - "log 0.4.17", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "port_scanner" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a6d2ac5dee293c3b2612d4993b98aec1dff096b0a2dae70ed7d95784a05da" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro2" -version = "1.0.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quick-xml" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.9", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "raw-window-handle" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" -dependencies = [ - "cty", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.9", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -dependencies = [ - "aho-corasick 0.6.10", - "memchr", - "regex-syntax 0.5.6", - "thread_local 0.3.6", - "utf8-ranges", -] - -[[package]] -name = "regex" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" -dependencies = [ - "aho-corasick 1.0.1", - "memchr", - "regex-syntax 0.7.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -dependencies = [ - "ucd-util", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" - -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64 0.21.2", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log 0.4.17", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots", - "winreg 0.10.1", -] - -[[package]] -name = "rfd" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea" -dependencies = [ - "block", - "dispatch", - "glib-sys", - "gobject-sys", - "gtk-sys", - "js-sys", - "lazy_static 1.4.0", - "log 0.4.17", - "objc", - "objc-foundation", - "objc_id", - "raw-window-handle", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.37.0", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "rquickjs" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc022cc82b5de6f38b2f4ddb8ed9c49cdbd7ce112e650b181598e102157257de" -dependencies = [ - "rquickjs-core", -] - -[[package]] -name = "rquickjs-core" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa1ecc1c84b31da87e5b26ce2b5218d36ffeb5c322141c78b79fa86a6ee3b9" -dependencies = [ - "rquickjs-sys", -] - -[[package]] -name = "rquickjs-sys" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24311952af42d8252e399cf48e7d470cb413b1a11a1a5b7fab648cd2edec76c5" -dependencies = [ - "cc", -] - -[[package]] -name = "rs-snowflake" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60ef3b82994702bbe4e134d98aadca4b49ed04440148985678d415c68127666" - -[[package]] -name = "runas" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49535b7c73aec5596ae2c44a6d8a7a8f8592e5744564c327fd4846750413d921" -dependencies = [ - "libc", - "security-framework-sys", - "which", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.17", -] - -[[package]] -name = "rustix" -version = "0.37.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustls" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" -dependencies = [ - "log 0.4.17", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" -dependencies = [ - "base64 0.21.2", -] - -[[package]] -name = "rustls-webpki" -version = "0.100.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" - -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "security-framework" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "selectors" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" -dependencies = [ - "bitflags", - "cssparser", - "derive_more", - "fxhash", - "log 0.4.17", - "matches", - "phf 0.8.0", - "phf_codegen 0.8.0", - "precomputed-hash", - "servo_arc", - "smallvec", - "thin-slice", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser 0.7.0", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser 0.10.2", -] - -[[package]] -name = "semver" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" -dependencies = [ - "serde", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest 2.6.0", -] - -[[package]] -name = "serde" -version = "1.0.163" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.163" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa 1.0.6", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "serde_spanned" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa 1.0.6", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "base64 0.13.1", - "chrono", - "hex", - "indexmap", - "serde", - "serde_json", - "serde_with_macros", - "time 0.3.15", -] - -[[package]] -name = "serde_with_macros" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "serde_yaml" -version = "0.9.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c" -dependencies = [ - "indexmap", - "itoa 1.0.6", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "serialize-to-javascript" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" -dependencies = [ - "serde", - "serde_json", - "serialize-to-javascript-impl", -] - -[[package]] -name = "serialize-to-javascript-impl" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "servo_arc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" -dependencies = [ - "nodrop", - "stable_deref_trait", -] - -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static 1.4.0", -] - -[[package]] -name = "shared_child" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "shared_library" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" -dependencies = [ - "lazy_static 1.4.0", - "libc", -] - -[[package]] -name = "signal-hook" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "simd-adler32" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" - -[[package]] -name = "siphasher" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "smol" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" -dependencies = [ - "async-channel", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-net", - "async-process", - "blocking", - "futures-lite", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "soup2" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b4d76501d8ba387cf0fefbe055c3e0a59891d09f0f995ae4e4b16f6b60f3c0" -dependencies = [ - "bitflags", - "gio", - "glib", - "libc", - "once_cell", - "soup2-sys", -] - -[[package]] -name = "soup2-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009ef427103fcb17f802871647a7fa6c60cbb654b4c4e4c0ac60a31c5f6dc9cf" -dependencies = [ - "bitflags", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps 5.0.0", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "state" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" -dependencies = [ - "loom", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared 0.10.0", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro2", - "quote", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sysinfo" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f1dc6930a439cc5d154221b5387d153f8183529b07c19aca24ea31e0a167e1" -dependencies = [ - "cfg-if", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi", -] - -[[package]] -name = "sysproxy" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9707a79d3b95683aa5a9521e698ffd878b8fb289727c25a69157fb85d529ffff" -dependencies = [ - "interfaces", - "thiserror", - "winapi", - "winreg 0.10.1", -] - -[[package]] -name = "system-deps" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" -dependencies = [ - "cfg-expr 0.9.1", - "heck 0.3.3", - "pkg-config", - "toml 0.5.11", - "version-compare 0.0.11", -] - -[[package]] -name = "system-deps" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5fa6fb9ee296c0dc2df41a656ca7948546d061958115ddb0bcaae43ad0d17d2" -dependencies = [ - "cfg-expr 0.15.1", - "heck 0.4.1", - "pkg-config", - "toml 0.7.4", - "version-compare 0.1.1", -] - -[[package]] -name = "tao" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6d198e01085564cea63e976ad1566c1ba2c2e4cc79578e35d9f05521505e31" -dependencies = [ - "bitflags", - "cairo-rs", - "cc", - "cocoa", - "core-foundation", - "core-graphics", - "crossbeam-channel", - "dirs-next", - "dispatch", - "gdk", - "gdk-pixbuf", - "gdk-sys", - "gdkwayland-sys", - "gdkx11-sys", - "gio", - "glib", - "glib-sys", - "gtk", - "image", - "instant", - "jni", - "lazy_static 1.4.0", - "libappindicator", - "libc", - "log 0.4.17", - "ndk", - "ndk-context", - "ndk-sys", - "objc", - "once_cell", - "parking_lot", - "png", - "raw-window-handle", - "scopeguard", - "serde", - "tao-macros", - "unicode-segmentation", - "uuid", - "windows 0.39.0", - "windows-implement", - "x11-dl", -] - -[[package]] -name = "tao-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b27a4bcc5eb524658234589bdffc7e7bfb996dbae6ce9393bfd39cb4159b445" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "tar" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "target-lexicon" -version = "0.12.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" - -[[package]] -name = "tauri" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d42ba3a2e8556722f31336a0750c10dbb6a81396a1c452977f515da83f69f842" -dependencies = [ - "anyhow", - "attohttpc", - "base64 0.21.2", - "bytes", - "cocoa", - "dirs-next", - "embed_plist", - "encoding_rs", - "flate2", - "futures-util", - "glib", - "glob", - "gtk", - "heck 0.4.1", - "http", - "ignore", - "infer 0.9.0", - "minisign-verify", - "objc", - "once_cell", - "open 3.2.0", - "os_pipe", - "percent-encoding", - "png", - "rand 0.8.5", - "raw-window-handle", - "regex 1.8.3", - "reqwest", - "rfd", - "semver 1.0.17", - "serde", - "serde_json", - "serde_repr", - "serialize-to-javascript", - "shared_child", - "state", - "tar", - "tauri-macros", - "tauri-runtime", - "tauri-runtime-wry", - "tauri-utils", - "tempfile", - "thiserror", - "time 0.3.15", - "tokio", - "url", - "uuid", - "webkit2gtk", - "webview2-com", - "windows 0.39.0", - "zip", -] - -[[package]] -name = "tauri-build" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8807c85d656b2b93927c19fe5a5f1f1f348f96c2de8b90763b3c2d561511f9b4" -dependencies = [ - "anyhow", - "cargo_toml", - "heck 0.4.1", - "json-patch 0.2.7", - "semver 1.0.17", - "serde_json", - "tauri-utils", - "winres", -] - -[[package]] -name = "tauri-codegen" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a2105f807c6f50b2fa2ce5abd62ef207bc6f14c9fcc6b8caec437f6fb13bde" -dependencies = [ - "base64 0.21.2", - "brotli", - "ico", - "json-patch 1.0.0", - "plist", - "png", - "proc-macro2", - "quote", - "regex 1.8.3", - "semver 1.0.17", - "serde", - "serde_json", - "sha2 0.10.6", - "tauri-utils", - "thiserror", - "time 0.3.15", - "uuid", - "walkdir", -] - -[[package]] -name = "tauri-macros" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8784cfe6f5444097e93c69107d1ac5e8f13d02850efa8d8f2a40fe79674cef46" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "tauri-codegen", - "tauri-utils", -] - -[[package]] -name = "tauri-runtime" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b80ea3fcd5fefb60739a3b577b277e8fc30434538a2f5bba82ad7d4368c422" -dependencies = [ - "gtk", - "http", - "http-range", - "rand 0.8.5", - "raw-window-handle", - "serde", - "serde_json", - "tauri-utils", - "thiserror", - "url", - "uuid", - "webview2-com", - "windows 0.39.0", -] - -[[package]] -name = "tauri-runtime-wry" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c396950b1ba06aee1b4ffe6c7cd305ff433ca0e30acbc5fa1a2f92a4ce70f1" -dependencies = [ - "cocoa", - "gtk", - "percent-encoding", - "rand 0.8.5", - "raw-window-handle", - "tauri-runtime", - "tauri-utils", - "uuid", - "webkit2gtk", - "webview2-com", - "windows 0.39.0", - "wry", -] - -[[package]] -name = "tauri-utils" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6f9c2dafef5cbcf52926af57ce9561bd33bb41d7394f8bb849c0330260d864" -dependencies = [ - "brotli", - "ctor", - "glob", - "heck 0.4.1", - "html5ever", - "infer 0.12.0", - "json-patch 1.0.0", - "kuchiki", - "memchr", - "phf 0.10.1", - "proc-macro2", - "quote", - "semver 1.0.17", - "serde", - "serde_json", - "serde_with", - "thiserror", - "url", - "walkdir", - "windows 0.39.0", -] - -[[package]] -name = "tempfile" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys 0.45.0", -] - -[[package]] -name = "tendril" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" -dependencies = [ - "futf", - "mac", - "utf-8", -] - -[[package]] -name = "terminfo" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da31aef70da0f6352dbcb462683eb4dd2bfad01cf3fc96cf204547b9a839a585" -dependencies = [ - "dirs 4.0.0", - "fnv", - "nom 5.1.3", - "phf 0.11.1", - "phf_codegen 0.11.1", -] - -[[package]] -name = "termios" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" -dependencies = [ - "libc", -] - -[[package]] -name = "termwiz" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6892cc0348a9b3b8c377addba91e0f6365863d92354bf27559dca81ee8c5" -dependencies = [ - "anyhow", - "base64 0.13.1", - "bitflags", - "cfg-if", - "filedescriptor", - "hex", - "lazy_static 1.4.0", - "libc", - "log 0.4.17", - "memmem", - "num-derive", - "num-traits", - "ordered-float", - "regex 1.8.3", - "semver 0.11.0", - "sha2 0.9.9", - "signal-hook 0.1.17", - "terminfo", - "termios", - "thiserror", - "ucd-trie", - "unicode-segmentation", - "vtparse", - "winapi", -] - -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - -[[package]] -name = "thiserror" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "thread-id" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee93aa2b8331c0fec9091548843f2c90019571814057da3b783f9de09349d73" -dependencies = [ - "libc", - "redox_syscall 0.2.16", - "winapi", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -dependencies = [ - "lazy_static 1.4.0", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" -dependencies = [ - "itoa 1.0.6", - "libc", - "num_threads", - "serde", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" -dependencies = [ - "autocfg", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" -dependencies = [ - "futures-util", - "log 0.4.17", - "tokio", - "tungstenite", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "log 0.4.17", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static 1.4.0", - "log 0.4.17", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex 1.8.3", - "sharded-slab", - "smallvec", - "thread_local 1.1.7", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "treediff" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff" -dependencies = [ - "serde_json", -] - -[[package]] -name = "treediff" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" -dependencies = [ - "serde_json", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tungstenite" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log 0.4.17", - "rand 0.8.5", - "sha1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "typemap-ors" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68c24b707f02dd18f1e4ccceb9d49f2058c2fb86384ef9972592904d7a28867" -dependencies = [ - "unsafe-any-ors", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - -[[package]] -name = "ucd-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd2fc5d32b590614af8b0a20d837f32eca055edd0bbead59a9cfe80858be003" - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unsafe-any-ors" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a303d30665362d9680d7d91d78b23f5f899504d4f08b3c4cf08d055d87c0ad" -dependencies = [ - "destructure_traitobject", -] - -[[package]] -name = "unsafe-libyaml" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8-ranges" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "uuid" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" -dependencies = [ - "getrandom 0.2.9", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version-compare" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" - -[[package]] -name = "version-compare" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "vtparse" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log 0.4.17", - "try-lock", -] - -[[package]] -name = "warp" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "headers", - "http", - "hyper", - "log 0.4.17", - "mime", - "mime_guess", - "multer", - "percent-encoding", - "pin-project", - "rustls-pemfile", - "scoped-tls", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-stream", - "tokio-tungstenite", - "tokio-util", - "tower-service", - "tracing", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" -dependencies = [ - "bumpalo", - "log 0.4.17", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.18", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" - -[[package]] -name = "wasm-streams" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webkit2gtk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370" -dependencies = [ - "bitflags", - "cairo-rs", - "gdk", - "gdk-sys", - "gio", - "gio-sys", - "glib", - "glib-sys", - "gobject-sys", - "gtk", - "gtk-sys", - "javascriptcore-rs", - "libc", - "once_cell", - "soup2", - "webkit2gtk-sys", -] - -[[package]] -name = "webkit2gtk-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d76ca6ecc47aeba01ec61e480139dda143796abcae6f83bcddf50d6b5b1dcf3" -dependencies = [ - "atk-sys", - "bitflags", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "gtk-sys", - "javascriptcore-rs-sys", - "libc", - "pango-sys", - "pkg-config", - "soup2-sys", - "system-deps 6.1.0", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "webview2-com" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a769c9f1a64a8734bde70caafac2b96cada12cd4aefa49196b3a386b8b4178" -dependencies = [ - "webview2-com-macros", - "webview2-com-sys", - "windows 0.39.0", - "windows-implement", -] - -[[package]] -name = "webview2-com-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "webview2-com-sys" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac48ef20ddf657755fdcda8dfed2a7b4fc7e4581acce6fe9b88c3d64f29dee7" -dependencies = [ - "regex 1.8.3", - "serde", - "serde_json", - "thiserror", - "windows 0.39.0", - "windows-bindgen", - "windows-metadata", -] - -[[package]] -name = "which" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" -dependencies = [ - "either", - "libc", - "once_cell", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "window-shadows" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d30320647cfc3dc45554c8ad825b84831def81f967a2f7589931328ff9b16d" -dependencies = [ - "cocoa", - "objc", - "raw-window-handle", - "windows-sys 0.42.0", -] - -[[package]] -name = "window-vibrancy" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f762d9cc392fb85e6b1b5eed1ef13d73fed5149a5cbb017a7137497d14ef612" -dependencies = [ - "cocoa", - "objc", - "raw-window-handle", - "windows-sys 0.42.0", -] - -[[package]] -name = "windows" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" -dependencies = [ - "windows_aarch64_msvc 0.37.0", - "windows_i686_gnu 0.37.0", - "windows_i686_msvc 0.37.0", - "windows_x86_64_gnu 0.37.0", - "windows_x86_64_msvc 0.37.0", -] - -[[package]] -name = "windows" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" -dependencies = [ - "windows-implement", - "windows_aarch64_msvc 0.39.0", - "windows_i686_gnu 0.39.0", - "windows_i686_msvc 0.39.0", - "windows_x86_64_gnu 0.39.0", - "windows_x86_64_msvc 0.39.0", -] - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-bindgen" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68003dbd0e38abc0fb85b939240f4bce37c43a5981d3df37ccbaaa981b47cb41" -dependencies = [ - "windows-metadata", - "windows-tokens", -] - -[[package]] -name = "windows-implement" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" -dependencies = [ - "syn 1.0.109", - "windows-tokens", -] - -[[package]] -name = "windows-metadata" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows-tokens" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" - -[[package]] -name = "windows_i686_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" - -[[package]] -name = "windows_i686_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "winnow" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winres" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" -dependencies = [ - "toml 0.5.11", -] - -[[package]] -name = "wry" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33748f35413c8a98d45f7a08832d848c0c5915501803d1faade5a4ebcd258cea" -dependencies = [ - "base64 0.13.1", - "block", - "cocoa", - "core-graphics", - "crossbeam-channel", - "dunce", - "gdk", - "gio", - "glib", - "gtk", - "html5ever", - "http", - "kuchiki", - "libc", - "log 0.4.17", - "objc", - "objc_id", - "once_cell", - "serde", - "serde_json", - "sha2 0.10.6", - "soup2", - "tao", - "thiserror", - "url", - "webkit2gtk", - "webkit2gtk-sys", - "webview2-com", - "windows 0.39.0", - "windows-implement", -] - -[[package]] -name = "x11" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "xattr" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" -dependencies = [ - "libc", -] - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "byteorder", - "crc32fast", - "crossbeam-utils", -] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml deleted file mode 100644 index 440a398..0000000 --- a/src-tauri/Cargo.toml +++ /dev/null @@ -1,69 +0,0 @@ -[package] -name = "clash-verge" -version = "0.1.0" -description = "clash verge" -authors = ["zzzgydi"] -license = "GPL-3.0" -repository = "https://github.com/zzzgydi/clash-verge.git" -default-run = "clash-verge" -edition = "2021" -build = "build.rs" - -[build-dependencies] -tauri-build = { version = "1", features = [] } - -[dependencies] -warp = "0.3" -which = "4.2.2" -anyhow = "1.0" -dirs = "5.0.0" -open = "4.0.1" -log = "0.4.14" -ctrlc = "3.2.3" -dunce = "1.0.2" -log4rs = "1.0.0" -nanoid = "0.4.0" -chrono = "0.4.19" -sysinfo = "0.29" -sysproxy = "0.3" -rquickjs = "0.1.7" -serde_json = "1.0" -serde_yaml = "0.9" -auto-launch = "0.5" -once_cell = "1.14.0" -port_scanner = "0.1.5" -delay_timer = "0.11.1" -parking_lot = "0.12.0" -tokio = { version = "1", features = ["full"] } -serde = { version = "1.0", features = ["derive"] } -reqwest = { version = "0.11", features = ["json","rustls-tls"] } -tauri = { version = "1.2.4", features = ["global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] } -window-vibrancy = { version = "0.3.0" } -window-shadows = { version = "0.2.0" } -wry = { version = "0.24.3" } - - -[target.'cfg(windows)'.dependencies] -runas = "1.1.0" -deelevate = "0.2.0" -winreg = { version = "0.50", features = ["transactions"] } -windows-sys = { version = "0.48", features = ["Win32_System_LibraryLoader", "Win32_System_SystemInformation"] } - -[target.'cfg(windows)'.dependencies.tauri] -features = ["global-shortcut-all", "icon-png", "process-all", "shell-all", "system-tray", "updater", "window-all"] - -[target.'cfg(linux)'.dependencies.tauri] -features = ["global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "native-tls-vendored", "reqwest-native-tls-vendored"] - - -[features] -default = ["custom-protocol"] -custom-protocol = ["tauri/custom-protocol"] -verge-dev = [] -default-meta = [] - -[profile.release] -panic = "abort" -codegen-units = 1 -lto = true -opt-level = "s" diff --git a/src-tauri/build.rs b/src-tauri/build.rs deleted file mode 100644 index d860e1e..0000000 --- a/src-tauri/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - tauri_build::build() -} diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png deleted file mode 100644 index be2533a..0000000 Binary files a/src-tauri/icons/128x128.png and /dev/null differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png deleted file mode 100644 index 3245891..0000000 Binary files a/src-tauri/icons/128x128@2x.png and /dev/null differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png deleted file mode 100644 index 1a93685..0000000 Binary files a/src-tauri/icons/32x32.png and /dev/null differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png deleted file mode 100644 index 4240ea5..0000000 Binary files a/src-tauri/icons/Square107x107Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png deleted file mode 100644 index 822b49b..0000000 Binary files a/src-tauri/icons/Square142x142Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png deleted file mode 100644 index bb7e494..0000000 Binary files a/src-tauri/icons/Square150x150Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png deleted file mode 100644 index 9b0ec9f..0000000 Binary files a/src-tauri/icons/Square284x284Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png deleted file mode 100644 index 496a662..0000000 Binary files a/src-tauri/icons/Square30x30Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png deleted file mode 100644 index c02df10..0000000 Binary files a/src-tauri/icons/Square310x310Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png deleted file mode 100644 index 8ff531d..0000000 Binary files a/src-tauri/icons/Square44x44Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png deleted file mode 100644 index 7829892..0000000 Binary files a/src-tauri/icons/Square71x71Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png deleted file mode 100644 index 6b64990..0000000 Binary files a/src-tauri/icons/Square89x89Logo.png and /dev/null differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png deleted file mode 100644 index 15344c6..0000000 Binary files a/src-tauri/icons/StoreLogo.png and /dev/null differ diff --git a/src-tauri/icons/icon-new.icns b/src-tauri/icons/icon-new.icns deleted file mode 100644 index b66e74e..0000000 Binary files a/src-tauri/icons/icon-new.icns and /dev/null differ diff --git a/src-tauri/icons/icon-shrink.png b/src-tauri/icons/icon-shrink.png deleted file mode 100644 index 5ebfa38..0000000 Binary files a/src-tauri/icons/icon-shrink.png and /dev/null differ diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns deleted file mode 100644 index 88df4a0..0000000 Binary files a/src-tauri/icons/icon.icns and /dev/null differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico deleted file mode 100644 index e406a78..0000000 Binary files a/src-tauri/icons/icon.ico and /dev/null differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png deleted file mode 100644 index cf91cf6..0000000 Binary files a/src-tauri/icons/icon.png and /dev/null differ diff --git a/src-tauri/icons/tray-icon.ico b/src-tauri/icons/tray-icon.ico deleted file mode 100644 index 611c958..0000000 Binary files a/src-tauri/icons/tray-icon.ico and /dev/null differ diff --git a/src-tauri/icons/tray-icon.png b/src-tauri/icons/tray-icon.png deleted file mode 100644 index be2533a..0000000 Binary files a/src-tauri/icons/tray-icon.png and /dev/null differ diff --git a/src-tauri/icons/win-tray-icon-activated.png b/src-tauri/icons/win-tray-icon-activated.png deleted file mode 100644 index 441ff02..0000000 Binary files a/src-tauri/icons/win-tray-icon-activated.png and /dev/null differ diff --git a/src-tauri/icons/win-tray-icon.png b/src-tauri/icons/win-tray-icon.png deleted file mode 100644 index 29616c8..0000000 Binary files a/src-tauri/icons/win-tray-icon.png and /dev/null differ diff --git a/src-tauri/rustfmt.toml b/src-tauri/rustfmt.toml deleted file mode 100644 index 11eda88..0000000 --- a/src-tauri/rustfmt.toml +++ /dev/null @@ -1,14 +0,0 @@ -max_width = 100 -hard_tabs = false -tab_spaces = 4 -newline_style = "Auto" -use_small_heuristics = "Default" -reorder_imports = true -reorder_modules = true -remove_nested_parens = true -edition = "2021" -merge_derives = true -use_try_shorthand = false -use_field_init_shorthand = false -force_explicit_abi = true -imports_granularity = "Crate" diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs deleted file mode 100644 index 4b42ebe..0000000 --- a/src-tauri/src/cmds.rs +++ /dev/null @@ -1,280 +0,0 @@ -use crate::{ - config::*, - core::*, - feat, - utils::{dirs, help}, -}; -use crate::{ret_err, wrap_err}; -use anyhow::{Context, Result}; -use serde_yaml::Mapping; -use std::collections::{HashMap, VecDeque}; -use sysproxy::Sysproxy; - -type CmdResult = Result; - -#[tauri::command] -pub fn get_profiles() -> CmdResult { - Ok(Config::profiles().data().clone()) -} - -#[tauri::command] -pub async fn enhance_profiles() -> CmdResult { - wrap_err!(CoreManager::global().update_config().await)?; - handle::Handle::refresh_clash(); - Ok(()) -} - -#[tauri::command] -pub async fn import_profile(url: String, option: Option) -> CmdResult { - let item = wrap_err!(PrfItem::from_url(&url, None, None, option).await)?; - wrap_err!(Config::profiles().data().append_item(item)) -} - -#[tauri::command] -pub async fn create_profile(item: PrfItem, file_data: Option) -> CmdResult { - let item = wrap_err!(PrfItem::from(item, file_data).await)?; - wrap_err!(Config::profiles().data().append_item(item)) -} - -#[tauri::command] -pub async fn update_profile(index: String, option: Option) -> CmdResult { - wrap_err!(feat::update_profile(index, option).await) -} - -#[tauri::command] -pub async fn delete_profile(index: String) -> CmdResult { - let should_update = wrap_err!({ Config::profiles().data().delete_item(index) })?; - if should_update { - wrap_err!(CoreManager::global().update_config().await)?; - handle::Handle::refresh_clash(); - } - - Ok(()) -} - -/// 修改profiles的 -#[tauri::command] -pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { - wrap_err!({ Config::profiles().draft().patch_config(profiles) })?; - - match CoreManager::global().update_config().await { - Ok(_) => { - handle::Handle::refresh_clash(); - Config::profiles().apply(); - wrap_err!(Config::profiles().data().save_file())?; - Ok(()) - } - Err(err) => { - Config::profiles().discard(); - log::error!(target: "app", "{err}"); - Err(format!("{err}")) - } - } -} - -/// 修改某个profile item的 -#[tauri::command] -pub fn patch_profile(index: String, profile: PrfItem) -> CmdResult { - wrap_err!(Config::profiles().data().patch_item(index, profile))?; - wrap_err!(timer::Timer::global().refresh()) -} - -#[tauri::command] -pub fn view_profile(index: String) -> CmdResult { - let file = { - wrap_err!(Config::profiles().latest().get_item(&index))? - .file - .clone() - .ok_or("the file field is null") - }?; - - let path = wrap_err!(dirs::app_profiles_dir())?.join(file); - if !path.exists() { - ret_err!("the file not found"); - } - - wrap_err!(help::open_file(path)) -} - -#[tauri::command] -pub fn read_profile_file(index: String) -> CmdResult { - let profiles = Config::profiles(); - let profiles = profiles.latest(); - let item = wrap_err!(profiles.get_item(&index))?; - let data = wrap_err!(item.read_file())?; - Ok(data) -} - -#[tauri::command] -pub fn save_profile_file(index: String, file_data: Option) -> CmdResult { - if file_data.is_none() { - return Ok(()); - } - - let profiles = Config::profiles(); - let profiles = profiles.latest(); - let item = wrap_err!(profiles.get_item(&index))?; - wrap_err!(item.save_file(file_data.unwrap())) -} - -#[tauri::command] -pub fn get_clash_info() -> CmdResult { - Ok(Config::clash().latest().get_client_info()) -} - -#[tauri::command] -pub fn get_runtime_config() -> CmdResult> { - Ok(Config::runtime().latest().config.clone()) -} - -#[tauri::command] -pub fn get_runtime_yaml() -> CmdResult { - let runtime = Config::runtime(); - let runtime = runtime.latest(); - let config = runtime.config.as_ref(); - wrap_err!(config - .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) - .and_then( - |config| serde_yaml::to_string(config).context("failed to convert config to yaml") - )) -} - -#[tauri::command] -pub fn get_runtime_exists() -> CmdResult> { - Ok(Config::runtime().latest().exists_keys.clone()) -} - -#[tauri::command] -pub fn get_runtime_logs() -> CmdResult>> { - Ok(Config::runtime().latest().chain_logs.clone()) -} - -#[tauri::command] -pub async fn patch_clash_config(payload: Mapping) -> CmdResult { - wrap_err!(feat::patch_clash(payload).await) -} - -#[tauri::command] -pub fn get_verge_config() -> CmdResult { - Ok(Config::verge().data().clone()) -} - -#[tauri::command] -pub async fn patch_verge_config(payload: IVerge) -> CmdResult { - wrap_err!(feat::patch_verge(payload).await) -} - -#[tauri::command] -pub async fn change_clash_core(clash_core: Option) -> CmdResult { - wrap_err!(CoreManager::global().change_core(clash_core).await) -} - -/// restart the sidecar -#[tauri::command] -pub async fn restart_sidecar() -> CmdResult { - wrap_err!(CoreManager::global().run_core().await) -} - -#[tauri::command] -pub fn grant_permission(core: String) -> CmdResult { - #[cfg(any(target_os = "macos", target_os = "linux"))] - return wrap_err!(manager::grant_permission(core)); - - #[cfg(not(any(target_os = "macos", target_os = "linux")))] - return Err("Unsupported target".into()); -} - -/// get the system proxy -#[tauri::command] -pub fn get_sys_proxy() -> CmdResult { - let current = wrap_err!(Sysproxy::get_system_proxy())?; - - let mut map = Mapping::new(); - map.insert("enable".into(), current.enable.into()); - map.insert( - "server".into(), - format!("{}:{}", current.host, current.port).into(), - ); - map.insert("bypass".into(), current.bypass.into()); - - Ok(map) -} - -#[tauri::command] -pub fn get_clash_logs() -> CmdResult> { - Ok(logger::Logger::global().get_log()) -} - -#[tauri::command] -pub fn open_app_dir() -> CmdResult<()> { - let app_dir = wrap_err!(dirs::app_home_dir())?; - wrap_err!(open::that(app_dir)) -} - -#[tauri::command] -pub fn open_core_dir() -> CmdResult<()> { - let core_dir = wrap_err!(tauri::utils::platform::current_exe())?; - let core_dir = core_dir.parent().ok_or(format!("failed to get core dir"))?; - wrap_err!(open::that(core_dir)) -} - -#[tauri::command] -pub fn open_logs_dir() -> CmdResult<()> { - let log_dir = wrap_err!(dirs::app_logs_dir())?; - wrap_err!(open::that(log_dir)) -} - -#[tauri::command] -pub fn open_web_url(url: String) -> CmdResult<()> { - wrap_err!(open::that(url)) -} - -#[tauri::command] -pub async fn clash_api_get_proxy_delay( - name: String, - url: Option, -) -> CmdResult { - match clash_api::get_proxy_delay(name, url).await { - Ok(res) => Ok(res), - Err(err) => Err(format!("{}", err.to_string())), - } -} - -#[cfg(windows)] -pub mod service { - use super::*; - use crate::core::win_service; - - #[tauri::command] - pub async fn check_service() -> CmdResult { - wrap_err!(win_service::check_service().await) - } - - #[tauri::command] - pub async fn install_service() -> CmdResult { - wrap_err!(win_service::install_service().await) - } - - #[tauri::command] - pub async fn uninstall_service() -> CmdResult { - wrap_err!(win_service::uninstall_service().await) - } -} - -#[cfg(not(windows))] -pub mod service { - use super::*; - - #[tauri::command] - pub async fn check_service() -> CmdResult { - Ok(()) - } - #[tauri::command] - pub async fn install_service() -> CmdResult { - Ok(()) - } - #[tauri::command] - pub async fn uninstall_service() -> CmdResult { - Ok(()) - } -} diff --git a/src-tauri/src/config/clash.rs b/src-tauri/src/config/clash.rs deleted file mode 100644 index 6a4cf5e..0000000 --- a/src-tauri/src/config/clash.rs +++ /dev/null @@ -1,262 +0,0 @@ -use crate::utils::{dirs, help}; -use anyhow::Result; -use serde::{Deserialize, Serialize}; -use serde_yaml::{Mapping, Value}; -use std::{ - net::{IpAddr, Ipv4Addr, SocketAddr}, - str::FromStr, -}; - -#[derive(Default, Debug, Clone)] -pub struct IClashTemp(pub Mapping); - -impl IClashTemp { - pub fn new() -> Self { - match dirs::clash_path().and_then(|path| help::read_merge_mapping(&path)) { - Ok(map) => Self(Self::guard(map)), - Err(err) => { - log::error!(target: "app", "{err}"); - Self::template() - } - } - } - - pub fn template() -> Self { - let mut map = Mapping::new(); - - map.insert( - "mixed-port".into(), - match cfg!(feature = "default-meta") { - false => 7890.into(), - true => 7898.into(), - }, - ); - map.insert("log-level".into(), "info".into()); - map.insert("allow-lan".into(), false.into()); - map.insert("mode".into(), "rule".into()); - map.insert( - "external-controller".into(), - match cfg!(feature = "default-meta") { - false => "127.0.0.1:9090".into(), - true => "127.0.0.1:9098".into(), - }, - ); - map.insert("secret".into(), "".into()); - - Self(map) - } - - fn guard(mut config: Mapping) -> Mapping { - let port = Self::guard_mixed_port(&config); - let ctrl = Self::guard_server_ctrl(&config); - - config.insert("mixed-port".into(), port.into()); - config.insert("external-controller".into(), ctrl.into()); - config - } - - pub fn patch_config(&mut self, patch: Mapping) { - for (key, value) in patch.into_iter() { - self.0.insert(key, value); - } - } - - pub fn save_config(&self) -> Result<()> { - help::save_yaml( - &dirs::clash_path()?, - &self.0, - Some("# Generated by Clash Verge"), - ) - } - - pub fn get_mixed_port(&self) -> u16 { - Self::guard_mixed_port(&self.0) - } - - pub fn get_client_info(&self) -> ClashInfo { - let config = &self.0; - - ClashInfo { - port: Self::guard_mixed_port(&config), - server: Self::guard_client_ctrl(&config), - secret: config.get("secret").and_then(|value| match value { - Value::String(val_str) => Some(val_str.clone()), - Value::Bool(val_bool) => Some(val_bool.to_string()), - Value::Number(val_num) => Some(val_num.to_string()), - _ => None, - }), - } - } - - pub fn guard_mixed_port(config: &Mapping) -> u16 { - let mut port = config - .get("mixed-port") - .and_then(|value| match value { - Value::String(val_str) => val_str.parse().ok(), - Value::Number(val_num) => val_num.as_u64().map(|u| u as u16), - _ => None, - }) - .unwrap_or(7890); - if port == 0 { - port = 7890; - } - port - } - - pub fn guard_server_ctrl(config: &Mapping) -> String { - config - .get("external-controller") - .and_then(|value| match value.as_str() { - Some(val_str) => { - let val_str = val_str.trim(); - - let val = match val_str.starts_with(":") { - true => format!("127.0.0.1{val_str}"), - false => val_str.to_owned(), - }; - - SocketAddr::from_str(val.as_str()) - .ok() - .map(|s| s.to_string()) - } - None => None, - }) - .unwrap_or("127.0.0.1:9090".into()) - } - - pub fn guard_client_ctrl(config: &Mapping) -> String { - let value = Self::guard_server_ctrl(config); - match SocketAddr::from_str(value.as_str()) { - Ok(mut socket) => { - if socket.ip().is_unspecified() { - socket.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); - } - socket.to_string() - } - Err(_) => "127.0.0.1:9090".into(), - } - } -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] -pub struct ClashInfo { - /// clash core port - pub port: u16, - /// same as `external-controller` - pub server: String, - /// clash secret - pub secret: Option, -} - -#[test] -fn test_clash_info() { - fn get_case, D: Into>(mp: T, ec: D) -> ClashInfo { - let mut map = Mapping::new(); - map.insert("mixed-port".into(), mp.into()); - map.insert("external-controller".into(), ec.into()); - - IClashTemp(IClashTemp::guard(map)).get_client_info() - } - - fn get_result>(port: u16, server: S) -> ClashInfo { - ClashInfo { - port, - server: server.into(), - secret: None, - } - } - - assert_eq!( - IClashTemp(IClashTemp::guard(Mapping::new())).get_client_info(), - get_result(7890, "127.0.0.1:9090") - ); - - assert_eq!(get_case("", ""), get_result(7890, "127.0.0.1:9090")); - - assert_eq!(get_case(65537, ""), get_result(1, "127.0.0.1:9090")); - - assert_eq!( - get_case(8888, "127.0.0.1:8888"), - get_result(8888, "127.0.0.1:8888") - ); - - assert_eq!( - get_case(8888, " :98888 "), - get_result(8888, "127.0.0.1:9090") - ); - - assert_eq!( - get_case(8888, "0.0.0.0:8080 "), - get_result(8888, "127.0.0.1:8080") - ); - - assert_eq!( - get_case(8888, "0.0.0.0:8080"), - get_result(8888, "127.0.0.1:8080") - ); - - assert_eq!( - get_case(8888, "[::]:8080"), - get_result(8888, "127.0.0.1:8080") - ); - - assert_eq!( - get_case(8888, "192.168.1.1:8080"), - get_result(8888, "192.168.1.1:8080") - ); - - assert_eq!( - get_case(8888, "192.168.1.1:80800"), - get_result(8888, "127.0.0.1:9090") - ); -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] -#[serde(rename_all = "kebab-case")] -pub struct IClash { - pub mixed_port: Option, - pub allow_lan: Option, - pub log_level: Option, - pub ipv6: Option, - pub mode: Option, - pub external_controller: Option, - pub secret: Option, - pub dns: Option, - pub tun: Option, - pub interface_name: Option, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] -#[serde(rename_all = "kebab-case")] -pub struct IClashTUN { - pub enable: Option, - pub stack: Option, - pub auto_route: Option, - pub auto_detect_interface: Option, - pub dns_hijack: Option>, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] -#[serde(rename_all = "kebab-case")] -pub struct IClashDNS { - pub enable: Option, - pub listen: Option, - pub default_nameserver: Option>, - pub enhanced_mode: Option, - pub fake_ip_range: Option, - pub use_hosts: Option, - pub fake_ip_filter: Option>, - pub nameserver: Option>, - pub fallback: Option>, - pub fallback_filter: Option, - pub nameserver_policy: Option>, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] -#[serde(rename_all = "kebab-case")] -pub struct IClashFallbackFilter { - pub geoip: Option, - pub geoip_code: Option, - pub ipcidr: Option>, - pub domain: Option>, -} diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs deleted file mode 100644 index e5af8e5..0000000 --- a/src-tauri/src/config/config.rs +++ /dev/null @@ -1,103 +0,0 @@ -use super::{Draft, IClashTemp, IProfiles, IRuntime, IVerge}; -use crate::{ - enhance, - utils::{dirs, help}, -}; -use anyhow::{anyhow, Result}; -use once_cell::sync::OnceCell; -use std::{env::temp_dir, path::PathBuf}; - -pub const RUNTIME_CONFIG: &str = "clash-verge.yaml"; -pub const CHECK_CONFIG: &str = "clash-verge-check.yaml"; - -pub struct Config { - clash_config: Draft, - verge_config: Draft, - profiles_config: Draft, - runtime_config: Draft, -} - -impl Config { - pub fn global() -> &'static Config { - static CONFIG: OnceCell = OnceCell::new(); - - CONFIG.get_or_init(|| Config { - clash_config: Draft::from(IClashTemp::new()), - verge_config: Draft::from(IVerge::new()), - profiles_config: Draft::from(IProfiles::new()), - runtime_config: Draft::from(IRuntime::new()), - }) - } - - pub fn clash() -> Draft { - Self::global().clash_config.clone() - } - - pub fn verge() -> Draft { - Self::global().verge_config.clone() - } - - pub fn profiles() -> Draft { - Self::global().profiles_config.clone() - } - - pub fn runtime() -> Draft { - Self::global().runtime_config.clone() - } - - /// 初始化配置 - pub fn init_config() -> Result<()> { - crate::log_err!(Self::generate()); - if let Err(err) = Self::generate_file(ConfigType::Run) { - log::error!(target: "app", "{err}"); - - let runtime_path = dirs::app_home_dir()?.join(RUNTIME_CONFIG); - // 如果不存在就将默认的clash文件拿过来 - if !runtime_path.exists() { - help::save_yaml( - &runtime_path, - &Config::clash().latest().0, - Some("# Clash Verge Runtime"), - )?; - } - } - Ok(()) - } - - /// 将配置丢到对应的文件中 - pub fn generate_file(typ: ConfigType) -> Result { - let path = match typ { - ConfigType::Run => dirs::app_home_dir()?.join(RUNTIME_CONFIG), - ConfigType::Check => temp_dir().join(CHECK_CONFIG), - }; - - let runtime = Config::runtime(); - let runtime = runtime.latest(); - let config = runtime - .config - .as_ref() - .ok_or(anyhow!("failed to get runtime config"))?; - - help::save_yaml(&path, &config, Some("# Generated by Clash Verge"))?; - Ok(path) - } - - /// 生成配置存好 - pub fn generate() -> Result<()> { - let (config, exists_keys, logs) = enhance::enhance(); - - *Config::runtime().draft() = IRuntime { - config: Some(config), - exists_keys, - chain_logs: logs, - }; - - Ok(()) - } -} - -#[derive(Debug)] -pub enum ConfigType { - Run, - Check, -} diff --git a/src-tauri/src/config/draft.rs b/src-tauri/src/config/draft.rs deleted file mode 100644 index 5876f1b..0000000 --- a/src-tauri/src/config/draft.rs +++ /dev/null @@ -1,127 +0,0 @@ -use super::{IClashTemp, IProfiles, IRuntime, IVerge}; -use parking_lot::{MappedMutexGuard, Mutex, MutexGuard}; -use std::sync::Arc; - -#[derive(Debug, Clone)] -pub struct Draft { - inner: Arc)>>, -} - -macro_rules! draft_define { - ($id: ident) => { - impl Draft<$id> { - #[allow(unused)] - pub fn data(&self) -> MappedMutexGuard<$id> { - MutexGuard::map(self.inner.lock(), |guard| &mut guard.0) - } - - pub fn latest(&self) -> MappedMutexGuard<$id> { - MutexGuard::map(self.inner.lock(), |inner| { - if inner.1.is_none() { - &mut inner.0 - } else { - inner.1.as_mut().unwrap() - } - }) - } - - pub fn draft(&self) -> MappedMutexGuard<$id> { - MutexGuard::map(self.inner.lock(), |inner| { - if inner.1.is_none() { - inner.1 = Some(inner.0.clone()); - } - - inner.1.as_mut().unwrap() - }) - } - - pub fn apply(&self) -> Option<$id> { - let mut inner = self.inner.lock(); - - match inner.1.take() { - Some(draft) => { - let old_value = inner.0.to_owned(); - inner.0 = draft.to_owned(); - Some(old_value) - } - None => None, - } - } - - pub fn discard(&self) -> Option<$id> { - let mut inner = self.inner.lock(); - inner.1.take() - } - } - - impl From<$id> for Draft<$id> { - fn from(data: $id) -> Self { - Draft { - inner: Arc::new(Mutex::new((data, None))), - } - } - } - }; -} - -// draft_define!(IClash); -draft_define!(IClashTemp); -draft_define!(IProfiles); -draft_define!(IRuntime); -draft_define!(IVerge); - -#[test] -fn test_draft() { - let verge = IVerge { - enable_auto_launch: Some(true), - enable_tun_mode: Some(false), - ..IVerge::default() - }; - - let draft = Draft::from(verge); - - assert_eq!(draft.data().enable_auto_launch, Some(true)); - assert_eq!(draft.data().enable_tun_mode, Some(false)); - - assert_eq!(draft.draft().enable_auto_launch, Some(true)); - assert_eq!(draft.draft().enable_tun_mode, Some(false)); - - let mut d = draft.draft(); - d.enable_auto_launch = Some(false); - d.enable_tun_mode = Some(true); - drop(d); - - assert_eq!(draft.data().enable_auto_launch, Some(true)); - assert_eq!(draft.data().enable_tun_mode, Some(false)); - - assert_eq!(draft.draft().enable_auto_launch, Some(false)); - assert_eq!(draft.draft().enable_tun_mode, Some(true)); - - assert_eq!(draft.latest().enable_auto_launch, Some(false)); - assert_eq!(draft.latest().enable_tun_mode, Some(true)); - - assert!(draft.apply().is_some()); - assert!(draft.apply().is_none()); - - assert_eq!(draft.data().enable_auto_launch, Some(false)); - assert_eq!(draft.data().enable_tun_mode, Some(true)); - - assert_eq!(draft.draft().enable_auto_launch, Some(false)); - assert_eq!(draft.draft().enable_tun_mode, Some(true)); - - let mut d = draft.draft(); - d.enable_auto_launch = Some(true); - drop(d); - - assert_eq!(draft.data().enable_auto_launch, Some(false)); - - assert_eq!(draft.draft().enable_auto_launch, Some(true)); - - assert!(draft.discard().is_some()); - - assert_eq!(draft.data().enable_auto_launch, Some(false)); - - assert!(draft.discard().is_none()); - - assert_eq!(draft.draft().enable_auto_launch, Some(false)); -} diff --git a/src-tauri/src/config/mod.rs b/src-tauri/src/config/mod.rs deleted file mode 100644 index b246a76..0000000 --- a/src-tauri/src/config/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod clash; -mod config; -mod draft; -mod prfitem; -mod profiles; -mod runtime; -mod verge; - -pub use self::clash::*; -pub use self::config::*; -pub use self::draft::*; -pub use self::prfitem::*; -pub use self::profiles::*; -pub use self::runtime::*; -pub use self::verge::*; diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs deleted file mode 100644 index 1e1d4a8..0000000 --- a/src-tauri/src/config/prfitem.rs +++ /dev/null @@ -1,374 +0,0 @@ -use crate::utils::{dirs, help, tmpl}; -use anyhow::{bail, Context, Result}; -use reqwest::StatusCode; -use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; -use std::fs; -use sysproxy::Sysproxy; - -use super::Config; - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct PrfItem { - pub uid: Option, - - /// profile item type - /// enum value: remote | local | script | merge - #[serde(rename = "type")] - pub itype: Option, - - /// profile name - pub name: Option, - - /// profile file - pub file: Option, - - /// profile description - #[serde(skip_serializing_if = "Option::is_none")] - pub desc: Option, - - /// source url - #[serde(skip_serializing_if = "Option::is_none")] - pub url: Option, - - /// selected information - #[serde(skip_serializing_if = "Option::is_none")] - pub selected: Option>, - - /// subscription user info - #[serde(skip_serializing_if = "Option::is_none")] - pub extra: Option, - - /// updated time - pub updated: Option, - - /// some options of the item - #[serde(skip_serializing_if = "Option::is_none")] - pub option: Option, - - /// the file data - #[serde(skip)] - pub file_data: Option, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct PrfSelected { - pub name: Option, - pub now: Option, -} - -#[derive(Default, Debug, Clone, Copy, Deserialize, Serialize)] -pub struct PrfExtra { - pub upload: usize, - pub download: usize, - pub total: usize, - pub expire: usize, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] -pub struct PrfOption { - /// for `remote` profile's http request - /// see issue #13 - #[serde(skip_serializing_if = "Option::is_none")] - pub user_agent: Option, - - /// for `remote` profile - /// use system proxy - #[serde(skip_serializing_if = "Option::is_none")] - pub with_proxy: Option, - - /// for `remote` profile - /// use self proxy - #[serde(skip_serializing_if = "Option::is_none")] - pub self_proxy: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub update_interval: Option, -} - -impl PrfOption { - pub fn merge(one: Option, other: Option) -> Option { - match (one, other) { - (Some(mut a), Some(b)) => { - a.user_agent = b.user_agent.or(a.user_agent); - a.with_proxy = b.with_proxy.or(a.with_proxy); - a.self_proxy = b.self_proxy.or(a.self_proxy); - a.update_interval = b.update_interval.or(a.update_interval); - Some(a) - } - t @ _ => t.0.or(t.1), - } - } -} - -impl Default for PrfItem { - fn default() -> Self { - PrfItem { - uid: None, - itype: None, - name: None, - desc: None, - file: None, - url: None, - selected: None, - extra: None, - updated: None, - option: None, - file_data: None, - } - } -} - -impl PrfItem { - /// From partial item - /// must contain `itype` - pub async fn from(item: PrfItem, file_data: Option) -> Result { - if item.itype.is_none() { - bail!("type should not be null"); - } - - match item.itype.unwrap().as_str() { - "remote" => { - if item.url.is_none() { - bail!("url should not be null"); - } - let url = item.url.as_ref().unwrap().as_str(); - let name = item.name; - let desc = item.desc; - PrfItem::from_url(url, name, desc, item.option).await - } - "local" => { - let name = item.name.unwrap_or("Local File".into()); - let desc = item.desc.unwrap_or("".into()); - PrfItem::from_local(name, desc, file_data) - } - "merge" => { - let name = item.name.unwrap_or("Merge".into()); - let desc = item.desc.unwrap_or("".into()); - PrfItem::from_merge(name, desc) - } - "script" => { - let name = item.name.unwrap_or("Script".into()); - let desc = item.desc.unwrap_or("".into()); - PrfItem::from_script(name, desc) - } - typ @ _ => bail!("invalid profile item type \"{typ}\""), - } - } - - /// ## Local type - /// create a new item from name/desc - pub fn from_local(name: String, desc: String, file_data: Option) -> Result { - let uid = help::get_uid("l"); - let file = format!("{uid}.yaml"); - - Ok(PrfItem { - uid: Some(uid), - itype: Some("local".into()), - name: Some(name), - desc: Some(desc), - file: Some(file), - url: None, - selected: None, - extra: None, - option: None, - updated: Some(chrono::Local::now().timestamp() as usize), - file_data: Some(file_data.unwrap_or(tmpl::ITEM_LOCAL.into())), - }) - } - - /// ## Remote type - /// create a new item from url - pub async fn from_url( - url: &str, - name: Option, - desc: Option, - option: Option, - ) -> Result { - let opt_ref = option.as_ref(); - let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false)); - let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false)); - let user_agent = opt_ref.map_or(None, |o| o.user_agent.clone()); - - let mut builder = reqwest::ClientBuilder::new().use_rustls_tls().no_proxy(); - - // 使用软件自己的代理 - if self_proxy { - let port = Config::clash().data().get_mixed_port(); - - let proxy_scheme = format!("http://127.0.0.1:{port}"); - - if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) { - builder = builder.proxy(proxy); - } - } - // 使用系统代理 - else if with_proxy { - match Sysproxy::get_system_proxy() { - Ok(p @ Sysproxy { enable: true, .. }) => { - let proxy_scheme = format!("http://{}:{}", p.host, p.port); - - if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) { - builder = builder.proxy(proxy); - } - } - _ => {} - }; - } - - let version = unsafe { dirs::APP_VERSION }; - let version = format!("clash-verge/{version}"); - builder = builder.user_agent(user_agent.unwrap_or(version)); - - let resp = builder.build()?.get(url).send().await?; - - let status_code = resp.status(); - if !StatusCode::is_success(&status_code) { - bail!("failed to fetch remote profile with status {status_code}") - } - - let header = resp.headers(); - - // parse the Subscription UserInfo - let extra = match header.get("Subscription-Userinfo") { - Some(value) => { - let sub_info = value.to_str().unwrap_or(""); - - Some(PrfExtra { - upload: help::parse_str(sub_info, "upload=").unwrap_or(0), - download: help::parse_str(sub_info, "download=").unwrap_or(0), - total: help::parse_str(sub_info, "total=").unwrap_or(0), - expire: help::parse_str(sub_info, "expire=").unwrap_or(0), - }) - } - None => None, - }; - - // parse the Content-Disposition - let filename = match header.get("Content-Disposition") { - Some(value) => { - let filename = value.to_str().unwrap_or(""); - help::parse_str::(filename, "filename=") - } - None => None, - }; - - // parse the profile-update-interval - let option = match header.get("profile-update-interval") { - Some(value) => match value.to_str().unwrap_or("").parse::() { - Ok(val) => Some(PrfOption { - update_interval: Some(val * 60), // hour -> min - ..PrfOption::default() - }), - Err(_) => None, - }, - None => None, - }; - - let uid = help::get_uid("r"); - let file = format!("{uid}.yaml"); - let name = name.unwrap_or(filename.unwrap_or("Remote File".into())); - let data = resp.text_with_charset("utf-8").await?; - - // process the charset "UTF-8 with BOM" - let data = data.trim_start_matches('\u{feff}'); - - // check the data whether the valid yaml format - let yaml = serde_yaml::from_str::(data) - .context("the remote profile data is invalid yaml")?; - - if !yaml.contains_key("proxies") && !yaml.contains_key("proxy-providers") { - bail!("profile does not contain `proxies` or `proxy-providers`"); - } - - Ok(PrfItem { - uid: Some(uid), - itype: Some("remote".into()), - name: Some(name), - desc, - file: Some(file), - url: Some(url.into()), - selected: None, - extra, - option, - updated: Some(chrono::Local::now().timestamp() as usize), - file_data: Some(data.into()), - }) - } - - /// ## Merge type (enhance) - /// create the enhanced item by using `merge` rule - pub fn from_merge(name: String, desc: String) -> Result { - let uid = help::get_uid("m"); - let file = format!("{uid}.yaml"); - - Ok(PrfItem { - uid: Some(uid), - itype: Some("merge".into()), - name: Some(name), - desc: Some(desc), - file: Some(file), - url: None, - selected: None, - extra: None, - option: None, - updated: Some(chrono::Local::now().timestamp() as usize), - file_data: Some(tmpl::ITEM_MERGE.into()), - }) - } - - /// ## Script type (enhance) - /// create the enhanced item by using javascript quick.js - pub fn from_script(name: String, desc: String) -> Result { - let uid = help::get_uid("s"); - let file = format!("{uid}.js"); // js ext - - Ok(PrfItem { - uid: Some(uid), - itype: Some("script".into()), - name: Some(name), - desc: Some(desc), - file: Some(file), - url: None, - selected: None, - extra: None, - option: None, - updated: Some(chrono::Local::now().timestamp() as usize), - file_data: Some(tmpl::ITEM_SCRIPT.into()), - }) - } - - /// get the file data - pub fn read_file(&self) -> Result { - if self.file.is_none() { - bail!("could not find the file"); - } - - let file = self.file.clone().unwrap(); - let path = dirs::app_profiles_dir()?.join(file); - fs::read_to_string(path).context("failed to read the file") - } - - /// save the file data - pub fn save_file(&self, data: String) -> Result<()> { - if self.file.is_none() { - bail!("could not find the file"); - } - - let file = self.file.clone().unwrap(); - let path = dirs::app_profiles_dir()?.join(file); - fs::write(path, data.as_bytes()).context("failed to save the file") - } -} diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs deleted file mode 100644 index 788386a..0000000 --- a/src-tauri/src/config/profiles.rs +++ /dev/null @@ -1,280 +0,0 @@ -use super::prfitem::PrfItem; -use crate::utils::{dirs, help}; -use anyhow::{bail, Context, Result}; -use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; -use std::{fs, io::Write}; - -/// Define the `profiles.yaml` schema -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct IProfiles { - /// same as PrfConfig.current - pub current: Option, - - /// same as PrfConfig.chain - pub chain: Option>, - - /// record valid fields for clash - pub valid: Option>, - - /// profile list - pub items: Option>, -} - -macro_rules! patch { - ($lv: expr, $rv: expr, $key: tt) => { - if ($rv.$key).is_some() { - $lv.$key = $rv.$key; - } - }; -} - -impl IProfiles { - pub fn new() -> Self { - match dirs::profiles_path().and_then(|path| help::read_yaml::(&path)) { - Ok(mut profiles) => { - if profiles.items.is_none() { - profiles.items = Some(vec![]); - } - // compatible with the old old old version - profiles.items.as_mut().map(|items| { - for item in items.iter_mut() { - if item.uid.is_none() { - item.uid = Some(help::get_uid("d")); - } - } - }); - profiles - } - Err(err) => { - log::error!(target: "app", "{err}"); - Self::template() - } - } - } - - pub fn template() -> Self { - Self { - valid: Some(vec!["dns".into(), "sub-rules".into(), "unified-delay".into()]), - items: Some(vec![]), - ..Self::default() - } - } - - pub fn save_file(&self) -> Result<()> { - help::save_yaml( - &dirs::profiles_path()?, - self, - Some("# Profiles Config for Clash Verge"), - ) - } - - /// 只修改current,valid和chain - pub fn patch_config(&mut self, patch: IProfiles) -> Result<()> { - if self.items.is_none() { - self.items = Some(vec![]); - } - - if let Some(current) = patch.current { - let items = self.items.as_ref().unwrap(); - let some_uid = Some(current); - - if items.iter().any(|e| e.uid == some_uid) { - self.current = some_uid; - } - } - - if let Some(chain) = patch.chain { - self.chain = Some(chain); - } - - if let Some(valid) = patch.valid { - self.valid = Some(valid); - } - - Ok(()) - } - - pub fn get_current(&self) -> Option { - self.current.clone() - } - - /// get items ref - pub fn get_items(&self) -> Option<&Vec> { - self.items.as_ref() - } - - /// find the item by the uid - pub fn get_item(&self, uid: &String) -> Result<&PrfItem> { - if let Some(items) = self.items.as_ref() { - let some_uid = Some(uid.clone()); - - for each in items.iter() { - if each.uid == some_uid { - return Ok(each); - } - } - } - - bail!("failed to get the profile item \"uid:{uid}\""); - } - - /// append new item - /// if the file_data is some - /// then should save the data to file - pub fn append_item(&mut self, mut item: PrfItem) -> Result<()> { - if item.uid.is_none() { - bail!("the uid should not be null"); - } - - // save the file data - // move the field value after save - if let Some(file_data) = item.file_data.take() { - if item.file.is_none() { - bail!("the file should not be null"); - } - - let file = item.file.clone().unwrap(); - let path = dirs::app_profiles_dir()?.join(&file); - - fs::File::create(path) - .with_context(|| format!("failed to create file \"{}\"", file))? - .write(file_data.as_bytes()) - .with_context(|| format!("failed to write to file \"{}\"", file))?; - } - - if self.items.is_none() { - self.items = Some(vec![]); - } - - self.items.as_mut().map(|items| items.push(item)); - self.save_file() - } - - /// update the item value - pub fn patch_item(&mut self, uid: String, item: PrfItem) -> Result<()> { - let mut items = self.items.take().unwrap_or(vec![]); - - for each in items.iter_mut() { - if each.uid == Some(uid.clone()) { - patch!(each, item, itype); - patch!(each, item, name); - patch!(each, item, desc); - patch!(each, item, file); - patch!(each, item, url); - patch!(each, item, selected); - patch!(each, item, extra); - patch!(each, item, updated); - patch!(each, item, option); - - self.items = Some(items); - return self.save_file(); - } - } - - self.items = Some(items); - bail!("failed to find the profile item \"uid:{uid}\"") - } - - /// be used to update the remote item - /// only patch `updated` `extra` `file_data` - pub fn update_item(&mut self, uid: String, mut item: PrfItem) -> Result<()> { - if self.items.is_none() { - self.items = Some(vec![]); - } - - // find the item - let _ = self.get_item(&uid)?; - - if let Some(items) = self.items.as_mut() { - let some_uid = Some(uid.clone()); - - for each in items.iter_mut() { - if each.uid == some_uid { - each.extra = item.extra; - each.updated = item.updated; - - // save the file data - // move the field value after save - if let Some(file_data) = item.file_data.take() { - let file = each.file.take(); - let file = - file.unwrap_or(item.file.take().unwrap_or(format!("{}.yaml", &uid))); - - // the file must exists - each.file = Some(file.clone()); - - let path = dirs::app_profiles_dir()?.join(&file); - - fs::File::create(path) - .with_context(|| format!("failed to create file \"{}\"", file))? - .write(file_data.as_bytes()) - .with_context(|| format!("failed to write to file \"{}\"", file))?; - } - - break; - } - } - } - - self.save_file() - } - - /// delete item - /// if delete the current then return true - pub fn delete_item(&mut self, uid: String) -> Result { - let current = self.current.as_ref().unwrap_or(&uid); - let current = current.clone(); - - let mut items = self.items.take().unwrap_or(vec![]); - let mut index = None; - - // get the index - for i in 0..items.len() { - if items[i].uid == Some(uid.clone()) { - index = Some(i); - break; - } - } - - if let Some(index) = index { - items.remove(index).file.map(|file| { - let _ = dirs::app_profiles_dir().map(|path| { - let path = path.join(file); - if path.exists() { - let _ = fs::remove_file(path); - } - }); - }); - } - - // delete the original uid - if current == uid { - self.current = match items.len() > 0 { - true => items[0].uid.clone(), - false => None, - }; - } - - self.items = Some(items); - self.save_file()?; - Ok(current == uid) - } - - /// 获取current指向的配置内容 - pub fn current_mapping(&self) -> Result { - match (self.current.as_ref(), self.items.as_ref()) { - (Some(current), Some(items)) => { - if let Some(item) = items.iter().find(|e| e.uid.as_ref() == Some(current)) { - let file_path = match item.file.as_ref() { - Some(file) => dirs::app_profiles_dir()?.join(file), - None => bail!("failed to get the file field"), - }; - return Ok(help::read_merge_mapping(&file_path)?); - } - bail!("failed to find the current profile \"uid:{current}\""); - } - _ => Ok(Mapping::new()), - } - } -} diff --git a/src-tauri/src/config/runtime.rs b/src-tauri/src/config/runtime.rs deleted file mode 100644 index cce376b..0000000 --- a/src-tauri/src/config/runtime.rs +++ /dev/null @@ -1,31 +0,0 @@ -use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; -use std::collections::HashMap; - -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct IRuntime { - pub config: Option, - // 记录在配置中(包括merge和script生成的)出现过的keys - // 这些keys不一定都生效 - pub exists_keys: Vec, - pub chain_logs: HashMap>, -} - -impl IRuntime { - pub fn new() -> Self { - Self::default() - } - - // 这里只更改 allow-lan | ipv6 | log-level - pub fn patch_config(&mut self, patch: Mapping) { - if let Some(config) = self.config.as_mut() { - ["allow-lan", "ipv6", "log-level"] - .into_iter() - .for_each(|key| { - if let Some(value) = patch.get(key).to_owned() { - config.insert(key.into(), value.clone()); - } - }); - } - } -} diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs deleted file mode 100644 index 961280e..0000000 --- a/src-tauri/src/config/verge.rs +++ /dev/null @@ -1,224 +0,0 @@ -use crate::utils::{dirs, help}; -use anyhow::Result; -use log::LevelFilter; -use serde::{Deserialize, Serialize}; - -/// ### `verge.yaml` schema -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct IVerge { - /// app listening port for app singleton - pub app_singleton_port: Option, - - /// app log level - /// silent | error | warn | info | debug | trace - pub app_log_level: Option, - - // i18n - pub language: Option, - - /// `light` or `dark` or `system` - pub theme_mode: Option, - - /// enable blur mode - /// maybe be able to set the alpha - pub theme_blur: Option, - - /// enable traffic graph default is true - pub traffic_graph: Option, - - /// show memory info (only for Clash Meta) - pub enable_memory_usage: Option, - - /// clash tun mode - pub enable_tun_mode: Option, - - /// windows service mode - #[serde(skip_serializing_if = "Option::is_none")] - pub enable_service_mode: Option, - - /// can the app auto startup - pub enable_auto_launch: Option, - - /// not show the window on launch - pub enable_silent_start: Option, - - /// set system proxy - pub enable_system_proxy: Option, - - /// enable proxy guard - pub enable_proxy_guard: Option, - - /// set system proxy bypass - pub system_proxy_bypass: Option, - - /// proxy guard duration - pub proxy_guard_duration: Option, - - /// theme setting - pub theme_setting: Option, - - /// web ui list - pub web_ui_list: Option>, - - /// clash core path - #[serde(skip_serializing_if = "Option::is_none")] - pub clash_core: Option, - - /// hotkey map - /// format: {func},{key} - pub hotkeys: Option>, - - /// 切换代理时自动关闭连接 - pub auto_close_connection: Option, - - /// 默认的延迟测试连接 - pub default_latency_test: Option, - - /// 支持关闭字段过滤,避免meta的新字段都被过滤掉,默认为真 - pub enable_clash_fields: Option, - - /// 是否使用内部的脚本支持,默认为真 - pub enable_builtin_enhanced: Option, - - /// proxy 页面布局 列数 - pub proxy_layout_column: Option, - - /// 日志清理 - /// 0: 不清理; 1: 7天; 2: 30天; 3: 90天 - pub auto_log_clean: Option, - - /// window size and position - #[serde(skip_serializing_if = "Option::is_none")] - pub window_size_position: Option>, -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct IVergeTheme { - pub primary_color: Option, - pub secondary_color: Option, - pub primary_text: Option, - pub secondary_text: Option, - - pub info_color: Option, - pub error_color: Option, - pub warning_color: Option, - pub success_color: Option, - - pub font_family: Option, - pub css_injection: Option, -} - -impl IVerge { - pub fn new() -> Self { - match dirs::verge_path().and_then(|path| help::read_yaml::(&path)) { - Ok(config) => config, - Err(err) => { - log::error!(target: "app", "{err}"); - Self::template() - } - } - } - - pub fn template() -> Self { - Self { - clash_core: match cfg!(feature = "default-meta") { - false => Some("clash".into()), - true => Some("clash-meta".into()), - }, - language: match cfg!(feature = "default-meta") { - false => Some("en".into()), - true => Some("zh".into()), - }, - theme_mode: Some("system".into()), - theme_blur: Some(false), - traffic_graph: Some(true), - enable_memory_usage: Some(true), - enable_auto_launch: Some(false), - enable_silent_start: Some(false), - enable_system_proxy: Some(false), - enable_proxy_guard: Some(false), - proxy_guard_duration: Some(30), - auto_close_connection: Some(true), - enable_builtin_enhanced: Some(true), - enable_clash_fields: Some(true), - auto_log_clean: Some(3), - ..Self::default() - } - } - - /// Save IVerge App Config - pub fn save_file(&self) -> Result<()> { - help::save_yaml(&dirs::verge_path()?, &self, Some("# Clash Verge Config")) - } - - /// patch verge config - /// only save to file - pub fn patch_config(&mut self, patch: IVerge) { - macro_rules! patch { - ($key: tt) => { - if patch.$key.is_some() { - self.$key = patch.$key; - } - }; - } - - patch!(app_log_level); - patch!(language); - patch!(theme_mode); - patch!(theme_blur); - patch!(traffic_graph); - patch!(enable_memory_usage); - - patch!(enable_tun_mode); - patch!(enable_service_mode); - patch!(enable_auto_launch); - patch!(enable_silent_start); - patch!(enable_system_proxy); - patch!(enable_proxy_guard); - patch!(system_proxy_bypass); - patch!(proxy_guard_duration); - - patch!(theme_setting); - patch!(web_ui_list); - patch!(clash_core); - patch!(hotkeys); - - patch!(auto_close_connection); - patch!(default_latency_test); - patch!(enable_builtin_enhanced); - patch!(proxy_layout_column); - patch!(enable_clash_fields); - patch!(auto_log_clean); - patch!(window_size_position); - } - - /// 在初始化前尝试拿到单例端口的值 - pub fn get_singleton_port() -> u16 { - #[cfg(not(feature = "verge-dev"))] - const SERVER_PORT: u16 = 33331; - #[cfg(feature = "verge-dev")] - const SERVER_PORT: u16 = 11233; - - match dirs::verge_path().and_then(|path| help::read_yaml::(&path)) { - Ok(config) => config.app_singleton_port.unwrap_or(SERVER_PORT), - Err(_) => SERVER_PORT, // 这里就不log错误了 - } - } - - /// 获取日志等级 - pub fn get_log_level(&self) -> LevelFilter { - if let Some(level) = self.app_log_level.as_ref() { - match level.to_lowercase().as_str() { - "silent" => LevelFilter::Off, - "error" => LevelFilter::Error, - "warn" => LevelFilter::Warn, - "info" => LevelFilter::Info, - "debug" => LevelFilter::Debug, - "trace" => LevelFilter::Trace, - _ => LevelFilter::Info, - } - } else { - LevelFilter::Info - } - } -} diff --git a/src-tauri/src/core/clash_api.rs b/src-tauri/src/core/clash_api.rs deleted file mode 100644 index 0636b41..0000000 --- a/src-tauri/src/core/clash_api.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::config::Config; -use anyhow::{bail, Result}; -use reqwest::header::HeaderMap; -use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; -use std::collections::HashMap; - -/// PUT /configs -/// path 是绝对路径 -pub async fn put_configs(path: &str) -> Result<()> { - let (url, headers) = clash_client_info()?; - let url = format!("{url}/configs"); - - let mut data = HashMap::new(); - data.insert("path", path); - - let client = reqwest::ClientBuilder::new().no_proxy().build()?; - let builder = client.put(&url).headers(headers).json(&data); - let response = builder.send().await?; - - match response.status().as_u16() { - 204 => Ok(()), - status @ _ => { - bail!("failed to put configs with status \"{status}\"") - } - } -} - -/// PATCH /configs -pub async fn patch_configs(config: &Mapping) -> Result<()> { - let (url, headers) = clash_client_info()?; - let url = format!("{url}/configs"); - - let client = reqwest::ClientBuilder::new().no_proxy().build()?; - let builder = client.patch(&url).headers(headers.clone()).json(config); - builder.send().await?; - Ok(()) -} - -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct DelayRes { - delay: u64, -} - -/// GET /proxies/{name}/delay -/// 获取代理延迟 -pub async fn get_proxy_delay(name: String, test_url: Option) -> Result { - let (url, headers) = clash_client_info()?; - let url = format!("{url}/proxies/{name}/delay"); - - let default_url = "http://www.gstatic.com/generate_204"; - let test_url = test_url - .map(|s| if s.is_empty() { default_url.into() } else { s }) - .unwrap_or(default_url.into()); - - let client = reqwest::ClientBuilder::new().no_proxy().build()?; - let builder = client - .get(&url) - .headers(headers) - .query(&[("timeout", "10000"), ("url", &test_url)]); - let response = builder.send().await?; - - Ok(response.json::().await?) -} - -/// 根据clash info获取clash服务地址和请求头 -fn clash_client_info() -> Result<(String, HeaderMap)> { - let client = { Config::clash().data().get_client_info() }; - - let server = format!("http://{}", client.server); - - let mut headers = HeaderMap::new(); - headers.insert("Content-Type", "application/json".parse()?); - - if let Some(secret) = client.secret { - let secret = format!("Bearer {}", secret).parse()?; - headers.insert("Authorization", secret); - } - - Ok((server, headers)) -} - -/// 缩短clash的日志 -pub fn parse_log(log: String) -> String { - if log.starts_with("time=") && log.len() > 33 { - return (&log[33..]).to_owned(); - } - if log.len() > 9 { - return (&log[9..]).to_owned(); - } - return log; -} - -/// 缩短clash -t的错误输出 -/// 仅适配 clash p核 8-26、clash meta 1.13.1 -pub fn parse_check_output(log: String) -> String { - let t = log.find("time="); - let m = log.find("msg="); - let mr = log.rfind('"'); - - if let (Some(_), Some(m), Some(mr)) = (t, m, mr) { - let e = match log.find("level=error msg=") { - Some(e) => e + 17, - None => m + 5, - }; - - if mr > m { - return (&log[e..mr]).to_owned(); - } - } - - let l = log.find("error="); - let r = log.find("path=").or(Some(log.len())); - - if let (Some(l), Some(r)) = (l, r) { - return (&log[(l + 6)..(r - 1)]).to_owned(); - } - - log -} - -#[test] -fn test_parse_check_output() { - let str1 = r#"xxxx\n time="2022-11-18T20:42:58+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'""#; - let str2 = r#"20:43:49 ERR [Config] configuration file test failed error=proxy 0: unsupport proxy type: hysteria path=xxx"#; - let str3 = r#" - "time="2022-11-18T21:38:01+08:00" level=info msg="Start initial configuration in progress" - time="2022-11-18T21:38:01+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'" - configuration file xxx\n - "#; - - let res1 = parse_check_output(str1.into()); - let res2 = parse_check_output(str2.into()); - let res3 = parse_check_output(str3.into()); - - println!("res1: {res1}"); - println!("res2: {res2}"); - println!("res3: {res3}"); - - assert_eq!(res1, res3); -} diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs deleted file mode 100644 index 6b3053b..0000000 --- a/src-tauri/src/core/core.rs +++ /dev/null @@ -1,325 +0,0 @@ -use super::{clash_api, logger::Logger}; -use crate::log_err; -use crate::{config::*, utils::dirs}; -use anyhow::{bail, Context, Result}; -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::{fs, io::Write, sync::Arc, time::Duration}; -use sysinfo::{Pid, PidExt, ProcessExt, System, SystemExt}; -use tauri::api::process::{Command, CommandChild, CommandEvent}; -use tokio::time::sleep; - -#[derive(Debug)] -pub struct CoreManager { - sidecar: Arc>>, - - #[allow(unused)] - use_service_mode: Arc>, -} - -impl CoreManager { - pub fn global() -> &'static CoreManager { - static CORE_MANAGER: OnceCell = OnceCell::new(); - - CORE_MANAGER.get_or_init(|| CoreManager { - sidecar: Arc::new(Mutex::new(None)), - use_service_mode: Arc::new(Mutex::new(false)), - }) - } - - pub fn init(&self) -> Result<()> { - // kill old clash process - let _ = dirs::clash_pid_path() - .and_then(|path| fs::read(path).map(|p| p.to_vec()).context("")) - .and_then(|pid| String::from_utf8_lossy(&pid).parse().context("")) - .map(|pid| { - let mut system = System::new(); - system.refresh_all(); - system.process(Pid::from_u32(pid)).map(|proc| { - if proc.name().contains("clash") { - log::debug!(target: "app", "kill old clash process"); - proc.kill(); - } - }); - }); - - tauri::async_runtime::spawn(async { - // 启动clash - log_err!(Self::global().run_core().await); - }); - - Ok(()) - } - - /// 检查配置是否正确 - pub fn check_config(&self) -> Result<()> { - let config_path = Config::generate_file(ConfigType::Check)?; - let config_path = dirs::path_to_str(&config_path)?; - - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("clash".into()); - - let app_dir = dirs::app_home_dir()?; - let app_dir = dirs::path_to_str(&app_dir)?; - - let output = Command::new_sidecar(clash_core)? - .args(["-t", "-d", app_dir, "-f", config_path]) - .output()?; - - if !output.status.success() { - let error = clash_api::parse_check_output(output.stdout.clone()); - let error = match error.len() > 0 { - true => error, - false => output.stdout.clone(), - }; - Logger::global().set_log(output.stdout); - bail!("{error}"); - } - - Ok(()) - } - - /// 启动核心 - pub async fn run_core(&self) -> Result<()> { - let config_path = Config::generate_file(ConfigType::Run)?; - - #[allow(unused_mut)] - let mut should_kill = match self.sidecar.lock().take() { - Some(child) => { - log::debug!(target: "app", "stop the core by sidecar"); - let _ = child.kill(); - true - } - None => false, - }; - - #[cfg(target_os = "windows")] - if *self.use_service_mode.lock() { - log::debug!(target: "app", "stop the core by service"); - log_err!(super::win_service::stop_core_by_service().await); - should_kill = true; - } - - // 这里得等一会儿 - if should_kill { - sleep(Duration::from_millis(500)).await; - } - - #[cfg(target_os = "windows")] - { - use super::win_service; - - // 服务模式 - let enable = { Config::verge().latest().enable_service_mode.clone() }; - let enable = enable.unwrap_or(false); - - *self.use_service_mode.lock() = enable; - - if enable { - // 服务模式启动失败就直接运行sidecar - log::debug!(target: "app", "try to run core in service mode"); - - match (|| async { - win_service::check_service().await?; - win_service::run_core_by_service(&config_path).await - })() - .await - { - Ok(_) => return Ok(()), - Err(err) => { - // 修改这个值,免得stop出错 - *self.use_service_mode.lock() = false; - log::error!(target: "app", "{err}"); - } - } - } - } - - let app_dir = dirs::app_home_dir()?; - let app_dir = dirs::path_to_str(&app_dir)?; - - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("clash".into()); - let is_clash = clash_core == "clash"; - - let config_path = dirs::path_to_str(&config_path)?; - - // fix #212 - let args = match clash_core.as_str() { - "clash-meta" => vec!["-m", "-d", app_dir, "-f", config_path], - _ => vec!["-d", app_dir, "-f", config_path], - }; - - let cmd = Command::new_sidecar(clash_core)?; - let (mut rx, cmd_child) = cmd.args(args).spawn()?; - - // 将pid写入文件中 - crate::log_err!((|| { - let pid = cmd_child.pid(); - let path = dirs::clash_pid_path()?; - fs::File::create(path) - .context("failed to create the pid file")? - .write(format!("{pid}").as_bytes()) - .context("failed to write pid to the file")?; - >::Ok(()) - })()); - - let mut sidecar = self.sidecar.lock(); - *sidecar = Some(cmd_child); - drop(sidecar); - - tauri::async_runtime::spawn(async move { - while let Some(event) = rx.recv().await { - match event { - CommandEvent::Stdout(line) => { - if is_clash { - let stdout = clash_api::parse_log(line.clone()); - log::info!(target: "app", "[clash]: {stdout}"); - } else { - log::info!(target: "app", "[clash]: {line}"); - }; - Logger::global().set_log(line); - } - CommandEvent::Stderr(err) => { - // let stdout = clash_api::parse_log(err.clone()); - log::error!(target: "app", "[clash]: {err}"); - Logger::global().set_log(err); - } - CommandEvent::Error(err) => { - log::error!(target: "app", "[clash]: {err}"); - Logger::global().set_log(err); - } - CommandEvent::Terminated(_) => { - log::info!(target: "app", "clash core terminated"); - let _ = CoreManager::global().recover_core(); - break; - } - _ => {} - } - } - }); - - Ok(()) - } - - /// 重启内核 - pub fn recover_core(&'static self) -> Result<()> { - // 服务模式不管 - #[cfg(target_os = "windows")] - if *self.use_service_mode.lock() { - return Ok(()); - } - - // 清空原来的sidecar值 - if let Some(sidecar) = self.sidecar.lock().take() { - let _ = sidecar.kill(); - } - - tauri::async_runtime::spawn(async move { - // 6秒之后再查看服务是否正常 (时间随便搞的) - // terminated 可能是切换内核 (切换内核已经有500ms的延迟) - sleep(Duration::from_millis(6666)).await; - - if self.sidecar.lock().is_none() { - log::info!(target: "app", "recover clash core"); - - // 重新启动app - if let Err(err) = self.run_core().await { - log::error!(target: "app", "failed to recover clash core"); - log::error!(target: "app", "{err}"); - - let _ = self.recover_core(); - } - } - }); - - Ok(()) - } - - /// 停止核心运行 - pub fn stop_core(&self) -> Result<()> { - #[cfg(target_os = "windows")] - if *self.use_service_mode.lock() { - log::debug!(target: "app", "stop the core by service"); - tauri::async_runtime::block_on(async move { - log_err!(super::win_service::stop_core_by_service().await); - }); - return Ok(()); - } - - let mut sidecar = self.sidecar.lock(); - if let Some(child) = sidecar.take() { - log::debug!(target: "app", "stop the core by sidecar"); - let _ = child.kill(); - } - Ok(()) - } - - /// 切换核心 - pub async fn change_core(&self, clash_core: Option) -> Result<()> { - let clash_core = clash_core.ok_or(anyhow::anyhow!("clash core is null"))?; - - if &clash_core != "clash" && &clash_core != "clash-meta" { - bail!("invalid clash core name \"{clash_core}\""); - } - - log::debug!(target: "app", "change core to `{clash_core}`"); - - Config::verge().draft().clash_core = Some(clash_core); - - // 更新配置 - Config::generate()?; - - self.check_config()?; - - // 清掉旧日志 - Logger::global().clear_log(); - - match self.run_core().await { - Ok(_) => { - Config::verge().apply(); - Config::runtime().apply(); - log_err!(Config::verge().latest().save_file()); - Ok(()) - } - Err(err) => { - Config::verge().discard(); - Config::runtime().discard(); - Err(err) - } - } - } - - /// 更新proxies那些 - /// 如果涉及端口和外部控制则需要重启 - pub async fn update_config(&self) -> Result<()> { - log::debug!(target: "app", "try to update clash config"); - - // 更新配置 - Config::generate()?; - - // 检查配置是否正常 - self.check_config()?; - - // 更新运行时配置 - let path = Config::generate_file(ConfigType::Run)?; - let path = dirs::path_to_str(&path)?; - - // 发送请求 发送5次 - for i in 0..5 { - match clash_api::put_configs(path).await { - Ok(_) => break, - Err(err) => { - if i < 4 { - log::info!(target: "app", "{err}"); - } else { - bail!(err); - } - } - } - sleep(Duration::from_millis(250)).await; - } - - Ok(()) - } -} diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs deleted file mode 100644 index 5b46cea..0000000 --- a/src-tauri/src/core/handle.rs +++ /dev/null @@ -1,77 +0,0 @@ -use super::tray::Tray; -use crate::log_err; -use anyhow::{bail, Result}; -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::sync::Arc; -use tauri::{AppHandle, Manager, Window}; - -#[derive(Debug, Default, Clone)] -pub struct Handle { - pub app_handle: Arc>>, -} - -impl Handle { - pub fn global() -> &'static Handle { - static HANDLE: OnceCell = OnceCell::new(); - - HANDLE.get_or_init(|| Handle { - app_handle: Arc::new(Mutex::new(None)), - }) - } - - pub fn init(&self, app_handle: AppHandle) { - *self.app_handle.lock() = Some(app_handle); - } - - pub fn get_window(&self) -> Option { - self.app_handle - .lock() - .as_ref() - .map_or(None, |a| a.get_window("main")) - } - - pub fn refresh_clash() { - if let Some(window) = Self::global().get_window() { - log_err!(window.emit("verge://refresh-clash-config", "yes")); - } - } - - pub fn refresh_verge() { - if let Some(window) = Self::global().get_window() { - log_err!(window.emit("verge://refresh-verge-config", "yes")); - } - } - - #[allow(unused)] - pub fn refresh_profiles() { - if let Some(window) = Self::global().get_window() { - log_err!(window.emit("verge://refresh-profiles-config", "yes")); - } - } - - pub fn notice_message, M: Into>(status: S, msg: M) { - if let Some(window) = Self::global().get_window() { - log_err!(window.emit("verge://notice-message", (status.into(), msg.into()))); - } - } - - pub fn update_systray() -> Result<()> { - let app_handle = Self::global().app_handle.lock(); - if app_handle.is_none() { - bail!("update_systray unhandled error"); - } - Tray::update_systray(app_handle.as_ref().unwrap())?; - Ok(()) - } - - /// update the system tray state - pub fn update_systray_part() -> Result<()> { - let app_handle = Self::global().app_handle.lock(); - if app_handle.is_none() { - bail!("update_systray unhandled error"); - } - Tray::update_part(app_handle.as_ref().unwrap())?; - Ok(()) - } -} diff --git a/src-tauri/src/core/hotkey.rs b/src-tauri/src/core/hotkey.rs deleted file mode 100644 index cd4c149..0000000 --- a/src-tauri/src/core/hotkey.rs +++ /dev/null @@ -1,181 +0,0 @@ -use crate::{config::Config, feat, log_err}; -use anyhow::{bail, Result}; -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::{collections::HashMap, sync::Arc}; -use tauri::{AppHandle, GlobalShortcutManager}; -use wry::application::accelerator::Accelerator; - -pub struct Hotkey { - current: Arc>>, // 保存当前的热键设置 - - app_handle: Arc>>, -} - -impl Hotkey { - pub fn global() -> &'static Hotkey { - static HOTKEY: OnceCell = OnceCell::new(); - - HOTKEY.get_or_init(|| Hotkey { - current: Arc::new(Mutex::new(Vec::new())), - app_handle: Arc::new(Mutex::new(None)), - }) - } - - pub fn init(&self, app_handle: AppHandle) -> Result<()> { - *self.app_handle.lock() = Some(app_handle); - - let verge = Config::verge(); - - if let Some(hotkeys) = verge.latest().hotkeys.as_ref() { - for hotkey in hotkeys.iter() { - let mut iter = hotkey.split(','); - let func = iter.next(); - let key = iter.next(); - - match (key, func) { - (Some(key), Some(func)) => { - log_err!(Self::check_key(key).and_then(|_| self.register(key, func))); - } - _ => { - let key = key.unwrap_or("None"); - let func = func.unwrap_or("None"); - log::error!(target: "app", "invalid hotkey `{key}`:`{func}`"); - } - } - } - *self.current.lock() = hotkeys.clone(); - } - - Ok(()) - } - - /// 检查一个键是否合法 - fn check_key(hotkey: &str) -> Result<()> { - // fix #287 - // tauri的这几个方法全部有Result expect,会panic,先检测一遍避免挂了 - if hotkey.parse::().is_err() { - bail!("invalid hotkey `{hotkey}`"); - } - Ok(()) - } - - fn get_manager(&self) -> Result { - let app_handle = self.app_handle.lock(); - if app_handle.is_none() { - bail!("failed to get the hotkey manager"); - } - Ok(app_handle.as_ref().unwrap().global_shortcut_manager()) - } - - fn register(&self, hotkey: &str, func: &str) -> Result<()> { - let mut manager = self.get_manager()?; - - if manager.is_registered(hotkey)? { - manager.unregister(hotkey)?; - } - - let f = match func.trim() { - "open_dashboard" => || feat::open_dashboard(), - "clash_mode_rule" => || feat::change_clash_mode("rule".into()), - "clash_mode_global" => || feat::change_clash_mode("global".into()), - "clash_mode_direct" => || feat::change_clash_mode("direct".into()), - "clash_mode_script" => || feat::change_clash_mode("script".into()), - "toggle_system_proxy" => || feat::toggle_system_proxy(), - "enable_system_proxy" => || feat::enable_system_proxy(), - "disable_system_proxy" => || feat::disable_system_proxy(), - "toggle_tun_mode" => || feat::toggle_tun_mode(), - "enable_tun_mode" => || feat::enable_tun_mode(), - "disable_tun_mode" => || feat::disable_tun_mode(), - - _ => bail!("invalid function \"{func}\""), - }; - - manager.register(hotkey, f)?; - log::info!(target: "app", "register hotkey {hotkey} {func}"); - Ok(()) - } - - fn unregister(&self, hotkey: &str) -> Result<()> { - self.get_manager()?.unregister(&hotkey)?; - log::info!(target: "app", "unregister hotkey {hotkey}"); - Ok(()) - } - - pub fn update(&self, new_hotkeys: Vec) -> Result<()> { - let mut current = self.current.lock(); - let old_map = Self::get_map_from_vec(¤t); - let new_map = Self::get_map_from_vec(&new_hotkeys); - - let (del, add) = Self::get_diff(old_map, new_map); - - // 先检查一遍所有新的热键是不是可以用的 - for (hotkey, _) in add.iter() { - Self::check_key(hotkey)?; - } - - del.iter().for_each(|key| { - let _ = self.unregister(key); - }); - - add.iter().for_each(|(key, func)| { - log_err!(self.register(key, func)); - }); - - *current = new_hotkeys; - Ok(()) - } - - fn get_map_from_vec<'a>(hotkeys: &'a Vec) -> HashMap<&'a str, &'a str> { - let mut map = HashMap::new(); - - hotkeys.iter().for_each(|hotkey| { - let mut iter = hotkey.split(','); - let func = iter.next(); - let key = iter.next(); - - if func.is_some() && key.is_some() { - let func = func.unwrap().trim(); - let key = key.unwrap().trim(); - map.insert(key, func); - } - }); - map - } - - fn get_diff<'a>( - old_map: HashMap<&'a str, &'a str>, - new_map: HashMap<&'a str, &'a str>, - ) -> (Vec<&'a str>, Vec<(&'a str, &'a str)>) { - let mut del_list = vec![]; - let mut add_list = vec![]; - - old_map.iter().for_each(|(&key, func)| { - match new_map.get(key) { - Some(new_func) => { - if new_func != func { - del_list.push(key); - add_list.push((key, *new_func)); - } - } - None => del_list.push(key), - }; - }); - - new_map.iter().for_each(|(&key, &func)| { - if old_map.get(key).is_none() { - add_list.push((key, func)); - } - }); - - (del_list, add_list) - } -} - -impl Drop for Hotkey { - fn drop(&mut self) { - if let Ok(mut manager) = self.get_manager() { - let _ = manager.unregister_all(); - } - } -} diff --git a/src-tauri/src/core/logger.rs b/src-tauri/src/core/logger.rs deleted file mode 100644 index b426415..0000000 --- a/src-tauri/src/core/logger.rs +++ /dev/null @@ -1,36 +0,0 @@ -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::{collections::VecDeque, sync::Arc}; - -const LOGS_QUEUE_LEN: usize = 100; - -pub struct Logger { - log_data: Arc>>, -} - -impl Logger { - pub fn global() -> &'static Logger { - static LOGGER: OnceCell = OnceCell::new(); - - LOGGER.get_or_init(|| Logger { - log_data: Arc::new(Mutex::new(VecDeque::with_capacity(LOGS_QUEUE_LEN + 10))), - }) - } - - pub fn get_log(&self) -> VecDeque { - self.log_data.lock().clone() - } - - pub fn set_log(&self, text: String) { - let mut logs = self.log_data.lock(); - if logs.len() > LOGS_QUEUE_LEN { - logs.pop_front(); - } - logs.push_back(text); - } - - pub fn clear_log(&self) { - let mut logs = self.log_data.lock(); - logs.clear(); - } -} diff --git a/src-tauri/src/core/manager.rs b/src-tauri/src/core/manager.rs deleted file mode 100644 index fdb9269..0000000 --- a/src-tauri/src/core/manager.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::borrow::Cow; - -/// 给clash内核的tun模式授权 -#[cfg(any(target_os = "macos", target_os = "linux"))] -pub fn grant_permission(core: String) -> anyhow::Result<()> { - use std::process::Command; - use tauri::utils::platform::current_exe; - - let path = current_exe()?.with_file_name(core).canonicalize()?; - let path = path.display().to_string(); - - log::debug!("grant_permission path: {path}"); - - #[cfg(target_os = "macos")] - let output = { - // the path of clash /Applications/Clash Verge.app/Contents/MacOS/clash - // https://apple.stackexchange.com/questions/82967/problem-with-empty-spaces-when-executing-shell-commands-in-applescript - // let path = escape(&path); - let path = path.replace(' ', "\\\\ "); - let shell = format!("chown root:admin {path}\nchmod +sx {path}"); - let command = format!(r#"do shell script "{shell}" with administrator privileges"#); - Command::new("osascript") - .args(vec!["-e", &command]) - .output()? - }; - - #[cfg(target_os = "linux")] - let output = { - let path = path.replace(' ', "\\ "); // 避免路径中有空格 - let shell = format!("setcap cap_net_bind_service,cap_net_admin=+ep {path}"); - - let sudo = match Command::new("which").arg("pkexec").output() { - Ok(output) => { - if output.stdout.is_empty() { - "sudo" - } else { - "pkexec" - } - } - Err(_) => "sudo", - }; - - Command::new(sudo).arg("sh").arg("-c").arg(shell).output()? - }; - - if output.status.success() { - Ok(()) - } else { - let stderr = std::str::from_utf8(&output.stderr).unwrap_or(""); - anyhow::bail!("{stderr}"); - } -} - -#[allow(unused)] -pub fn escape<'a>(text: &'a str) -> Cow<'a, str> { - let bytes = text.as_bytes(); - - let mut owned = None; - - for pos in 0..bytes.len() { - let special = match bytes[pos] { - b' ' => Some(b' '), - _ => None, - }; - if let Some(s) = special { - if owned.is_none() { - owned = Some(bytes[0..pos].to_owned()); - } - owned.as_mut().unwrap().push(b'\\'); - owned.as_mut().unwrap().push(b'\\'); - owned.as_mut().unwrap().push(s); - } else if let Some(owned) = owned.as_mut() { - owned.push(bytes[pos]); - } - } - - if let Some(owned) = owned { - unsafe { Cow::Owned(String::from_utf8_unchecked(owned)) } - } else { - unsafe { Cow::Borrowed(std::str::from_utf8_unchecked(bytes)) } - } -} diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs deleted file mode 100644 index 4221721..0000000 --- a/src-tauri/src/core/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub mod clash_api; -mod core; -pub mod handle; -pub mod hotkey; -pub mod logger; -pub mod manager; -pub mod sysopt; -pub mod timer; -pub mod tray; -pub mod win_service; - -pub use self::core::*; diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs deleted file mode 100644 index c43114e..0000000 --- a/src-tauri/src/core/sysopt.rs +++ /dev/null @@ -1,304 +0,0 @@ -use crate::{config::Config, log_err}; -use anyhow::{anyhow, Result}; -use auto_launch::{AutoLaunch, AutoLaunchBuilder}; -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::sync::Arc; -use sysproxy::Sysproxy; -use tauri::{async_runtime::Mutex as TokioMutex, utils::platform::current_exe}; - -pub struct Sysopt { - /// current system proxy setting - cur_sysproxy: Arc>>, - - /// record the original system proxy - /// recover it when exit - old_sysproxy: Arc>>, - - /// helps to auto launch the app - auto_launch: Arc>>, - - /// record whether the guard async is running or not - guard_state: Arc>, -} - -#[cfg(target_os = "windows")] -static DEFAULT_BYPASS: &str = "localhost;127.*;192.168.*;"; -#[cfg(target_os = "linux")] -static DEFAULT_BYPASS: &str = "localhost,127.0.0.1,::1"; -#[cfg(target_os = "macos")] -static DEFAULT_BYPASS: &str = "127.0.0.1,localhost,"; - -impl Sysopt { - pub fn global() -> &'static Sysopt { - static SYSOPT: OnceCell = OnceCell::new(); - - SYSOPT.get_or_init(|| Sysopt { - cur_sysproxy: Arc::new(Mutex::new(None)), - old_sysproxy: Arc::new(Mutex::new(None)), - auto_launch: Arc::new(Mutex::new(None)), - guard_state: Arc::new(TokioMutex::new(false)), - }) - } - - /// init the sysproxy - pub fn init_sysproxy(&self) -> Result<()> { - let port = { Config::clash().latest().get_mixed_port() }; - - let (enable, bypass) = { - let verge = Config::verge(); - let verge = verge.latest(); - ( - verge.enable_system_proxy.clone().unwrap_or(false), - verge.system_proxy_bypass.clone(), - ) - }; - - let current = Sysproxy { - enable, - host: String::from("127.0.0.1"), - port, - bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()), - }; - - if enable { - let old = Sysproxy::get_system_proxy().map_or(None, |p| Some(p)); - current.set_system_proxy()?; - - *self.old_sysproxy.lock() = old; - *self.cur_sysproxy.lock() = Some(current); - } - - // run the system proxy guard - self.guard_proxy(); - Ok(()) - } - - /// update the system proxy - pub fn update_sysproxy(&self) -> Result<()> { - let mut cur_sysproxy = self.cur_sysproxy.lock(); - let old_sysproxy = self.old_sysproxy.lock(); - - if cur_sysproxy.is_none() || old_sysproxy.is_none() { - drop(cur_sysproxy); - drop(old_sysproxy); - return self.init_sysproxy(); - } - - let (enable, bypass) = { - let verge = Config::verge(); - let verge = verge.latest(); - ( - verge.enable_system_proxy.clone().unwrap_or(false), - verge.system_proxy_bypass.clone(), - ) - }; - let mut sysproxy = cur_sysproxy.take().unwrap(); - - sysproxy.enable = enable; - sysproxy.bypass = bypass.unwrap_or(DEFAULT_BYPASS.into()); - - sysproxy.set_system_proxy()?; - *cur_sysproxy = Some(sysproxy); - - Ok(()) - } - - /// reset the sysproxy - pub fn reset_sysproxy(&self) -> Result<()> { - let mut cur_sysproxy = self.cur_sysproxy.lock(); - let mut old_sysproxy = self.old_sysproxy.lock(); - - let cur_sysproxy = cur_sysproxy.take(); - - if let Some(mut old) = old_sysproxy.take() { - // 如果原代理和当前代理 端口一致,就disable关闭,否则就恢复原代理设置 - // 当前没有设置代理的时候,不确定旧设置是否和当前一致,全关了 - let port_same = cur_sysproxy.map_or(true, |cur| old.port == cur.port); - - if old.enable && port_same { - old.enable = false; - log::info!(target: "app", "reset proxy by disabling the original proxy"); - } else { - log::info!(target: "app", "reset proxy to the original proxy"); - } - - old.set_system_proxy()?; - } else if let Some(mut cur @ Sysproxy { enable: true, .. }) = cur_sysproxy { - // 没有原代理,就按现在的代理设置disable即可 - log::info!(target: "app", "reset proxy by disabling the current proxy"); - cur.enable = false; - cur.set_system_proxy()?; - } else { - log::info!(target: "app", "reset proxy with no action"); - } - - Ok(()) - } - - /// init the auto launch - pub fn init_launch(&self) -> Result<()> { - let enable = { Config::verge().latest().enable_auto_launch.clone() }; - let enable = enable.unwrap_or(false); - - let app_exe = current_exe()?; - let app_exe = dunce::canonicalize(app_exe)?; - let app_name = app_exe - .file_stem() - .and_then(|f| f.to_str()) - .ok_or(anyhow!("failed to get file stem"))?; - - let app_path = app_exe - .as_os_str() - .to_str() - .ok_or(anyhow!("failed to get app_path"))? - .to_string(); - - // fix issue #26 - #[cfg(target_os = "windows")] - let app_path = format!("\"{app_path}\""); - - // use the /Applications/Clash Verge.app path - #[cfg(target_os = "macos")] - let app_path = (|| -> Option { - let path = std::path::PathBuf::from(&app_path); - let path = path.parent()?.parent()?.parent()?; - let extension = path.extension()?.to_str()?; - match extension == "app" { - true => Some(path.as_os_str().to_str()?.to_string()), - false => None, - } - })() - .unwrap_or(app_path); - - // fix #403 - #[cfg(target_os = "linux")] - let app_path = { - use crate::core::handle::Handle; - use tauri::Manager; - - let handle = Handle::global(); - match handle.app_handle.lock().as_ref() { - Some(app_handle) => { - let appimage = app_handle.env().appimage; - appimage - .and_then(|p| p.to_str().map(|s| s.to_string())) - .unwrap_or(app_path) - } - None => app_path, - } - }; - - let auto = AutoLaunchBuilder::new() - .set_app_name(app_name) - .set_app_path(&app_path) - .build()?; - - // 避免在开发时将自启动关了 - #[cfg(feature = "verge-dev")] - if !enable { - return Ok(()); - } - - #[cfg(target_os = "macos")] - { - if enable && !auto.is_enabled().unwrap_or(false) { - // 避免重复设置登录项 - let _ = auto.disable(); - auto.enable()?; - } else if !enable { - let _ = auto.disable(); - } - } - - #[cfg(not(target_os = "macos"))] - if enable { - auto.enable()?; - } - - *self.auto_launch.lock() = Some(auto); - - Ok(()) - } - - /// update the startup - pub fn update_launch(&self) -> Result<()> { - let auto_launch = self.auto_launch.lock(); - - if auto_launch.is_none() { - drop(auto_launch); - return self.init_launch(); - } - let enable = { Config::verge().latest().enable_auto_launch.clone() }; - let enable = enable.unwrap_or(false); - let auto_launch = auto_launch.as_ref().unwrap(); - - match enable { - true => auto_launch.enable()?, - false => log_err!(auto_launch.disable()), // 忽略关闭的错误 - }; - - Ok(()) - } - - /// launch a system proxy guard - /// read config from file directly - pub fn guard_proxy(&self) { - use tokio::time::{sleep, Duration}; - - let guard_state = self.guard_state.clone(); - - tauri::async_runtime::spawn(async move { - // if it is running, exit - let mut state = guard_state.lock().await; - if *state { - return; - } - *state = true; - drop(state); - - // default duration is 10s - let mut wait_secs = 10u64; - - loop { - sleep(Duration::from_secs(wait_secs)).await; - - let (enable, guard, guard_duration, bypass) = { - let verge = Config::verge(); - let verge = verge.latest(); - ( - verge.enable_system_proxy.clone().unwrap_or(false), - verge.enable_proxy_guard.clone().unwrap_or(false), - verge.proxy_guard_duration.clone().unwrap_or(10), - verge.system_proxy_bypass.clone(), - ) - }; - - // stop loop - if !enable || !guard { - break; - } - - // update duration - wait_secs = guard_duration; - - log::debug!(target: "app", "try to guard the system proxy"); - - let port = { Config::clash().latest().get_mixed_port() }; - - let sysproxy = Sysproxy { - enable: true, - host: "127.0.0.1".into(), - port, - bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()), - }; - - log_err!(sysproxy.set_system_proxy()); - } - - let mut state = guard_state.lock().await; - *state = false; - drop(state); - }); - } -} diff --git a/src-tauri/src/core/timer.rs b/src-tauri/src/core/timer.rs deleted file mode 100644 index 1b40f0f..0000000 --- a/src-tauri/src/core/timer.rs +++ /dev/null @@ -1,184 +0,0 @@ -use crate::config::Config; -use crate::feat; -use anyhow::{Context, Result}; -use delay_timer::prelude::{DelayTimer, DelayTimerBuilder, TaskBuilder}; -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::collections::HashMap; -use std::sync::Arc; - -type TaskID = u64; - -pub struct Timer { - /// cron manager - delay_timer: Arc>, - - /// save the current state - timer_map: Arc>>, - - /// increment id - timer_count: Arc>, -} - -impl Timer { - pub fn global() -> &'static Timer { - static TIMER: OnceCell = OnceCell::new(); - - TIMER.get_or_init(|| Timer { - delay_timer: Arc::new(Mutex::new(DelayTimerBuilder::default().build())), - timer_map: Arc::new(Mutex::new(HashMap::new())), - timer_count: Arc::new(Mutex::new(1)), - }) - } - - /// restore timer - pub fn init(&self) -> Result<()> { - self.refresh()?; - - let cur_timestamp = chrono::Local::now().timestamp(); - - let timer_map = self.timer_map.lock(); - let delay_timer = self.delay_timer.lock(); - - Config::profiles().latest().get_items().map(|items| { - items - .iter() - .filter_map(|item| { - // mins to seconds - let interval = ((item.option.as_ref()?.update_interval?) as i64) * 60; - let updated = item.updated? as i64; - - if interval > 0 && cur_timestamp - updated >= interval { - Some(item) - } else { - None - } - }) - .for_each(|item| { - if let Some(uid) = item.uid.as_ref() { - if let Some((task_id, _)) = timer_map.get(uid) { - crate::log_err!(delay_timer.advance_task(*task_id)); - } - } - }) - }); - - Ok(()) - } - - /// Correctly update all cron tasks - pub fn refresh(&self) -> Result<()> { - let diff_map = self.gen_diff(); - - let mut timer_map = self.timer_map.lock(); - let mut delay_timer = self.delay_timer.lock(); - - for (uid, diff) in diff_map.into_iter() { - match diff { - DiffFlag::Del(tid) => { - let _ = timer_map.remove(&uid); - crate::log_err!(delay_timer.remove_task(tid)); - } - DiffFlag::Add(tid, val) => { - let _ = timer_map.insert(uid.clone(), (tid, val)); - crate::log_err!(self.add_task(&mut delay_timer, uid, tid, val)); - } - DiffFlag::Mod(tid, val) => { - let _ = timer_map.insert(uid.clone(), (tid, val)); - crate::log_err!(delay_timer.remove_task(tid)); - crate::log_err!(self.add_task(&mut delay_timer, uid, tid, val)); - } - } - } - - Ok(()) - } - - /// generate a uid -> update_interval map - fn gen_map(&self) -> HashMap { - let mut new_map = HashMap::new(); - - if let Some(items) = Config::profiles().latest().get_items() { - for item in items.iter() { - if item.option.is_some() { - let option = item.option.as_ref().unwrap(); - let interval = option.update_interval.unwrap_or(0); - - if interval > 0 { - new_map.insert(item.uid.clone().unwrap(), interval); - } - } - } - } - - new_map - } - - /// generate the diff map for refresh - fn gen_diff(&self) -> HashMap { - let mut diff_map = HashMap::new(); - - let timer_map = self.timer_map.lock(); - - let new_map = self.gen_map(); - let cur_map = &timer_map; - - cur_map.iter().for_each(|(uid, (tid, val))| { - let new_val = new_map.get(uid).unwrap_or(&0); - - if *new_val == 0 { - diff_map.insert(uid.clone(), DiffFlag::Del(*tid)); - } else if new_val != val { - diff_map.insert(uid.clone(), DiffFlag::Mod(*tid, *new_val)); - } - }); - - let mut count = self.timer_count.lock(); - - new_map.iter().for_each(|(uid, val)| { - if cur_map.get(uid).is_none() { - diff_map.insert(uid.clone(), DiffFlag::Add(*count, *val)); - - *count += 1; - } - }); - - diff_map - } - - /// add a cron task - fn add_task( - &self, - delay_timer: &mut DelayTimer, - uid: String, - tid: TaskID, - minutes: u64, - ) -> Result<()> { - let task = TaskBuilder::default() - .set_task_id(tid) - .set_maximum_parallel_runnable_num(1) - .set_frequency_repeated_by_minutes(minutes) - // .set_frequency_repeated_by_seconds(minutes) // for test - .spawn_async_routine(move || Self::async_task(uid.to_owned())) - .context("failed to create timer task")?; - - delay_timer - .add_task(task) - .context("failed to add timer task")?; - - Ok(()) - } - - /// the task runner - async fn async_task(uid: String) { - log::info!(target: "app", "running timer task `{uid}`"); - crate::log_err!(feat::update_profile(uid, None).await); - } -} - -#[derive(Debug)] -enum DiffFlag { - Del(TaskID), - Add(TaskID, u64), - Mod(TaskID, u64), -} diff --git a/src-tauri/src/core/tray.rs b/src-tauri/src/core/tray.rs deleted file mode 100644 index 307e35d..0000000 --- a/src-tauri/src/core/tray.rs +++ /dev/null @@ -1,175 +0,0 @@ -use crate::{cmds, config::Config, feat, utils::resolve}; -use anyhow::Result; -use tauri::{ - api, AppHandle, CustomMenuItem, Manager, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, - SystemTraySubmenu, -}; - -pub struct Tray {} - -impl Tray { - pub fn tray_menu(app_handle: &AppHandle) -> SystemTrayMenu { - let zh = { Config::verge().latest().language == Some("zh".into()) }; - - let version = app_handle.package_info().version.to_string(); - - macro_rules! t { - ($en: expr, $zh: expr) => { - if zh { - $zh - } else { - $en - } - }; - } - - SystemTrayMenu::new() - .add_item(CustomMenuItem::new( - "open_window", - t!("Dashboard", "打开面板"), - )) - .add_native_item(SystemTrayMenuItem::Separator) - .add_item(CustomMenuItem::new( - "rule_mode", - t!("Rule Mode", "规则模式"), - )) - .add_item(CustomMenuItem::new( - "global_mode", - t!("Global Mode", "全局模式"), - )) - .add_item(CustomMenuItem::new( - "direct_mode", - t!("Direct Mode", "直连模式"), - )) - .add_item(CustomMenuItem::new( - "script_mode", - t!("Script Mode", "脚本模式"), - )) - .add_native_item(SystemTrayMenuItem::Separator) - .add_item(CustomMenuItem::new( - "system_proxy", - t!("System Proxy", "系统代理"), - )) - .add_item(CustomMenuItem::new("tun_mode", t!("TUN Mode", "Tun 模式"))) - .add_item(CustomMenuItem::new( - "copy_env", - t!("Copy Env", "复制环境变量"), - )) - .add_submenu(SystemTraySubmenu::new( - t!("Open Dir", "打开目录"), - SystemTrayMenu::new() - .add_item(CustomMenuItem::new( - "open_app_dir", - t!("App Dir", "应用目录"), - )) - .add_item(CustomMenuItem::new( - "open_core_dir", - t!("Core Dir", "内核目录"), - )) - .add_item(CustomMenuItem::new( - "open_logs_dir", - t!("Logs Dir", "日志目录"), - )), - )) - .add_submenu(SystemTraySubmenu::new( - t!("More", "更多"), - SystemTrayMenu::new() - .add_item(CustomMenuItem::new( - "restart_clash", - t!("Restart Clash", "重启 Clash"), - )) - .add_item(CustomMenuItem::new( - "restart_app", - t!("Restart App", "重启应用"), - )) - .add_item( - CustomMenuItem::new("app_version", format!("Version {version}")).disabled(), - ), - )) - .add_native_item(SystemTrayMenuItem::Separator) - .add_item(CustomMenuItem::new("quit", t!("Quit", "退出")).accelerator("CmdOrControl+Q")) - } - - pub fn update_systray(app_handle: &AppHandle) -> Result<()> { - app_handle - .tray_handle() - .set_menu(Tray::tray_menu(app_handle))?; - Tray::update_part(app_handle)?; - Ok(()) - } - - pub fn update_part(app_handle: &AppHandle) -> Result<()> { - let mode = { - Config::clash() - .latest() - .0 - .get("mode") - .map(|val| val.as_str().unwrap_or("rule")) - .unwrap_or("rule") - .to_owned() - }; - - let tray = app_handle.tray_handle(); - - let _ = tray.get_item("rule_mode").set_selected(mode == "rule"); - let _ = tray.get_item("global_mode").set_selected(mode == "global"); - let _ = tray.get_item("direct_mode").set_selected(mode == "direct"); - let _ = tray.get_item("script_mode").set_selected(mode == "script"); - - let verge = Config::verge(); - let verge = verge.latest(); - let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); - let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); - - #[cfg(target_os = "windows")] - { - let indication_icon = if *system_proxy { - include_bytes!("../../icons/win-tray-icon-activated.png").to_vec() - } else { - include_bytes!("../../icons/win-tray-icon.png").to_vec() - }; - - let _ = tray.set_icon(tauri::Icon::Raw(indication_icon)); - } - - let _ = tray.get_item("system_proxy").set_selected(*system_proxy); - let _ = tray.get_item("tun_mode").set_selected(*tun_mode); - - Ok(()) - } - - pub fn on_system_tray_event(app_handle: &AppHandle, event: SystemTrayEvent) { - match event { - SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { - mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => { - let mode = &mode[0..mode.len() - 5]; - feat::change_clash_mode(mode.into()); - } - - "open_window" => resolve::create_window(app_handle), - "system_proxy" => feat::toggle_system_proxy(), - "tun_mode" => feat::toggle_tun_mode(), - "copy_env" => feat::copy_clash_env(), - "open_app_dir" => crate::log_err!(cmds::open_app_dir()), - "open_core_dir" => crate::log_err!(cmds::open_core_dir()), - "open_logs_dir" => crate::log_err!(cmds::open_logs_dir()), - "restart_clash" => feat::restart_clash_core(), - "restart_app" => api::process::restart(&app_handle.env()), - "quit" => { - let _ = resolve::save_window_size_position(app_handle, true); - - resolve::resolve_reset(); - api::process::kill_children(); - app_handle.exit(0); - std::process::exit(0); - } - _ => {} - }, - #[cfg(target_os = "windows")] - SystemTrayEvent::LeftClick { .. } => { - resolve::create_window(app_handle); - } - _ => {} - } - } -} diff --git a/src-tauri/src/core/win_service.rs b/src-tauri/src/core/win_service.rs deleted file mode 100644 index 865895b..0000000 --- a/src-tauri/src/core/win_service.rs +++ /dev/null @@ -1,178 +0,0 @@ -#![cfg(target_os = "windows")] - -use crate::config::Config; -use crate::utils::dirs; -use anyhow::{bail, Context, Result}; -use deelevate::{PrivilegeLevel, Token}; -use runas::Command as RunasCommand; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use std::os::windows::process::CommandExt; -use std::path::PathBuf; -use std::time::Duration; -use std::{env::current_exe, process::Command as StdCommand}; -use tokio::time::sleep; - -const SERVICE_URL: &str = "http://127.0.0.1:33211"; - -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct ResponseBody { - pub core_type: Option, - pub bin_path: String, - pub config_dir: String, - pub log_file: String, -} - -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct JsonResponse { - pub code: u64, - pub msg: String, - pub data: Option, -} - -/// Install the Clash Verge Service -/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 -pub async fn install_service() -> Result<()> { - let binary_path = dirs::service_path()?; - let install_path = binary_path.with_file_name("install-service.exe"); - - if !install_path.exists() { - bail!("installer exe not found"); - } - - let token = Token::with_current_process()?; - let level = token.privilege_level()?; - - let status = match level { - PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).show(false).status()?, - _ => StdCommand::new(install_path) - .creation_flags(0x08000000) - .status()?, - }; - - if !status.success() { - bail!( - "failed to install service with status {}", - status.code().unwrap() - ); - } - - Ok(()) -} - -/// Uninstall the Clash Verge Service -/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 -pub async fn uninstall_service() -> Result<()> { - let binary_path = dirs::service_path()?; - let uninstall_path = binary_path.with_file_name("uninstall-service.exe"); - - if !uninstall_path.exists() { - bail!("uninstaller exe not found"); - } - - let token = Token::with_current_process()?; - let level = token.privilege_level()?; - - let status = match level { - PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).show(false).status()?, - _ => StdCommand::new(uninstall_path) - .creation_flags(0x08000000) - .status()?, - }; - - if !status.success() { - bail!( - "failed to uninstall service with status {}", - status.code().unwrap() - ); - } - - Ok(()) -} - -/// check the windows service status -pub async fn check_service() -> Result { - let url = format!("{SERVICE_URL}/get_clash"); - let response = reqwest::ClientBuilder::new() - .no_proxy() - .build()? - .get(url) - .send() - .await - .context("failed to connect to the Clash Verge Service")? - .json::() - .await - .context("failed to parse the Clash Verge Service response")?; - - Ok(response) -} - -/// start the clash by service -pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> { - let status = check_service().await?; - - if status.code == 0 { - stop_core_by_service().await?; - sleep(Duration::from_secs(1)).await; - } - - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("clash".into()); - - let clash_bin = format!("{clash_core}.exe"); - let bin_path = current_exe()?.with_file_name(clash_bin); - let bin_path = dirs::path_to_str(&bin_path)?; - - let config_dir = dirs::app_home_dir()?; - let config_dir = dirs::path_to_str(&config_dir)?; - - let log_path = dirs::service_log_file()?; - let log_path = dirs::path_to_str(&log_path)?; - - let config_file = dirs::path_to_str(config_file)?; - - let mut map = HashMap::new(); - map.insert("core_type", clash_core.as_str()); - map.insert("bin_path", bin_path); - map.insert("config_dir", config_dir); - map.insert("config_file", config_file); - map.insert("log_file", log_path); - - let url = format!("{SERVICE_URL}/start_clash"); - let res = reqwest::ClientBuilder::new() - .no_proxy() - .build()? - .post(url) - .json(&map) - .send() - .await? - .json::() - .await - .context("failed to connect to the Clash Verge Service")?; - - if res.code != 0 { - bail!(res.msg); - } - - Ok(()) -} - -/// stop the clash by service -pub(super) async fn stop_core_by_service() -> Result<()> { - let url = format!("{SERVICE_URL}/stop_clash"); - let res = reqwest::ClientBuilder::new() - .no_proxy() - .build()? - .post(url) - .send() - .await? - .json::() - .await - .context("failed to connect to the Clash Verge Service")?; - - if res.code != 0 { - bail!(res.msg); - } - - Ok(()) -} diff --git a/src-tauri/src/enhance/builtin/meta_guard.js b/src-tauri/src/enhance/builtin/meta_guard.js deleted file mode 100644 index be4183b..0000000 --- a/src-tauri/src/enhance/builtin/meta_guard.js +++ /dev/null @@ -1,6 +0,0 @@ -function main(params) { - if (params.mode === "script") { - params.mode = "rule"; - } - return params; -} diff --git a/src-tauri/src/enhance/builtin/meta_hy_alpn.js b/src-tauri/src/enhance/builtin/meta_hy_alpn.js deleted file mode 100644 index da1fac0..0000000 --- a/src-tauri/src/enhance/builtin/meta_hy_alpn.js +++ /dev/null @@ -1,10 +0,0 @@ -function main(params) { - if (Array.isArray(params.proxies)) { - params.proxies.forEach((p, i) => { - if (p.type === "hysteria" && typeof p.alpn === "string") { - params.proxies[i].alpn = [p.alpn]; - } - }); - } - return params; -} diff --git a/src-tauri/src/enhance/chain.rs b/src-tauri/src/enhance/chain.rs deleted file mode 100644 index 75c61fb..0000000 --- a/src-tauri/src/enhance/chain.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::{ - config::PrfItem, - utils::{dirs, help}, -}; -use serde_yaml::Mapping; -use std::fs; - -#[derive(Debug, Clone)] -pub struct ChainItem { - pub uid: String, - pub data: ChainType, -} - -#[derive(Debug, Clone)] -pub enum ChainType { - Merge(Mapping), - Script(String), -} - -#[derive(Debug, Clone)] -pub enum ChainSupport { - Clash, - ClashMeta, - All, -} - -impl From<&PrfItem> for Option { - fn from(item: &PrfItem) -> Self { - let itype = item.itype.as_ref()?.as_str(); - let file = item.file.clone()?; - let uid = item.uid.clone().unwrap_or("".into()); - let path = dirs::app_profiles_dir().ok()?.join(file); - - if !path.exists() { - return None; - } - - match itype { - "script" => Some(ChainItem { - uid, - data: ChainType::Script(fs::read_to_string(path).ok()?), - }), - "merge" => Some(ChainItem { - uid, - data: ChainType::Merge(help::read_merge_mapping(&path).ok()?), - }), - _ => None, - } - } -} - -impl ChainItem { - /// 内建支持一些脚本 - pub fn builtin() -> Vec<(ChainSupport, ChainItem)> { - // meta 的一些处理 - let meta_guard = - ChainItem::to_script("verge_meta_guard", include_str!("./builtin/meta_guard.js")); - - // meta 1.13.2 alpn string 转 数组 - let hy_alpn = - ChainItem::to_script("verge_hy_alpn", include_str!("./builtin/meta_hy_alpn.js")); - - vec![ - (ChainSupport::ClashMeta, hy_alpn), - (ChainSupport::ClashMeta, meta_guard), - ] - } - - pub fn to_script, D: Into>(uid: U, data: D) -> Self { - Self { - uid: uid.into(), - data: ChainType::Script(data.into()), - } - } -} - -impl ChainSupport { - pub fn is_support(&self, core: Option<&String>) -> bool { - match core { - Some(core) => match (self, core.as_str()) { - (ChainSupport::All, _) => true, - (ChainSupport::Clash, "clash") => true, - (ChainSupport::ClashMeta, "clash-meta") => true, - _ => false, - }, - None => true, - } - } -} diff --git a/src-tauri/src/enhance/field.rs b/src-tauri/src/enhance/field.rs deleted file mode 100644 index 2130b41..0000000 --- a/src-tauri/src/enhance/field.rs +++ /dev/null @@ -1,155 +0,0 @@ -use serde_yaml::{Mapping, Value}; -use std::collections::HashSet; - -pub const HANDLE_FIELDS: [&str; 9] = [ - "mode", - "port", - "socks-port", - "mixed-port", - "allow-lan", - "log-level", - "ipv6", - "secret", - "external-controller", -]; - -pub const DEFAULT_FIELDS: [&str; 5] = [ - "proxies", - "proxy-groups", - "proxy-providers", - "rules", - "rule-providers", -]; - -pub const OTHERS_FIELDS: [&str; 30] = [ - "dns", - "tun", - "ebpf", - "hosts", - "script", - "profile", - "payload", - "tunnels", - "auto-redir", - "experimental", - "interface-name", - "routing-mark", - "redir-port", - "tproxy-port", - "iptables", - "external-ui", - "bind-address", - "authentication", - "tls", // meta - "sniffer", // meta - "geox-url", // meta - "listeners", // meta - "sub-rules", // meta - "geodata-mode", // meta - "unified-delay", // meta - "tcp-concurrent", // meta - "enable-process", // meta - "find-process-mode", // meta - "external-controller-tls", // meta - "global-client-fingerprint", // meta -]; - -pub fn use_clash_fields() -> Vec { - DEFAULT_FIELDS - .into_iter() - .chain(HANDLE_FIELDS) - .chain(OTHERS_FIELDS) - .map(|s| s.to_string()) - .collect() -} - -pub fn use_valid_fields(mut valid: Vec) -> Vec { - let others = Vec::from(OTHERS_FIELDS); - - valid.iter_mut().for_each(|s| s.make_ascii_lowercase()); - valid - .into_iter() - .filter(|s| others.contains(&s.as_str())) - .chain(DEFAULT_FIELDS.iter().map(|s| s.to_string())) - .collect() -} - -pub fn use_filter(config: Mapping, filter: &Vec, enable: bool) -> Mapping { - if !enable { - return config; - } - - let mut ret = Mapping::new(); - - for (key, value) in config.into_iter() { - if let Some(key) = key.as_str() { - if filter.contains(&key.to_string()) { - ret.insert(Value::from(key), value); - } - } - } - ret -} - -pub fn use_lowercase(config: Mapping) -> Mapping { - let mut ret = Mapping::new(); - - for (key, value) in config.into_iter() { - if let Some(key_str) = key.as_str() { - let mut key_str = String::from(key_str); - key_str.make_ascii_lowercase(); - ret.insert(Value::from(key_str), value); - } - } - ret -} - -pub fn use_sort(config: Mapping, enable_filter: bool) -> Mapping { - let mut ret = Mapping::new(); - - HANDLE_FIELDS - .into_iter() - .chain(OTHERS_FIELDS) - .chain(DEFAULT_FIELDS) - .for_each(|key| { - let key = Value::from(key); - config.get(&key).map(|value| { - ret.insert(key, value.clone()); - }); - }); - - if !enable_filter { - let supported_keys: HashSet<&str> = HANDLE_FIELDS - .into_iter() - .chain(OTHERS_FIELDS) - .chain(DEFAULT_FIELDS) - .collect(); - - let config_keys: HashSet<&str> = config - .keys() - .filter_map(|e| e.as_str()) - .into_iter() - .collect(); - - config_keys.difference(&supported_keys).for_each(|&key| { - let key = Value::from(key); - config.get(&key).map(|value| { - ret.insert(key, value.clone()); - }); - }); - } - - ret -} - -pub fn use_keys(config: &Mapping) -> Vec { - config - .iter() - .filter_map(|(key, _)| key.as_str()) - .map(|s| { - let mut s = s.to_string(); - s.make_ascii_lowercase(); - return s; - }) - .collect() -} diff --git a/src-tauri/src/enhance/merge.rs b/src-tauri/src/enhance/merge.rs deleted file mode 100644 index 20342c9..0000000 --- a/src-tauri/src/enhance/merge.rs +++ /dev/null @@ -1,92 +0,0 @@ -use super::{use_filter, use_lowercase}; -use serde_yaml::{self, Mapping, Sequence, Value}; - -const MERGE_FIELDS: [&str; 6] = [ - "prepend-rules", - "append-rules", - "prepend-proxies", - "append-proxies", - "prepend-proxy-groups", - "append-proxy-groups", -]; - -pub fn use_merge(merge: Mapping, mut config: Mapping) -> Mapping { - // 直接覆盖原字段 - use_lowercase(merge.clone()) - .into_iter() - .for_each(|(key, value)| { - config.insert(key, value); - }); - - let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string()); - let merge = use_filter(merge, &merge_list.collect(), true); - - ["rules", "proxies", "proxy-groups"] - .iter() - .for_each(|key_str| { - let key_val = Value::from(key_str.to_string()); - - let mut list = Sequence::default(); - list = config.get(&key_val).map_or(list.clone(), |val| { - val.as_sequence().map_or(list, |v| v.clone()) - }); - - let pre_key = Value::from(format!("prepend-{key_str}")); - let post_key = Value::from(format!("append-{key_str}")); - - if let Some(pre_val) = merge.get(&pre_key) { - if pre_val.is_sequence() { - let mut pre_val = pre_val.as_sequence().unwrap().clone(); - pre_val.extend(list); - list = pre_val; - } - } - - if let Some(post_val) = merge.get(&post_key) { - if post_val.is_sequence() { - list.extend(post_val.as_sequence().unwrap().clone()); - } - } - - config.insert(key_val, Value::from(list)); - }); - config -} - -#[test] -fn test_merge() -> anyhow::Result<()> { - let merge = r" - prepend-rules: - - prepend - - 1123123 - append-rules: - - append - prepend-proxies: - - 9999 - append-proxies: - - 1111 - rules: - - replace - proxy-groups: - - 123781923810 - tun: - enable: true - dns: - enable: true - "; - - let config = r" - rules: - - aaaaa - script1: test - "; - - let merge = serde_yaml::from_str::(merge)?; - let config = serde_yaml::from_str::(config)?; - - let result = serde_yaml::to_string(&use_merge(merge, config))?; - - println!("{result}"); - - Ok(()) -} diff --git a/src-tauri/src/enhance/mod.rs b/src-tauri/src/enhance/mod.rs deleted file mode 100644 index 0a41400..0000000 --- a/src-tauri/src/enhance/mod.rs +++ /dev/null @@ -1,126 +0,0 @@ -mod chain; -mod field; -mod merge; -mod script; -mod tun; - -pub(self) use self::field::*; - -use self::chain::*; -use self::merge::*; -use self::script::*; -use self::tun::*; -use crate::config::Config; -use serde_yaml::Mapping; -use std::collections::HashMap; -use std::collections::HashSet; - -type ResultLog = Vec<(String, String)>; - -/// Enhance mode -/// 返回最终配置、该配置包含的键、和script执行的结果 -pub fn enhance() -> (Mapping, Vec, HashMap) { - // config.yaml 的配置 - let clash_config = { Config::clash().latest().0.clone() }; - - let (clash_core, enable_tun, enable_builtin, enable_filter) = { - let verge = Config::verge(); - let verge = verge.latest(); - ( - verge.clash_core.clone(), - verge.enable_tun_mode.clone().unwrap_or(false), - verge.enable_builtin_enhanced.clone().unwrap_or(true), - verge.enable_clash_fields.clone().unwrap_or(true), - ) - }; - - // 从profiles里拿东西 - let (mut config, chain, valid) = { - let profiles = Config::profiles(); - let profiles = profiles.latest(); - - let current = profiles.current_mapping().unwrap_or(Mapping::new()); - - let chain = match profiles.chain.as_ref() { - Some(chain) => chain - .iter() - .filter_map(|uid| profiles.get_item(uid).ok()) - .filter_map(|item| >::from(item)) - .collect::>(), - None => vec![], - }; - - let valid = profiles.valid.clone().unwrap_or(vec![]); - - (current, chain, valid) - }; - - let mut result_map = HashMap::new(); // 保存脚本日志 - let mut exists_keys = use_keys(&config); // 保存出现过的keys - - let valid = use_valid_fields(valid); - config = use_filter(config, &valid, enable_filter); - - // 处理用户的profile - chain.into_iter().for_each(|item| match item.data { - ChainType::Merge(merge) => { - exists_keys.extend(use_keys(&merge)); - config = use_merge(merge, config.to_owned()); - config = use_filter(config.to_owned(), &valid, enable_filter); - } - ChainType::Script(script) => { - let mut logs = vec![]; - - match use_script(script, config.to_owned()) { - Ok((res_config, res_logs)) => { - exists_keys.extend(use_keys(&res_config)); - config = use_filter(res_config, &valid, enable_filter); - logs.extend(res_logs); - } - Err(err) => logs.push(("exception".into(), err.to_string())), - } - - result_map.insert(item.uid, logs); - } - }); - - // 合并默认的config - for (key, value) in clash_config.into_iter() { - config.insert(key, value); - } - - let clash_fields = use_clash_fields(); - - // 内建脚本最后跑 - if enable_builtin { - ChainItem::builtin() - .into_iter() - .filter(|(s, _)| s.is_support(clash_core.as_ref())) - .map(|(_, c)| c) - .for_each(|item| { - log::debug!(target: "app", "run builtin script {}", item.uid); - - match item.data { - ChainType::Script(script) => match use_script(script, config.to_owned()) { - Ok((res_config, _)) => { - config = use_filter(res_config, &clash_fields, enable_filter); - } - Err(err) => { - log::error!(target: "app", "builtin script error `{err}`"); - } - }, - _ => {} - } - }); - } - - config = use_filter(config, &clash_fields, enable_filter); - config = use_tun(config, enable_tun); - config = use_sort(config, enable_filter); - - let mut exists_set = HashSet::new(); - exists_set.extend(exists_keys.into_iter().filter(|s| clash_fields.contains(s))); - exists_keys = exists_set.into_iter().collect(); - - (config, exists_keys, result_map) -} diff --git a/src-tauri/src/enhance/script.rs b/src-tauri/src/enhance/script.rs deleted file mode 100644 index 97b34c2..0000000 --- a/src-tauri/src/enhance/script.rs +++ /dev/null @@ -1,94 +0,0 @@ -use super::use_lowercase; -use anyhow::Result; -use serde_yaml::Mapping; - -pub fn use_script(script: String, config: Mapping) -> Result<(Mapping, Vec<(String, String)>)> { - use rquickjs::{Context, Func, Runtime}; - use std::sync::{Arc, Mutex}; - - let runtime = Runtime::new().unwrap(); - let context = Context::full(&runtime).unwrap(); - let outputs = Arc::new(Mutex::new(vec![])); - - let copy_outputs = outputs.clone(); - let result = context.with(|ctx| -> Result { - ctx.globals().set( - "__verge_log__", - Func::from(move |level: String, data: String| { - let mut out = copy_outputs.lock().unwrap(); - out.push((level, data)); - }), - )?; - - ctx.eval( - r#"var console = Object.freeze({ - log(data){__verge_log__("log",JSON.stringify(data))}, - info(data){__verge_log__("info",JSON.stringify(data))}, - error(data){__verge_log__("error",JSON.stringify(data))}, - debug(data){__verge_log__("debug",JSON.stringify(data))}, - });"#, - )?; - - let config = use_lowercase(config.clone()); - let config_str = serde_json::to_string(&config)?; - - let code = format!( - r#"try{{ - {script}; - JSON.stringify(main({config_str})||'') - }} catch(err) {{ - `__error_flag__ ${{err.toString()}}` - }}"# - ); - let result: String = ctx.eval(code.as_str())?; - if result.starts_with("__error_flag__") { - anyhow::bail!(result[15..].to_owned()); - } - if result == "\"\"" { - anyhow::bail!("main function should return object"); - } - return Ok(serde_json::from_str::(result.as_str())?); - }); - - let mut out = outputs.lock().unwrap(); - match result { - Ok(config) => Ok((use_lowercase(config), out.to_vec())), - Err(err) => { - out.push(("exception".into(), err.to_string())); - Ok((config, out.to_vec())) - } - } -} - -#[test] -fn test_script() { - let script = r#" - function main(config) { - if (Array.isArray(config.rules)) { - config.rules = [...config.rules, "add"]; - } - console.log(config); - config.proxies = ["111"]; - return config; - } - "#; - - let config = r#" - rules: - - 111 - - 222 - tun: - enable: false - dns: - enable: false - "#; - - let config = serde_yaml::from_str(config).unwrap(); - let (config, results) = use_script(script.into(), config).unwrap(); - - let config_str = serde_yaml::to_string(&config).unwrap(); - - println!("{config_str}"); - - dbg!(results); -} diff --git a/src-tauri/src/enhance/tun.rs b/src-tauri/src/enhance/tun.rs deleted file mode 100644 index b72823a..0000000 --- a/src-tauri/src/enhance/tun.rs +++ /dev/null @@ -1,81 +0,0 @@ -use serde_yaml::{Mapping, Value}; - -macro_rules! revise { - ($map: expr, $key: expr, $val: expr) => { - let ret_key = Value::String($key.into()); - $map.insert(ret_key, Value::from($val)); - }; -} - -// if key not exists then append value -macro_rules! append { - ($map: expr, $key: expr, $val: expr) => { - let ret_key = Value::String($key.into()); - if !$map.contains_key(&ret_key) { - $map.insert(ret_key, Value::from($val)); - } - }; -} - -pub fn use_tun(mut config: Mapping, enable: bool) -> Mapping { - let tun_key = Value::from("tun"); - let tun_val = config.get(&tun_key); - - if !enable && tun_val.is_none() { - return config; - } - - let mut tun_val = tun_val.map_or(Mapping::new(), |val| { - val.as_mapping().cloned().unwrap_or(Mapping::new()) - }); - - revise!(tun_val, "enable", enable); - if enable { - append!(tun_val, "stack", "gvisor"); - append!(tun_val, "dns-hijack", vec!["any:53"]); - append!(tun_val, "auto-route", true); - append!(tun_val, "auto-detect-interface", true); - } - - revise!(config, "tun", tun_val); - - if enable { - use_dns_for_tun(config) - } else { - config - } -} - -fn use_dns_for_tun(mut config: Mapping) -> Mapping { - let dns_key = Value::from("dns"); - let dns_val = config.get(&dns_key); - - let mut dns_val = dns_val.map_or(Mapping::new(), |val| { - val.as_mapping().cloned().unwrap_or(Mapping::new()) - }); - - // 开启tun将同时开启dns - revise!(dns_val, "enable", true); - - append!(dns_val, "enhanced-mode", "fake-ip"); - append!(dns_val, "fake-ip-range", "198.18.0.1/16"); - append!( - dns_val, - "nameserver", - vec!["114.114.114.114", "223.5.5.5", "8.8.8.8"] - ); - append!(dns_val, "fallback", vec![] as Vec<&str>); - - #[cfg(target_os = "windows")] - append!( - dns_val, - "fake-ip-filter", - vec![ - "dns.msftncsi.com", - "www.msftncsi.com", - "www.msftconnecttest.com" - ] - ); - revise!(config, "dns", dns_val); - config -} diff --git a/src-tauri/src/feat.rs b/src-tauri/src/feat.rs deleted file mode 100644 index a446c27..0000000 --- a/src-tauri/src/feat.rs +++ /dev/null @@ -1,341 +0,0 @@ -//! -//! feat mod 里的函数主要用于 -//! - hotkey 快捷键 -//! - timer 定时器 -//! - cmds 页面调用 -//! -use crate::config::*; -use crate::core::*; -use crate::log_err; -use crate::utils::resolve; -use anyhow::{bail, Result}; -use serde_yaml::{Mapping, Value}; -use wry::application::clipboard::Clipboard; - -// 打开面板 -pub fn open_dashboard() { - let handle = handle::Handle::global(); - let app_handle = handle.app_handle.lock(); - if let Some(app_handle) = app_handle.as_ref() { - resolve::create_window(app_handle); - } -} - -// 重启clash -pub fn restart_clash_core() { - tauri::async_runtime::spawn(async { - match CoreManager::global().run_core().await { - Ok(_) => { - handle::Handle::refresh_clash(); - handle::Handle::notice_message("set_config::ok", "ok"); - } - Err(err) => { - handle::Handle::notice_message("set_config::error", format!("{err}")); - log::error!(target:"app", "{err}"); - } - } - }); -} - -// 切换模式 rule/global/direct/script mode -pub fn change_clash_mode(mode: String) { - let mut mapping = Mapping::new(); - mapping.insert(Value::from("mode"), mode.clone().into()); - - tauri::async_runtime::spawn(async move { - log::debug!(target: "app", "change clash mode to {mode}"); - - match clash_api::patch_configs(&mapping).await { - Ok(_) => { - // 更新配置 - Config::clash().data().patch_config(mapping); - - if Config::clash().data().save_config().is_ok() { - handle::Handle::refresh_clash(); - log_err!(handle::Handle::update_systray_part()); - } - } - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -// 切换系统代理 -pub fn toggle_system_proxy() { - let enable = Config::verge().draft().enable_system_proxy.clone(); - let enable = enable.unwrap_or(false); - - tauri::async_runtime::spawn(async move { - match patch_verge(IVerge { - enable_system_proxy: Some(!enable), - ..IVerge::default() - }) - .await - { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -// 打开系统代理 -pub fn enable_system_proxy() { - tauri::async_runtime::spawn(async { - match patch_verge(IVerge { - enable_system_proxy: Some(true), - ..IVerge::default() - }) - .await - { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -// 关闭系统代理 -pub fn disable_system_proxy() { - tauri::async_runtime::spawn(async { - match patch_verge(IVerge { - enable_system_proxy: Some(false), - ..IVerge::default() - }) - .await - { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -// 切换tun模式 -pub fn toggle_tun_mode() { - let enable = Config::verge().data().enable_tun_mode.clone(); - let enable = enable.unwrap_or(false); - - tauri::async_runtime::spawn(async move { - match patch_verge(IVerge { - enable_tun_mode: Some(!enable), - ..IVerge::default() - }) - .await - { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -// 打开tun模式 -pub fn enable_tun_mode() { - tauri::async_runtime::spawn(async { - match patch_verge(IVerge { - enable_tun_mode: Some(true), - ..IVerge::default() - }) - .await - { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -// 关闭tun模式 -pub fn disable_tun_mode() { - tauri::async_runtime::spawn(async { - match patch_verge(IVerge { - enable_tun_mode: Some(false), - ..IVerge::default() - }) - .await - { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - }); -} - -/// 修改clash的配置 -pub async fn patch_clash(patch: Mapping) -> Result<()> { - Config::clash().draft().patch_config(patch.clone()); - - match { - let mixed_port = patch.get("mixed-port"); - if mixed_port.is_some() { - let changed = mixed_port != Config::clash().data().0.get("mixed-port"); - // 检查端口占用 - if changed { - if let Some(port) = mixed_port.clone().unwrap().as_u64() { - if !port_scanner::local_port_available(port as u16) { - Config::clash().discard(); - bail!("port already in use"); - } - } - } - }; - - // 激活配置 - if mixed_port.is_some() - || patch.get("secret").is_some() - || patch.get("external-controller").is_some() - { - Config::generate()?; - CoreManager::global().run_core().await?; - handle::Handle::refresh_clash(); - } - - // 更新系统代理 - if mixed_port.is_some() { - log_err!(sysopt::Sysopt::global().init_sysproxy()); - } - - if patch.get("mode").is_some() { - log_err!(handle::Handle::update_systray_part()); - } - - Config::runtime().latest().patch_config(patch); - - >::Ok(()) - } { - Ok(()) => { - Config::clash().apply(); - Config::clash().data().save_config()?; - Ok(()) - } - Err(err) => { - Config::clash().discard(); - Err(err) - } - } -} - -/// 修改verge的配置 -/// 一般都是一个个的修改 -pub async fn patch_verge(patch: IVerge) -> Result<()> { - Config::verge().draft().patch_config(patch.clone()); - - let tun_mode = patch.enable_tun_mode; - let auto_launch = patch.enable_auto_launch; - let system_proxy = patch.enable_system_proxy; - let proxy_bypass = patch.system_proxy_bypass; - let language = patch.language; - - match { - #[cfg(target_os = "windows")] - { - let service_mode = patch.enable_service_mode; - - if service_mode.is_some() { - log::debug!(target: "app", "change service mode to {}", service_mode.unwrap()); - - Config::generate()?; - CoreManager::global().run_core().await?; - } else if tun_mode.is_some() { - update_core_config().await?; - } - } - - #[cfg(not(target_os = "windows"))] - if tun_mode.is_some() { - update_core_config().await?; - } - - if auto_launch.is_some() { - sysopt::Sysopt::global().update_launch()?; - } - if system_proxy.is_some() || proxy_bypass.is_some() { - sysopt::Sysopt::global().update_sysproxy()?; - sysopt::Sysopt::global().guard_proxy(); - } - - if let Some(true) = patch.enable_proxy_guard { - sysopt::Sysopt::global().guard_proxy(); - } - - if let Some(hotkeys) = patch.hotkeys { - hotkey::Hotkey::global().update(hotkeys)?; - } - - if language.is_some() { - handle::Handle::update_systray()?; - } else if system_proxy.or(tun_mode).is_some() { - handle::Handle::update_systray_part()?; - } - - >::Ok(()) - } { - Ok(()) => { - Config::verge().apply(); - Config::verge().data().save_file()?; - Ok(()) - } - Err(err) => { - Config::verge().discard(); - Err(err) - } - } -} - -/// 更新某个profile -/// 如果更新当前配置就激活配置 -pub async fn update_profile(uid: String, option: Option) -> Result<()> { - let url_opt = { - let profiles = Config::profiles(); - let profiles = profiles.latest(); - let item = profiles.get_item(&uid)?; - let is_remote = item.itype.as_ref().map_or(false, |s| s == "remote"); - - if !is_remote { - None // 直接更新 - } else if item.url.is_none() { - bail!("failed to get the profile item url"); - } else { - Some((item.url.clone().unwrap(), item.option.clone())) - } - }; - - let should_update = match url_opt { - Some((url, opt)) => { - let merged_opt = PrfOption::merge(opt, option); - let item = PrfItem::from_url(&url, None, None, merged_opt).await?; - - let profiles = Config::profiles(); - let mut profiles = profiles.latest(); - profiles.update_item(uid.clone(), item)?; - - Some(uid) == profiles.get_current() - } - None => true, - }; - - if should_update { - update_core_config().await?; - } - - Ok(()) -} - -/// 更新配置 -async fn update_core_config() -> Result<()> { - match CoreManager::global().update_config().await { - Ok(_) => { - handle::Handle::refresh_clash(); - handle::Handle::notice_message("set_config::ok", "ok"); - Ok(()) - } - Err(err) => { - handle::Handle::notice_message("set_config::error", format!("{err}")); - Err(err) - } - } -} - -/// copy env variable -pub fn copy_clash_env() { - let port = { Config::clash().data().get_client_info().port }; - let text = format!("export https_proxy=http://127.0.0.1:{port} http_proxy=http://127.0.0.1:{port} all_proxy=socks5://127.0.0.1:{port}"); - - let mut cliboard = Clipboard::new(); - cliboard.write_text(text); -} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs deleted file mode 100644 index 0c20bec..0000000 --- a/src-tauri/src/main.rs +++ /dev/null @@ -1,142 +0,0 @@ -#![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" -)] - -mod cmds; -mod config; -mod core; -mod enhance; -mod feat; -mod utils; - -use crate::utils::{init, resolve, server}; -use tauri::{api, SystemTray}; - -fn main() -> std::io::Result<()> { - // 单例检测 - if server::check_singleton().is_err() { - println!("app exists"); - return Ok(()); - } - - crate::log_err!(init::init_config()); - - #[allow(unused_mut)] - let mut builder = tauri::Builder::default() - .system_tray(SystemTray::new()) - .setup(|app| Ok(resolve::resolve_setup(app))) - .on_system_tray_event(core::tray::Tray::on_system_tray_event) - .invoke_handler(tauri::generate_handler![ - // common - cmds::get_sys_proxy, - cmds::open_app_dir, - cmds::open_logs_dir, - cmds::open_web_url, - cmds::open_core_dir, - // cmds::kill_sidecar, - cmds::restart_sidecar, - cmds::grant_permission, - // clash - cmds::get_clash_info, - cmds::get_clash_logs, - cmds::patch_clash_config, - cmds::change_clash_core, - cmds::get_runtime_config, - cmds::get_runtime_yaml, - cmds::get_runtime_exists, - cmds::get_runtime_logs, - // verge - cmds::get_verge_config, - cmds::patch_verge_config, - // cmds::update_hotkeys, - // profile - cmds::get_profiles, - cmds::enhance_profiles, - cmds::patch_profiles_config, - cmds::view_profile, - cmds::patch_profile, - cmds::create_profile, - cmds::import_profile, - cmds::update_profile, - cmds::delete_profile, - cmds::read_profile_file, - cmds::save_profile_file, - // service mode - cmds::service::check_service, - cmds::service::install_service, - cmds::service::uninstall_service, - // clash api - cmds::clash_api_get_proxy_delay - ]); - - #[cfg(target_os = "macos")] - { - use tauri::{Menu, MenuItem, Submenu}; - - builder = builder.menu( - Menu::new().add_submenu(Submenu::new( - "Edit", - Menu::new() - .add_native_item(MenuItem::Undo) - .add_native_item(MenuItem::Redo) - .add_native_item(MenuItem::Copy) - .add_native_item(MenuItem::Paste) - .add_native_item(MenuItem::Cut) - .add_native_item(MenuItem::SelectAll) - .add_native_item(MenuItem::CloseWindow) - .add_native_item(MenuItem::Quit), - )), - ); - } - - let app = builder - .build(tauri::generate_context!()) - .expect("error while running tauri application"); - - app.run(|app_handle, e| match e { - tauri::RunEvent::ExitRequested { api, .. } => { - api.prevent_exit(); - } - tauri::RunEvent::Exit => { - resolve::resolve_reset(); - api::process::kill_children(); - app_handle.exit(0); - } - #[cfg(target_os = "macos")] - tauri::RunEvent::WindowEvent { label, event, .. } => { - use tauri::Manager; - - if label == "main" { - match event { - tauri::WindowEvent::CloseRequested { api, .. } => { - api.prevent_close(); - let _ = resolve::save_window_size_position(&app_handle, true); - - app_handle.get_window("main").map(|win| { - let _ = win.hide(); - }); - } - _ => {} - } - } - } - #[cfg(not(target_os = "macos"))] - tauri::RunEvent::WindowEvent { label, event, .. } => { - if label == "main" { - match event { - tauri::WindowEvent::CloseRequested { .. } => { - let _ = resolve::save_window_size_position(&app_handle, true); - } - tauri::WindowEvent::Moved(_) | tauri::WindowEvent::Resized(_) => { - let _ = resolve::save_window_size_position(&app_handle, false); - } - _ => {} - } - } - } - _ => {} - }); - - Ok(()) -} diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs deleted file mode 100644 index 696831d..0000000 --- a/src-tauri/src/utils/dirs.rs +++ /dev/null @@ -1,159 +0,0 @@ -use anyhow::Result; -use std::path::PathBuf; -use tauri::{ - api::path::{home_dir, resource_dir}, - Env, PackageInfo, -}; - -#[cfg(not(feature = "verge-dev"))] -static APP_DIR: &str = "clash-verge"; -#[cfg(feature = "verge-dev")] -static APP_DIR: &str = "clash-verge-dev"; - -static CLASH_CONFIG: &str = "config.yaml"; -static VERGE_CONFIG: &str = "verge.yaml"; -static PROFILE_YAML: &str = "profiles.yaml"; - -static mut RESOURCE_DIR: Option = None; - -/// portable flag -#[allow(unused)] -static mut PORTABLE_FLAG: bool = false; - -pub static mut APP_VERSION: &str = "v1.2.0"; - -/// initialize portable flag -#[cfg(target_os = "windows")] -pub unsafe fn init_portable_flag() -> Result<()> { - use tauri::utils::platform::current_exe; - - let exe = current_exe()?; - - if let Some(dir) = exe.parent() { - let dir = PathBuf::from(dir).join(".config/PORTABLE"); - - if dir.exists() { - PORTABLE_FLAG = true; - } - } - - Ok(()) -} - -/// get the verge app home dir -pub fn app_home_dir() -> Result { - #[cfg(target_os = "windows")] - unsafe { - use tauri::utils::platform::current_exe; - - if !PORTABLE_FLAG { - Ok(home_dir() - .ok_or(anyhow::anyhow!("failed to get app home dir"))? - .join(".config") - .join(APP_DIR)) - } else { - let app_exe = current_exe()?; - let app_exe = dunce::canonicalize(app_exe)?; - let app_dir = app_exe - .parent() - .ok_or(anyhow::anyhow!("failed to get the portable app dir"))?; - Ok(PathBuf::from(app_dir).join(".config").join(APP_DIR)) - } - } - - #[cfg(not(target_os = "windows"))] - Ok(home_dir() - .ok_or(anyhow::anyhow!("failed to get the app home dir"))? - .join(".config") - .join(APP_DIR)) -} - -/// get the resources dir -pub fn app_resources_dir(package_info: &PackageInfo) -> Result { - let res_dir = resource_dir(package_info, &Env::default()) - .ok_or(anyhow::anyhow!("failed to get the resource dir"))? - .join("resources"); - - unsafe { - RESOURCE_DIR = Some(res_dir.clone()); - - let ver = package_info.version.to_string(); - let ver_str = format!("v{ver}"); - APP_VERSION = Box::leak(Box::new(ver_str)); - } - - Ok(res_dir) -} - -/// profiles dir -pub fn app_profiles_dir() -> Result { - Ok(app_home_dir()?.join("profiles")) -} - -/// logs dir -pub fn app_logs_dir() -> Result { - Ok(app_home_dir()?.join("logs")) -} - -pub fn clash_path() -> Result { - Ok(app_home_dir()?.join(CLASH_CONFIG)) -} - -pub fn verge_path() -> Result { - Ok(app_home_dir()?.join(VERGE_CONFIG)) -} - -pub fn profiles_path() -> Result { - Ok(app_home_dir()?.join(PROFILE_YAML)) -} - -#[allow(unused)] -pub fn app_res_dir() -> Result { - unsafe { - Ok(RESOURCE_DIR - .clone() - .ok_or(anyhow::anyhow!("failed to get the resource dir"))?) - } -} - -pub fn clash_pid_path() -> Result { - unsafe { - Ok(RESOURCE_DIR - .clone() - .ok_or(anyhow::anyhow!("failed to get the resource dir"))? - .join("clash.pid")) - } -} - -#[cfg(windows)] -pub fn service_path() -> Result { - unsafe { - let res_dir = RESOURCE_DIR - .clone() - .ok_or(anyhow::anyhow!("failed to get the resource dir"))?; - Ok(res_dir.join("clash-verge-service.exe")) - } -} - -#[cfg(windows)] -pub fn service_log_file() -> Result { - use chrono::Local; - - let log_dir = app_logs_dir()?.join("service"); - - let local_time = Local::now().format("%Y-%m-%d-%H%M").to_string(); - let log_file = format!("{}.log", local_time); - let log_file = log_dir.join(log_file); - - let _ = std::fs::create_dir_all(&log_dir); - - Ok(log_file) -} - -pub fn path_to_str(path: &PathBuf) -> Result<&str> { - let path_str = path - .as_os_str() - .to_str() - .ok_or(anyhow::anyhow!("failed to get path from {:?}", path))?; - Ok(path_str) -} diff --git a/src-tauri/src/utils/help.rs b/src-tauri/src/utils/help.rs deleted file mode 100644 index 03a89f4..0000000 --- a/src-tauri/src/utils/help.rs +++ /dev/null @@ -1,172 +0,0 @@ -use anyhow::{anyhow, bail, Context, Result}; -use nanoid::nanoid; -use serde::{de::DeserializeOwned, Serialize}; -use serde_yaml::{Mapping, Value}; -use std::{fs, path::PathBuf, str::FromStr}; - -/// read data from yaml as struct T -pub fn read_yaml(path: &PathBuf) -> Result { - if !path.exists() { - bail!("file not found \"{}\"", path.display()); - } - - let yaml_str = fs::read_to_string(&path) - .with_context(|| format!("failed to read the file \"{}\"", path.display()))?; - - serde_yaml::from_str::(&yaml_str).with_context(|| { - format!( - "failed to read the file with yaml format \"{}\"", - path.display() - ) - }) -} - -/// read mapping from yaml fix #165 -pub fn read_merge_mapping(path: &PathBuf) -> Result { - let mut val: Value = read_yaml(path)?; - val.apply_merge() - .with_context(|| format!("failed to apply merge \"{}\"", path.display()))?; - - Ok(val - .as_mapping() - .ok_or(anyhow!( - "failed to transform to yaml mapping \"{}\"", - path.display() - ))? - .to_owned()) -} - -/// save the data to the file -/// can set `prefix` string to add some comments -pub fn save_yaml(path: &PathBuf, data: &T, prefix: Option<&str>) -> Result<()> { - let data_str = serde_yaml::to_string(data)?; - - let yaml_str = match prefix { - Some(prefix) => format!("{prefix}\n\n{data_str}"), - None => data_str, - }; - - let path_str = path.as_os_str().to_string_lossy().to_string(); - fs::write(path, yaml_str.as_bytes()) - .with_context(|| format!("failed to save file \"{path_str}\"")) -} - -const ALPHABET: [char; 62] = [ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', - 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', - 'V', 'W', 'X', 'Y', 'Z', -]; - -/// generate the uid -pub fn get_uid(prefix: &str) -> String { - let id = nanoid!(11, &ALPHABET); - format!("{prefix}{id}") -} - -/// parse the string -/// xxx=123123; => 123123 -pub fn parse_str(target: &str, key: &str) -> Option { - target.find(key).and_then(|idx| { - let idx = idx + key.len(); - let value = &target[idx..]; - - match value.split(';').nth(0) { - Some(value) => value.trim().parse(), - None => value.trim().parse(), - } - .ok() - }) -} - -/// open file -/// use vscode by default -pub fn open_file(path: PathBuf) -> Result<()> { - #[cfg(target_os = "macos")] - let code = "Visual Studio Code"; - #[cfg(not(target_os = "macos"))] - let code = "code"; - - // use vscode first - if let Err(err) = open::with(&path, code) { - log::error!(target: "app", "failed to open file with VScode `{err}`"); - // default open - open::that(path)?; - } - - Ok(()) -} - -#[macro_export] -macro_rules! error { - ($result: expr) => { - log::error!(target: "app", "{}", $result); - }; -} - -#[macro_export] -macro_rules! log_err { - ($result: expr) => { - if let Err(err) = $result { - log::error!(target: "app", "{err}"); - } - }; - - ($result: expr, $err_str: expr) => { - if let Err(_) = $result { - log::error!(target: "app", "{}", $err_str); - } - }; -} - -#[macro_export] -macro_rules! trace_err { - ($result: expr, $err_str: expr) => { - if let Err(err) = $result { - log::trace!(target: "app", "{}, err {}", $err_str, err); - } - } -} - -/// wrap the anyhow error -/// transform the error to String -#[macro_export] -macro_rules! wrap_err { - ($stat: expr) => { - match $stat { - Ok(a) => Ok(a), - Err(err) => { - log::error!(target: "app", "{}", err.to_string()); - Err(format!("{}", err.to_string())) - } - } - }; -} - -/// return the string literal error -#[macro_export] -macro_rules! ret_err { - ($str: expr) => { - return Err($str.into()) - }; -} - -#[test] -fn test_parse_value() { - let test_1 = "upload=111; download=2222; total=3333; expire=444"; - let test_2 = "attachment; filename=Clash.yaml"; - - assert_eq!(parse_str::(test_1, "upload=").unwrap(), 111); - assert_eq!(parse_str::(test_1, "download=").unwrap(), 2222); - assert_eq!(parse_str::(test_1, "total=").unwrap(), 3333); - assert_eq!(parse_str::(test_1, "expire=").unwrap(), 444); - assert_eq!( - parse_str::(test_2, "filename=").unwrap(), - format!("Clash.yaml") - ); - - assert_eq!(parse_str::(test_1, "aaa="), None); - assert_eq!(parse_str::(test_1, "upload1="), None); - assert_eq!(parse_str::(test_1, "expire1="), None); - assert_eq!(parse_str::(test_2, "attachment="), None); -} diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs deleted file mode 100644 index e9bcd42..0000000 --- a/src-tauri/src/utils/init.rs +++ /dev/null @@ -1,243 +0,0 @@ -use crate::config::*; -use crate::utils::{dirs, help}; -use anyhow::Result; -use chrono::{DateTime, Local}; -use log::LevelFilter; -use log4rs::append::console::ConsoleAppender; -use log4rs::append::file::FileAppender; -use log4rs::config::{Appender, Logger, Root}; -use log4rs::encode::pattern::PatternEncoder; -use std::fs::{self, DirEntry}; -use std::str::FromStr; -use tauri::PackageInfo; - -/// initialize this instance's log file -fn init_log() -> Result<()> { - let log_dir = dirs::app_logs_dir()?; - if !log_dir.exists() { - let _ = fs::create_dir_all(&log_dir); - } - - let log_level = Config::verge().data().get_log_level(); - if log_level == LevelFilter::Off { - return Ok(()); - } - - let local_time = Local::now().format("%Y-%m-%d-%H%M").to_string(); - let log_file = format!("{}.log", local_time); - let log_file = log_dir.join(log_file); - - let log_pattern = match log_level { - LevelFilter::Trace => "{d(%Y-%m-%d %H:%M:%S)} {l} [{M}] - {m}{n}", - _ => "{d(%Y-%m-%d %H:%M:%S)} {l} - {m}{n}", - }; - - let encode = Box::new(PatternEncoder::new(log_pattern)); - - let stdout = ConsoleAppender::builder().encoder(encode.clone()).build(); - let tofile = FileAppender::builder().encoder(encode).build(log_file)?; - - let mut logger_builder = Logger::builder(); - let mut root_builder = Root::builder(); - - let log_more = log_level == LevelFilter::Trace || log_level == LevelFilter::Debug; - - #[cfg(feature = "verge-dev")] - { - logger_builder = logger_builder.appenders(["file", "stdout"]); - if log_more { - root_builder = root_builder.appenders(["file", "stdout"]); - } else { - root_builder = root_builder.appenders(["stdout"]); - } - } - #[cfg(not(feature = "verge-dev"))] - { - logger_builder = logger_builder.appenders(["file"]); - if log_more { - root_builder = root_builder.appenders(["file"]); - } - } - - let (config, _) = log4rs::config::Config::builder() - .appender(Appender::builder().build("stdout", Box::new(stdout))) - .appender(Appender::builder().build("file", Box::new(tofile))) - .logger(logger_builder.additive(false).build("app", log_level)) - .build_lossy(root_builder.build(log_level)); - - log4rs::init_config(config)?; - - Ok(()) -} - -/// 删除log文件 -pub fn delete_log() -> Result<()> { - let log_dir = dirs::app_logs_dir()?; - if !log_dir.exists() { - return Ok(()); - } - - let auto_log_clean = { - let verge = Config::verge(); - let verge = verge.data(); - verge.auto_log_clean.clone().unwrap_or(0) - }; - - let day = match auto_log_clean { - 1 => 7, - 2 => 30, - 3 => 90, - _ => return Ok(()), - }; - - log::debug!(target: "app", "try to delete log files, day: {day}"); - - // %Y-%m-%d to NaiveDateTime - let parse_time_str = |s: &str| { - let sa: Vec<&str> = s.split('-').collect(); - if sa.len() != 4 { - return Err(anyhow::anyhow!("invalid time str")); - } - - let year = i32::from_str(sa[0])?; - let month = u32::from_str(sa[1])?; - let day = u32::from_str(sa[2])?; - let time = chrono::NaiveDate::from_ymd_opt(year, month, day) - .ok_or(anyhow::anyhow!("invalid time str"))? - .and_hms_opt(0, 0, 0) - .ok_or(anyhow::anyhow!("invalid time str"))?; - Ok(time) - }; - - let process_file = |file: DirEntry| -> Result<()> { - let file_name = file.file_name(); - let file_name = file_name.to_str().unwrap_or_default(); - - if file_name.ends_with(".log") { - let now = Local::now(); - let created_time = parse_time_str(&file_name[0..file_name.len() - 4])?; - let file_time = DateTime::::from_local(created_time, now.offset().clone()); - - let duration = now.signed_duration_since(file_time); - if duration.num_days() > day { - let file_path = file.path(); - let _ = fs::remove_file(file_path); - log::info!(target: "app", "delete log file: {file_name}"); - } - } - Ok(()) - }; - - for file in fs::read_dir(&log_dir)? { - if let Ok(file) = file { - let _ = process_file(file); - } - } - Ok(()) -} - -/// Initialize all the config files -/// before tauri setup -pub fn init_config() -> Result<()> { - #[cfg(target_os = "windows")] - unsafe { - let _ = dirs::init_portable_flag(); - } - - let _ = init_log(); - let _ = delete_log(); - - crate::log_err!(dirs::app_home_dir().map(|app_dir| { - if !app_dir.exists() { - let _ = fs::create_dir_all(&app_dir); - } - })); - - crate::log_err!(dirs::app_profiles_dir().map(|profiles_dir| { - if !profiles_dir.exists() { - let _ = fs::create_dir_all(&profiles_dir); - } - })); - - crate::log_err!(dirs::clash_path().map(|path| { - if !path.exists() { - help::save_yaml(&path, &IClashTemp::template().0, Some("# Clash Verge"))?; - } - >::Ok(()) - })); - - crate::log_err!(dirs::verge_path().map(|path| { - if !path.exists() { - help::save_yaml(&path, &IVerge::template(), Some("# Clash Verge"))?; - } - >::Ok(()) - })); - - crate::log_err!(dirs::profiles_path().map(|path| { - if !path.exists() { - help::save_yaml(&path, &IProfiles::template(), Some("# Clash Verge"))?; - } - >::Ok(()) - })); - - Ok(()) -} - -/// initialize app resources -/// after tauri setup -pub fn init_resources(package_info: &PackageInfo) -> Result<()> { - let app_dir = dirs::app_home_dir()?; - let res_dir = dirs::app_resources_dir(package_info)?; - - if !app_dir.exists() { - let _ = fs::create_dir_all(&app_dir); - } - if !res_dir.exists() { - let _ = fs::create_dir_all(&res_dir); - } - - #[cfg(target_os = "windows")] - let file_list = ["Country.mmdb", "geoip.dat", "geosite.dat", "wintun.dll"]; - #[cfg(not(target_os = "windows"))] - let file_list = ["Country.mmdb", "geoip.dat", "geosite.dat"]; - - // copy the resource file - // if the source file is newer than the destination file, copy it over - for file in file_list.iter() { - let src_path = res_dir.join(file); - let dest_path = app_dir.join(file); - - let handle_copy = || { - match fs::copy(&src_path, &dest_path) { - Ok(_) => log::debug!(target: "app", "resources copied '{file}'"), - Err(err) => { - log::error!(target: "app", "failed to copy resources '{file}', {err}") - } - }; - }; - - if src_path.exists() && !dest_path.exists() { - handle_copy(); - continue; - } - - let src_modified = fs::metadata(&src_path).and_then(|m| m.modified()); - let dest_modified = fs::metadata(&dest_path).and_then(|m| m.modified()); - - match (src_modified, dest_modified) { - (Ok(src_modified), Ok(dest_modified)) => { - if src_modified > dest_modified { - handle_copy(); - } else { - log::debug!(target: "app", "skipping resource copy '{file}'"); - } - } - _ => { - log::debug!(target: "app", "failed to get modified '{file}'"); - handle_copy(); - } - }; - } - - Ok(()) -} diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs deleted file mode 100644 index aeb0a60..0000000 --- a/src-tauri/src/utils/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod dirs; -pub mod help; -pub mod init; -pub mod resolve; -pub mod server; -pub mod tmpl; -// mod winhelp; diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs deleted file mode 100644 index 14d4bdd..0000000 --- a/src-tauri/src/utils/resolve.rs +++ /dev/null @@ -1,179 +0,0 @@ -use crate::{config::Config, core::*, utils::init, utils::server}; -use crate::{log_err, trace_err}; -use anyhow::Result; -use tauri::{App, AppHandle, Manager}; - -/// handle something when start app -pub fn resolve_setup(app: &mut App) { - #[cfg(target_os = "macos")] - app.set_activation_policy(tauri::ActivationPolicy::Accessory); - - handle::Handle::global().init(app.app_handle()); - - log_err!(init::init_resources(app.package_info())); - - // 启动核心 - log::trace!("init config"); - log_err!(Config::init_config()); - - log::trace!("launch core"); - log_err!(CoreManager::global().init()); - - // setup a simple http server for singleton - log::trace!("launch embed server"); - server::embed_server(app.app_handle()); - - log::trace!("init system tray"); - log_err!(tray::Tray::update_systray(&app.app_handle())); - - let silent_start = { Config::verge().data().enable_silent_start.clone() }; - if !silent_start.unwrap_or(false) { - create_window(&app.app_handle()); - } - - log_err!(sysopt::Sysopt::global().init_launch()); - log_err!(sysopt::Sysopt::global().init_sysproxy()); - - log_err!(handle::Handle::update_systray_part()); - log_err!(hotkey::Hotkey::global().init(app.app_handle())); - log_err!(timer::Timer::global().init()); -} - -/// reset system proxy -pub fn resolve_reset() { - log_err!(sysopt::Sysopt::global().reset_sysproxy()); - log_err!(CoreManager::global().stop_core()); -} - -/// create main window -pub fn create_window(app_handle: &AppHandle) { - if let Some(window) = app_handle.get_window("main") { - trace_err!(window.unminimize(), "set win unminimize"); - trace_err!(window.show(), "set win visible"); - trace_err!(window.set_focus(), "set win focus"); - return; - } - - let mut builder = tauri::window::WindowBuilder::new( - app_handle, - "main".to_string(), - tauri::WindowUrl::App("index.html".into()), - ) - .title("Clash Verge") - .fullscreen(false) - .min_inner_size(600.0, 520.0); - - match Config::verge().latest().window_size_position.clone() { - Some(size_pos) if size_pos.len() == 4 => { - let size = (size_pos[0], size_pos[1]); - let pos = (size_pos[2], size_pos[3]); - let w = size.0.clamp(600.0, f64::INFINITY); - let h = size.1.clamp(520.0, f64::INFINITY); - builder = builder.inner_size(w, h).position(pos.0, pos.1); - } - _ => { - #[cfg(target_os = "windows")] - { - builder = builder.inner_size(800.0, 636.0).center(); - } - - #[cfg(target_os = "macos")] - { - builder = builder.inner_size(800.0, 642.0).center(); - } - - #[cfg(target_os = "linux")] - { - builder = builder.inner_size(800.0, 642.0).center(); - } - } - }; - - #[cfg(target_os = "windows")] - { - use std::time::Duration; - use tokio::time::sleep; - use window_shadows::set_shadow; - - match builder - .decorations(false) - .transparent(true) - .visible(false) - .build() - { - Ok(win) => { - log::trace!("try to calculate the monitor size"); - let center = (|| -> Result { - let mut center = false; - let monitor = win.current_monitor()?.ok_or(anyhow::anyhow!(""))?; - let size = monitor.size(); - let pos = win.outer_position()?; - - if pos.x < -400 - || pos.x > (size.width - 200).try_into()? - || pos.y < -200 - || pos.y > (size.height - 200).try_into()? - { - center = true; - } - Ok(center) - })(); - - if center.unwrap_or(true) { - trace_err!(win.center(), "set win center"); - } - - log::trace!("try to create window"); - let app_handle = app_handle.clone(); - - // 加点延迟避免界面闪一下 - tauri::async_runtime::spawn(async move { - sleep(Duration::from_millis(888)).await; - - if let Some(window) = app_handle.get_window("main") { - trace_err!(set_shadow(&window, true), "set win shadow"); - trace_err!(window.show(), "set win visible"); - trace_err!(window.unminimize(), "set win unminimize"); - trace_err!(window.set_focus(), "set win focus"); - } else { - log::error!(target: "app", "failed to create window, get_window is None") - } - }); - } - Err(err) => log::error!(target: "app", "failed to create window, {err}"), - } - } - - #[cfg(target_os = "macos")] - crate::log_err!(builder - .decorations(true) - .hidden_title(true) - .title_bar_style(tauri::TitleBarStyle::Overlay) - .build()); - - #[cfg(target_os = "linux")] - crate::log_err!(builder.decorations(true).transparent(false).build()); -} - -/// save window size and position -pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) -> Result<()> { - let win = app_handle - .get_window("main") - .ok_or(anyhow::anyhow!("failed to get window"))?; - - let scale = win.scale_factor()?; - let size = win.inner_size()?; - let size = size.to_logical::(scale); - let pos = win.outer_position()?; - let pos = pos.to_logical::(scale); - - let verge = Config::verge(); - let mut verge = verge.latest(); - verge.window_size_position = Some(vec![size.width, size.height, pos.x, pos.y]); - - if save_to_file { - verge.save_file()?; - } - - Ok(()) -} diff --git a/src-tauri/src/utils/server.rs b/src-tauri/src/utils/server.rs deleted file mode 100644 index f4e9836..0000000 --- a/src-tauri/src/utils/server.rs +++ /dev/null @@ -1,44 +0,0 @@ -extern crate warp; - -use super::resolve; -use crate::config::IVerge; -use anyhow::{bail, Result}; -use port_scanner::local_port_available; -use tauri::AppHandle; -use warp::Filter; - -/// check whether there is already exists -pub fn check_singleton() -> Result<()> { - let port = IVerge::get_singleton_port(); - - if !local_port_available(port) { - tauri::async_runtime::block_on(async { - let url = format!("http://127.0.0.1:{port}/commands/visible"); - let resp = reqwest::get(url).await?.text().await?; - - if &resp == "ok" { - bail!("app exists"); - } - - log::error!("failed to setup singleton listen server"); - Ok(()) - }) - } else { - Ok(()) - } -} - -/// The embed server only be used to implement singleton process -/// maybe it can be used as pac server later -pub fn embed_server(app_handle: AppHandle) { - let port = IVerge::get_singleton_port(); - - tauri::async_runtime::spawn(async move { - let commands = warp::path!("commands" / "visible").map(move || { - resolve::create_window(&app_handle); - format!("ok") - }); - - warp::serve(commands).bind(([127, 0, 0, 1], port)).await; - }); -} diff --git a/src-tauri/src/utils/tmpl.rs b/src-tauri/src/utils/tmpl.rs deleted file mode 100644 index ec17c33..0000000 --- a/src-tauri/src/utils/tmpl.rs +++ /dev/null @@ -1,36 +0,0 @@ -///! Some config file template - -/// template for new a profile item -pub const ITEM_LOCAL: &str = "# Profile Template for clash verge - -proxies: - -proxy-groups: - -rules: -"; - -/// enhanced profile -pub const ITEM_MERGE: &str = "# Merge Template for clash verge -# The `Merge` format used to enhance profile - -prepend-rules: - -prepend-proxies: - -prepend-proxy-groups: - -append-rules: - -append-proxies: - -append-proxy-groups: -"; - -/// enhanced profile -pub const ITEM_SCRIPT: &str = "// Define the `main` function - -function main(params) { - return params; -} -"; diff --git a/src-tauri/src/utils/winhelp.rs b/src-tauri/src/utils/winhelp.rs deleted file mode 100644 index e903d95..0000000 --- a/src-tauri/src/utils/winhelp.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![cfg(target_os = "windows")] -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] - -//! -//! From https://github.com/tauri-apps/window-vibrancy/blob/dev/src/windows.rs -//! - -use windows_sys::Win32::{ - Foundation::*, - System::{LibraryLoader::*, SystemInformation::*}, -}; - -fn get_function_impl(library: &str, function: &str) -> Option { - assert_eq!(library.chars().last(), Some('\0')); - assert_eq!(function.chars().last(), Some('\0')); - - let module = unsafe { LoadLibraryA(library.as_ptr()) }; - if module == 0 { - return None; - } - Some(unsafe { GetProcAddress(module, function.as_ptr()) }) -} - -macro_rules! get_function { - ($lib:expr, $func:ident) => { - get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0')).map(|f| unsafe { - std::mem::transmute::<::windows_sys::Win32::Foundation::FARPROC, $func>(f) - }) - }; -} - -/// Returns a tuple of (major, minor, buildnumber) -fn get_windows_ver() -> Option<(u32, u32, u32)> { - type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> i32; - let handle = get_function!("ntdll.dll", RtlGetVersion); - if let Some(rtl_get_version) = handle { - unsafe { - let mut vi = OSVERSIONINFOW { - dwOSVersionInfoSize: 0, - dwMajorVersion: 0, - dwMinorVersion: 0, - dwBuildNumber: 0, - dwPlatformId: 0, - szCSDVersion: [0; 128], - }; - - let status = (rtl_get_version)(&mut vi as _); - - if status >= 0 { - Some((vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber)) - } else { - None - } - } - } else { - None - } -} - -pub fn is_win11() -> bool { - let v = get_windows_ver().unwrap_or_default(); - v.2 >= 22000 -} - -#[test] -fn test_version() { - dbg!(get_windows_ver().unwrap_or_default()); -} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json deleted file mode 100644 index 71c7200..0000000 --- a/src-tauri/tauri.conf.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "package": { - "productName": "Clash Verge", - "version": "1.3.8" - }, - "build": { - "distDir": "../dist", - "devPath": "http://localhost:3000/", - "beforeDevCommand": "yarn run web:dev", - "beforeBuildCommand": "yarn run web:build" - }, - "tauri": { - "systemTray": { - "iconPath": "icons/tray-icon.ico", - "iconAsTemplate": true - }, - "bundle": { - "active": true, - "targets": "all", - "identifier": "top.gydi.clashverge", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon-new.icns", - "icons/icon.ico" - ], - "resources": ["resources"], - "externalBin": ["sidecar/clash", "sidecar/clash-meta"], - "copyright": "© 2022 zzzgydi All Rights Reserved", - "category": "DeveloperTool", - "shortDescription": "A Clash GUI based on tauri.", - "longDescription": "A Clash GUI based on tauri.", - "deb": { - "depends": ["openssl"] - }, - "macOS": { - "frameworks": [], - "minimumSystemVersion": "", - "exceptionDomain": "", - "signingIdentity": null, - "entitlements": null - }, - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "", - "wix": { - "language": ["zh-CN", "en-US", "ru-RU"] - } - } - }, - "updater": { - "active": true, - "endpoints": [ - "https://ghproxy.com/https://github.com/zzzgydi/clash-verge/releases/download/updater/update-proxy.json", - "https://github.com/zzzgydi/clash-verge/releases/download/updater/update.json" - ], - "dialog": false, - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDExNUFBNTBBN0FDNEFBRTUKUldUbHFzUjZDcVZhRVRJM25NS3NkSFlFVElxUkNZMzZ6bHUwRVJjb2F3alJXVzRaeDdSaTA2YWYK" - }, - "allowlist": { - "shell": { - "all": true - }, - "window": { - "all": true - }, - "process": { - "all": true - }, - "globalShortcut": { - "all": true - } - }, - "windows": [], - "security": { - "csp": "script-src 'unsafe-eval' 'self'; default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; img-src data: 'self';" - } - } -} diff --git a/src/assets/image/logo-box.png b/src/assets/image/logo-box.png deleted file mode 100644 index fe64a1f..0000000 Binary files a/src/assets/image/logo-box.png and /dev/null differ diff --git a/src/assets/image/logo.ico b/src/assets/image/logo.ico deleted file mode 100644 index e406a78..0000000 Binary files a/src/assets/image/logo.ico and /dev/null differ diff --git a/src/assets/image/logo.png b/src/assets/image/logo.png deleted file mode 100644 index c384c7c..0000000 Binary files a/src/assets/image/logo.png and /dev/null differ diff --git a/src/assets/image/logo.svg b/src/assets/image/logo.svg deleted file mode 100644 index 750fb40..0000000 --- a/src/assets/image/logo.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss deleted file mode 100644 index 2fdcc9e..0000000 --- a/src/assets/styles/index.scss +++ /dev/null @@ -1,50 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - -webkit-font-smoothing: antialiased; - - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -:root { - --primary-main: #5b5c9d; - --text-primary: #637381; - --selection-color: #f5f5f5; - --scroller-color: #90939980; -} - -::selection { - color: var(--selection-color); - background-color: var(--primary-main); -} - -*::-webkit-scrollbar { - width: 6px; - height: 6px; - background: transparent; -} -*::-webkit-scrollbar-thumb { - border-radius: 6px; - background-color: var(--scroller-color); -} - -@import "./layout.scss"; -@import "./page.scss"; - -@media (prefers-color-scheme: dark) { - :root { - background-color: rgba(18, 18, 18, 1); - } -} - -.user-none { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} diff --git a/src/assets/styles/layout.scss b/src/assets/styles/layout.scss deleted file mode 100644 index 3d16c86..0000000 --- a/src/assets/styles/layout.scss +++ /dev/null @@ -1,117 +0,0 @@ -.layout { - width: 100%; - height: 100vh; - display: flex; - overflow: hidden; - - &__left { - flex: 1 0 25%; - display: flex; - height: 100%; - max-width: 225px; - min-width: 125px; - padding: 16px 0 8px; - flex-direction: column; - box-sizing: border-box; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - overflow: hidden; - - $maxLogo: 100px; - - .the-logo { - position: relative; - flex: 0 1 $maxLogo; - width: 100%; - max-width: $maxLogo + 32px; - max-height: $maxLogo; - margin: 0 auto; - padding: 0 16px; - text-align: center; - box-sizing: border-box; - - img, - svg { - width: 100%; - height: 100%; - pointer-events: none; - } - - .the-newbtn { - position: absolute; - right: 10px; - bottom: 0px; - transform: scale(0.8); - } - } - - .the-menu { - flex: 1 1 80%; - overflow-y: auto; - margin-bottom: 8px; - } - - .the-traffic { - flex: 0 0 60px; - - > div { - margin: 0 auto; - } - } - } - - &__right { - position: relative; - flex: 1 1 75%; - height: 100%; - - .the-bar { - position: absolute; - top: 2px; - right: 8px; - height: 36px; - display: flex; - align-items: center; - box-sizing: border-box; - z-index: 2; - } - - .the-content { - position: absolute; - top: 0; - left: 0; - right: 2px; - bottom: 10px; - } - } -} - -.linux, -.windows, -.unknown { - &.layout { - $maxLogo: 115px; - .layout__left .the-logo { - flex: 0 1 $maxLogo; - max-width: $maxLogo + 32px; - max-height: $maxLogo; - } - - .layout__right .the-content { - top: 30px; - } - } -} - -.macos { - &.layout { - .layout__left { - padding-top: 24px; - } - .layout__right .the-content { - top: 20px; - } - } -} diff --git a/src/assets/styles/page.scss b/src/assets/styles/page.scss deleted file mode 100644 index ae7fce3..0000000 --- a/src/assets/styles/page.scss +++ /dev/null @@ -1,35 +0,0 @@ -.base-page { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - - > header { - flex: 0 0 58px; - width: 90%; - // max-width: 850px; - margin: 0 auto; - padding-right: 4px; - box-sizing: border-box; - display: flex; - align-items: center; - justify-content: space-between; - } - - > section { - position: relative; - flex: 1 1 100%; - width: 100%; - height: 100%; - overflow: auto; - padding: 8px 0; - box-sizing: border-box; - scrollbar-gutter: stable; - - .base-content { - width: 90%; - // max-width: 850px; - margin: 0 auto; - } - } -} diff --git a/src/components/base/base-dialog.tsx b/src/components/base/base-dialog.tsx deleted file mode 100644 index db4226c..0000000 --- a/src/components/base/base-dialog.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { ReactNode } from "react"; -import { - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - type SxProps, - type Theme, -} from "@mui/material"; - -interface Props { - title: ReactNode; - open: boolean; - okBtn?: ReactNode; - cancelBtn?: ReactNode; - disableOk?: boolean; - disableCancel?: boolean; - disableFooter?: boolean; - contentSx?: SxProps; - children?: ReactNode; - onOk?: () => void; - onCancel?: () => void; - onClose?: () => void; -} - -export interface DialogRef { - open: () => void; - close: () => void; -} - -export const BaseDialog: React.FC = (props) => { - const { - open, - title, - children, - okBtn, - cancelBtn, - contentSx, - disableCancel, - disableOk, - disableFooter, - } = props; - - return ( - - {title} - - {children} - - {!disableFooter && ( - - {!disableCancel && ( - - )} - {!disableOk && ( - - )} - - )} - - ); -}; diff --git a/src/components/base/base-empty.tsx b/src/components/base/base-empty.tsx deleted file mode 100644 index c364a50..0000000 --- a/src/components/base/base-empty.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { alpha, Box, Typography } from "@mui/material"; -import { InboxRounded } from "@mui/icons-material"; - -interface Props { - text?: React.ReactNode; - extra?: React.ReactNode; -} - -export const BaseEmpty = (props: Props) => { - const { text = "Empty", extra } = props; - - return ( - ({ - width: "100%", - height: "100%", - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", - color: alpha(palette.text.secondary, 0.75), - })} - > - - {text} - {extra} - - ); -}; diff --git a/src/components/base/base-error-boundary.tsx b/src/components/base/base-error-boundary.tsx deleted file mode 100644 index 2475a2f..0000000 --- a/src/components/base/base-error-boundary.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ReactNode } from "react"; -import { ErrorBoundary, FallbackProps } from "react-error-boundary"; - -function ErrorFallback({ error }: FallbackProps) { - return ( -
-

Something went wrong:(

- -
{error.message}
- -
- Error Stack -
{error.stack}
-
-
- ); -} - -interface Props { - children?: ReactNode; -} - -export const BaseErrorBoundary = (props: Props) => { - return ( - - {props.children} - - ); -}; diff --git a/src/components/base/base-loading.tsx b/src/components/base/base-loading.tsx deleted file mode 100644 index 0fdbebf..0000000 --- a/src/components/base/base-loading.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { styled } from "@mui/material"; - -const Loading = styled("div")` - position: relative; - display: flex; - height: 100%; - min-height: 18px; - box-sizing: border-box; - align-items: center; - - & > div { - box-sizing: border-box; - width: 6px; - height: 6px; - margin: 2px; - border-radius: 100%; - animation: loading 0.7s -0.15s infinite linear; - } - - & > div:nth-child(2n-1) { - animation-delay: -0.5s; - } - - @keyframes loading { - 50% { - opacity: 0.2; - transform: scale(0.75); - } - 100% { - opacity: 1; - transform: scale(1); - } - } -`; - -const LoadingItem = styled("div")(({ theme }) => ({ - background: theme.palette.text.secondary, -})); - -export const BaseLoading = () => { - return ( - - - - - - ); -}; diff --git a/src/components/base/base-notice.tsx b/src/components/base/base-notice.tsx deleted file mode 100644 index 5849034..0000000 --- a/src/components/base/base-notice.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { createRoot } from "react-dom/client"; -import { ReactNode, useState } from "react"; -import { Box, IconButton, Slide, Snackbar, Typography } from "@mui/material"; -import { Close, CheckCircleRounded, ErrorRounded } from "@mui/icons-material"; - -interface InnerProps { - type: string; - duration?: number; - message: ReactNode; - onClose: () => void; -} - -const NoticeInner = (props: InnerProps) => { - const { type, message, duration = 1500, onClose } = props; - const [visible, setVisible] = useState(true); - - const onBtnClose = () => { - setVisible(false); - onClose(); - }; - const onAutoClose = (_e: any, reason: string) => { - if (reason !== "clickaway") onBtnClose(); - }; - - const msgElement = - type === "info" ? ( - message - ) : ( - - {type === "error" && } - {type === "success" && } - - - {message} - - - ); - - return ( - } - transitionDuration={200} - action={ - - - - } - /> - ); -}; - -interface NoticeInstance { - (props: Omit): void; - - info(message: ReactNode, duration?: number): void; - error(message: ReactNode, duration?: number): void; - success(message: ReactNode, duration?: number): void; -} - -let parent: HTMLDivElement = null!; - -// @ts-ignore -export const Notice: NoticeInstance = (props) => { - if (!parent) { - parent = document.createElement("div"); - document.body.appendChild(parent); - } - - const container = document.createElement("div"); - parent.appendChild(container); - const root = createRoot(container); - - const onUnmount = () => { - root.unmount(); - if (parent) setTimeout(() => parent.removeChild(container), 500); - }; - - root.render(); -}; - -(["info", "error", "success"] as const).forEach((type) => { - Notice[type] = (message, duration) => { - setTimeout(() => Notice({ type, message, duration }), 0); - }; -}); diff --git a/src/components/base/base-page.tsx b/src/components/base/base-page.tsx deleted file mode 100644 index 869731a..0000000 --- a/src/components/base/base-page.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { ReactNode } from "react"; -import { Typography } from "@mui/material"; -import { BaseErrorBoundary } from "./base-error-boundary"; - -interface Props { - title?: React.ReactNode; // the page title - header?: React.ReactNode; // something behind title - contentStyle?: React.CSSProperties; - children?: ReactNode; -} - -export const BasePage: React.FC = (props) => { - const { title, header, contentStyle, children } = props; - - return ( - -
-
- - {title} - - - {header} -
- -
-
- {children} -
-
-
-
- ); -}; diff --git a/src/components/base/index.ts b/src/components/base/index.ts deleted file mode 100644 index 3e0e324..0000000 --- a/src/components/base/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { BaseDialog, type DialogRef } from "./base-dialog"; -export { BasePage } from "./base-page"; -export { BaseEmpty } from "./base-empty"; -export { BaseLoading } from "./base-loading"; -export { BaseErrorBoundary } from "./base-error-boundary"; -export { Notice } from "./base-notice"; diff --git a/src/components/connection/connection-detail.tsx b/src/components/connection/connection-detail.tsx deleted file mode 100644 index 7ed786e..0000000 --- a/src/components/connection/connection-detail.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import dayjs from "dayjs"; -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { Box, Button, Snackbar } from "@mui/material"; -import { deleteConnection } from "@/services/api"; -import { truncateStr } from "@/utils/truncate-str"; -import parseTraffic from "@/utils/parse-traffic"; - -export interface ConnectionDetailRef { - open: (detail: IConnectionsItem) => void; -} - -export const ConnectionDetail = forwardRef( - (props, ref) => { - const [open, setOpen] = useState(false); - const [detail, setDetail] = useState(null!); - - useImperativeHandle(ref, () => ({ - open: (detail: IConnectionsItem) => { - if (open) return; - setOpen(true); - setDetail(detail); - }, - })); - - const onClose = () => setOpen(false); - - return ( - - ) : null - } - /> - ); - } -); - -interface InnerProps { - data: IConnectionsItem; - onClose?: () => void; -} - -const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { - const { metadata, rulePayload } = data; - const chains = [...data.chains].reverse().join(" / "); - const rule = rulePayload ? `${data.rule}(${rulePayload})` : data.rule; - const host = metadata.host - ? `${metadata.host}:${metadata.destinationPort}` - : `${metadata.destinationIP}:${metadata.destinationPort}`; - - const information = [ - { label: "Host", value: host }, - { label: "Download", value: parseTraffic(data.download).join(" ") }, - { label: "Upload", value: parseTraffic(data.upload).join(" ") }, - { - label: "DL Speed", - value: parseTraffic(data.curDownload ?? -1).join(" ") + "/s", - }, - { - label: "UL Speed", - value: parseTraffic(data.curUpload ?? -1).join(" ") + "/s", - }, - { label: "Chains", value: chains }, - { label: "Rule", value: rule }, - { - label: "Process", - value: truncateStr(metadata.process || metadata.processPath), - }, - { label: "Time", value: dayjs(data.start).fromNow() }, - { label: "Source", value: `${metadata.sourceIP}:${metadata.sourcePort}` }, - { label: "Destination IP", value: metadata.destinationIP }, - { label: "Type", value: `${metadata.type}(${metadata.network})` }, - ]; - - const onDelete = useLockFn(async () => deleteConnection(data.id)); - - return ( - - {information.map((each) => ( -
- {each.label}: {each.value} -
- ))} - - - - -
- ); -}; diff --git a/src/components/connection/connection-item.tsx b/src/components/connection/connection-item.tsx deleted file mode 100644 index d6c78eb..0000000 --- a/src/components/connection/connection-item.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import dayjs from "dayjs"; -import { useLockFn } from "ahooks"; -import { - styled, - ListItem, - IconButton, - ListItemText, - Box, - alpha, -} from "@mui/material"; -import { CloseRounded } from "@mui/icons-material"; -import { deleteConnection } from "@/services/api"; -import parseTraffic from "@/utils/parse-traffic"; - -const Tag = styled("span")(({ theme }) => ({ - fontSize: "10px", - padding: "0 4px", - lineHeight: 1.375, - border: "1px solid", - borderRadius: 4, - borderColor: alpha(theme.palette.text.secondary, 0.35), - marginRight: "4px", -})); - -interface Props { - value: IConnectionsItem; - onShowDetail?: () => void; -} - -export const ConnectionItem = (props: Props) => { - const { value, onShowDetail } = props; - - const { id, metadata, chains, start, curUpload, curDownload } = value; - - const onDelete = useLockFn(async () => deleteConnection(id)); - const showTraffic = curUpload! >= 100 || curDownload! >= 100; - - return ( - - - - } - > - - - {metadata.network} - - - {metadata.type} - - {!!metadata.process && {metadata.process}} - - {chains?.length > 0 && {chains[value.chains.length - 1]}} - - {dayjs(start).fromNow()} - - {showTraffic && ( - - {parseTraffic(curUpload!)} / {parseTraffic(curDownload!)} - - )} - - } - /> - - ); -}; diff --git a/src/components/connection/connection-table.tsx b/src/components/connection/connection-table.tsx deleted file mode 100644 index 143bf9f..0000000 --- a/src/components/connection/connection-table.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import dayjs from "dayjs"; -import { useMemo, useState } from "react"; -import { DataGrid, GridColDef } from "@mui/x-data-grid"; -import { truncateStr } from "@/utils/truncate-str"; -import parseTraffic from "@/utils/parse-traffic"; - -interface Props { - connections: IConnectionsItem[]; - onShowDetail: (data: IConnectionsItem) => void; -} - -export const ConnectionTable = (props: Props) => { - const { connections, onShowDetail } = props; - - const [columnVisible, setColumnVisible] = useState< - Partial> - >({}); - - const columns: GridColDef[] = [ - { field: "host", headerName: "Host", flex: 220, minWidth: 220 }, - { - field: "download", - headerName: "Download", - width: 88, - align: "right", - headerAlign: "right", - }, - { - field: "upload", - headerName: "Upload", - width: 88, - align: "right", - headerAlign: "right", - }, - { - field: "dlSpeed", - headerName: "DL Speed", - width: 88, - align: "right", - headerAlign: "right", - }, - { - field: "ulSpeed", - headerName: "UL Speed", - width: 88, - align: "right", - headerAlign: "right", - }, - { field: "chains", headerName: "Chains", flex: 360, minWidth: 360 }, - { field: "rule", headerName: "Rule", flex: 300, minWidth: 250 }, - { field: "process", headerName: "Process", flex: 480, minWidth: 480 }, - { - field: "time", - headerName: "Time", - flex: 120, - minWidth: 100, - align: "right", - headerAlign: "right", - }, - { field: "source", headerName: "Source", flex: 200, minWidth: 130 }, - { - field: "destinationIP", - headerName: "Destination IP", - flex: 200, - minWidth: 130, - }, - { field: "type", headerName: "Type", flex: 160, minWidth: 100 }, - ]; - - const connRows = useMemo(() => { - return connections.map((each) => { - const { metadata, rulePayload } = each; - const chains = [...each.chains].reverse().join(" / "); - const rule = rulePayload ? `${each.rule}(${rulePayload})` : each.rule; - - return { - id: each.id, - host: metadata.host - ? `${metadata.host}:${metadata.destinationPort}` - : `${metadata.destinationIP}:${metadata.destinationPort}`, - download: parseTraffic(each.download).join(" "), - upload: parseTraffic(each.upload).join(" "), - dlSpeed: parseTraffic(each.curDownload).join(" ") + "/s", - ulSpeed: parseTraffic(each.curUpload).join(" ") + "/s", - chains, - rule, - process: truncateStr(metadata.process || metadata.processPath), - time: dayjs(each.start).fromNow(), - source: `${metadata.sourceIP}:${metadata.sourcePort}`, - destinationIP: metadata.destinationIP, - type: `${metadata.type}(${metadata.network})`, - - connectionData: each, - }; - }); - }, [connections]); - - return ( - onShowDetail(e.row.connectionData)} - density="compact" - sx={{ border: "none", "div:focus": { outline: "none !important" } }} - columnVisibilityModel={columnVisible} - onColumnVisibilityModelChange={(e) => setColumnVisible(e)} - /> - ); -}; diff --git a/src/components/layout/layout-control.tsx b/src/components/layout/layout-control.tsx deleted file mode 100644 index 6ec12b9..0000000 --- a/src/components/layout/layout-control.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Button } from "@mui/material"; -import { appWindow } from "@tauri-apps/api/window"; -import { - CloseRounded, - CropSquareRounded, - HorizontalRuleRounded, -} from "@mui/icons-material"; - -export const LayoutControl = () => { - const minWidth = 40; - - return ( - <> - - - - - - - ); -}; diff --git a/src/components/layout/layout-item.tsx b/src/components/layout/layout-item.tsx deleted file mode 100644 index 5a33da2..0000000 --- a/src/components/layout/layout-item.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { alpha, ListItem, ListItemButton, ListItemText } from "@mui/material"; -import { useMatch, useResolvedPath, useNavigate } from "react-router-dom"; -import type { LinkProps } from "react-router-dom"; - -export const LayoutItem = (props: LinkProps) => { - const { to, children } = props; - - const resolved = useResolvedPath(to); - const match = useMatch({ path: resolved.pathname, end: true }); - const navigate = useNavigate(); - - return ( - - { - const bgcolor = - mode === "light" - ? alpha(primary.main, 0.15) - : alpha(primary.main, 0.35); - const color = mode === "light" ? primary.main : primary.light; - - return { - "&.Mui-selected": { bgcolor }, - "&.Mui-selected:hover": { bgcolor }, - "&.Mui-selected .MuiListItemText-primary": { color }, - }; - }, - ]} - onClick={() => navigate(to)} - > - - - - ); -}; diff --git a/src/components/layout/layout-traffic.tsx b/src/components/layout/layout-traffic.tsx deleted file mode 100644 index 4e65a87..0000000 --- a/src/components/layout/layout-traffic.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import { Box, Typography } from "@mui/material"; -import { - ArrowDownward, - ArrowUpward, - MemoryOutlined, -} from "@mui/icons-material"; -import { useClashInfo } from "@/hooks/use-clash"; -import { useVerge } from "@/hooks/use-verge"; -import { TrafficGraph, type TrafficRef } from "./traffic-graph"; -import { useLogSetup } from "./use-log-setup"; -import { useVisibility } from "@/hooks/use-visibility"; -import { useWebsocket } from "@/hooks/use-websocket"; -import parseTraffic from "@/utils/parse-traffic"; - -// setup the traffic -export const LayoutTraffic = () => { - const { clashInfo } = useClashInfo(); - const { verge } = useVerge(); - - // whether hide traffic graph - const trafficGraph = verge?.traffic_graph ?? true; - - const trafficRef = useRef(null); - const [traffic, setTraffic] = useState({ up: 0, down: 0 }); - const [memory, setMemory] = useState({ inuse: 0 }); - const pageVisible = useVisibility(); - - // setup log ws during layout - useLogSetup(); - - const { connect, disconnect } = useWebsocket((event) => { - const data = JSON.parse(event.data) as ITrafficItem; - trafficRef.current?.appendData(data); - setTraffic(data); - }); - - useEffect(() => { - if (!clashInfo || !pageVisible) return; - - const { server = "", secret = "" } = clashInfo; - connect(`ws://${server}/traffic?token=${encodeURIComponent(secret)}`); - - return () => { - disconnect(); - }; - }, [clashInfo, pageVisible]); - - /* --------- meta memory information --------- */ - const isMetaCore = verge?.clash_core === "clash-meta"; - const displayMemory = isMetaCore && (verge?.enable_memory_usage ?? true); - - const memoryWs = useWebsocket( - (event) => { - setMemory(JSON.parse(event.data)); - }, - { onError: () => setMemory({ inuse: 0 }) } - ); - - useEffect(() => { - if (!clashInfo || !pageVisible || !displayMemory) return; - const { server = "", secret = "" } = clashInfo; - memoryWs.connect( - `ws://${server}/memory?token=${encodeURIComponent(secret)}` - ); - return () => memoryWs.disconnect(); - }, [clashInfo, pageVisible, displayMemory]); - - const [up, upUnit] = parseTraffic(traffic.up); - const [down, downUnit] = parseTraffic(traffic.down); - const [inuse, inuseUnit] = parseTraffic(memory.inuse); - - const iconStyle: any = { - sx: { mr: "8px", fontSize: 16 }, - }; - const valStyle: any = { - component: "span", - color: "primary", - textAlign: "center", - sx: { flex: "1 1 56px", userSelect: "none" }, - }; - const unitStyle: any = { - component: "span", - color: "grey.500", - fontSize: "12px", - textAlign: "right", - sx: { flex: "0 1 27px", userSelect: "none" }, - }; - - return ( - - {trafficGraph && pageVisible && ( -
- -
- )} - - - - 0 ? "primary" : "disabled"} - /> - {up} - {upUnit}/s - - - - 0 ? "primary" : "disabled"} - /> - {down} - {downUnit}/s - - - {displayMemory && ( - - - {inuse} - {inuseUnit} - - )} - -
- ); -}; diff --git a/src/components/layout/traffic-graph.tsx b/src/components/layout/traffic-graph.tsx deleted file mode 100644 index 5c1a6b7..0000000 --- a/src/components/layout/traffic-graph.tsx +++ /dev/null @@ -1,195 +0,0 @@ -import { forwardRef, useEffect, useImperativeHandle, useRef } from "react"; -import { useTheme } from "@mui/material"; - -const maxPoint = 30; - -const refLineAlpha = 1; -const refLineWidth = 2; - -const upLineAlpha = 0.6; -const upLineWidth = 4; - -const downLineAlpha = 1; -const downLineWidth = 4; - -const defaultList = Array(maxPoint + 2).fill({ up: 0, down: 0 }); - -type TrafficData = { up: number; down: number }; - -export interface TrafficRef { - appendData: (data: TrafficData) => void; - toggleStyle: () => void; -} - -/** - * draw the traffic graph - */ -export const TrafficGraph = forwardRef((props, ref) => { - const countRef = useRef(0); - const styleRef = useRef(true); - const listRef = useRef(defaultList); - const canvasRef = useRef(null!); - - const cacheRef = useRef(null); - - const { palette } = useTheme(); - - useImperativeHandle(ref, () => ({ - appendData: (data: TrafficData) => { - cacheRef.current = data; - }, - toggleStyle: () => { - styleRef.current = !styleRef.current; - }, - })); - - useEffect(() => { - let timer: any; - const zero = { up: 0, down: 0 }; - - const handleData = () => { - const data = cacheRef.current ? cacheRef.current : zero; - cacheRef.current = null; - - const list = listRef.current; - if (list.length > maxPoint + 2) list.shift(); - list.push(data); - countRef.current = 0; - - timer = setTimeout(handleData, 1000); - }; - - handleData(); - - return () => { - if (timer) clearTimeout(timer); - }; - }, []); - - useEffect(() => { - let raf = 0; - const canvas = canvasRef.current!; - - if (!canvas) return; - - const context = canvas.getContext("2d")!; - - if (!context) return; - - const { primary, secondary, divider } = palette; - const refLineColor = divider || "rgba(0, 0, 0, 0.12)"; - const upLineColor = secondary.main || "#9c27b0"; - const downLineColor = primary.main || "#5b5c9d"; - - const width = canvas.width; - const height = canvas.height; - const dx = width / maxPoint; - const dy = height / 7; - const l1 = dy; - const l2 = dy * 4; - - const countY = (v: number) => { - const h = height; - - if (v == 0) return h - 1; - if (v <= 10) return h - (v / 10) * dy; - if (v <= 100) return h - (v / 100 + 1) * dy; - if (v <= 1024) return h - (v / 1024 + 2) * dy; - if (v <= 10240) return h - (v / 10240 + 3) * dy; - if (v <= 102400) return h - (v / 102400 + 4) * dy; - if (v <= 1048576) return h - (v / 1048576 + 5) * dy; - if (v <= 10485760) return h - (v / 10485760 + 6) * dy; - return 1; - }; - - const drawBezier = (list: number[], offset: number) => { - const points = list.map((y, i) => [ - (dx * (i - 1) - offset + 3) | 0, - countY(y), - ]); - - let x = points[0][0]; - let y = points[0][1]; - - context.moveTo(x, y); - - for (let i = 1; i < points.length; i++) { - const p1 = points[i]; - const p2 = points[i + 1] || p1; - - const x1 = (p1[0] + p2[0]) / 2; - const y1 = (p1[1] + p2[1]) / 2; - - context.quadraticCurveTo(p1[0], p1[1], x1, y1); - x = x1; - y = y1; - } - }; - - const drawLine = (list: number[], offset: number) => { - const points = list.map((y, i) => [ - (dx * (i - 1) - offset) | 0, - countY(y), - ]); - - context.moveTo(points[0][0], points[0][1]); - - for (let i = 1; i < points.length; i++) { - const p = points[i]; - context.lineTo(p[0], p[1]); - } - }; - - const drawGraph = (lastTime: number) => { - const listUp = listRef.current.map((v) => v.up); - const listDown = listRef.current.map((v) => v.down); - const lineStyle = styleRef.current; - - const now = Date.now(); - const diff = now - lastTime; - const temp = Math.min((diff / 1000) * dx + countRef.current, dx); - const offset = countRef.current === 0 ? 0 : temp; - countRef.current = temp; - - context.clearRect(0, 0, width, height); - - // Reference lines - context.beginPath(); - context.globalAlpha = refLineAlpha; - context.lineWidth = refLineWidth; - context.strokeStyle = refLineColor; - context.moveTo(0, l1); - context.lineTo(width, l1); - context.moveTo(0, l2); - context.lineTo(width, l2); - context.stroke(); - context.closePath(); - - context.beginPath(); - context.globalAlpha = upLineAlpha; - context.lineWidth = upLineWidth; - context.strokeStyle = upLineColor; - lineStyle ? drawBezier(listUp, offset) : drawLine(listUp, offset); - context.stroke(); - context.closePath(); - - context.beginPath(); - context.globalAlpha = downLineAlpha; - context.lineWidth = downLineWidth; - context.strokeStyle = downLineColor; - lineStyle ? drawBezier(listDown, offset) : drawLine(listDown, offset); - context.stroke(); - context.closePath(); - - raf = requestAnimationFrame(() => drawGraph(now)); - }; - - drawGraph(Date.now()); - - return () => { - cancelAnimationFrame(raf); - }; - }, [palette]); - - return ; -}); diff --git a/src/components/layout/update-button.tsx b/src/components/layout/update-button.tsx deleted file mode 100644 index b71ea07..0000000 --- a/src/components/layout/update-button.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import useSWR from "swr"; -import { useRef } from "react"; -import { Button } from "@mui/material"; -import { checkUpdate } from "@tauri-apps/api/updater"; -import { UpdateViewer } from "../setting/mods/update-viewer"; -import { DialogRef } from "../base"; - -interface Props { - className?: string; -} - -export const UpdateButton = (props: Props) => { - const { className } = props; - - const viewerRef = useRef(null); - - const { data: updateInfo } = useSWR("checkUpdate", checkUpdate, { - errorRetryCount: 2, - revalidateIfStale: false, - focusThrottleInterval: 36e5, // 1 hour - }); - - if (!updateInfo?.shouldUpdate) return null; - - return ( - <> - - - - - ); -}; diff --git a/src/components/layout/use-custom-theme.ts b/src/components/layout/use-custom-theme.ts deleted file mode 100644 index e029494..0000000 --- a/src/components/layout/use-custom-theme.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { useEffect, useMemo } from "react"; -import { useRecoilState } from "recoil"; -import { createTheme, Theme } from "@mui/material"; -import { appWindow } from "@tauri-apps/api/window"; -import { atomThemeMode } from "@/services/states"; -import { defaultTheme, defaultDarkTheme } from "@/pages/_theme"; -import { useVerge } from "@/hooks/use-verge"; - -/** - * custom theme - */ -export const useCustomTheme = () => { - const { verge } = useVerge(); - const { theme_mode, theme_setting } = verge ?? {}; - const [mode, setMode] = useRecoilState(atomThemeMode); - - useEffect(() => { - const themeMode = ["light", "dark", "system"].includes(theme_mode!) - ? theme_mode! - : "light"; - - if (themeMode !== "system") { - setMode(themeMode); - return; - } - - appWindow.theme().then((m) => m && setMode(m)); - const unlisten = appWindow.onThemeChanged((e) => setMode(e.payload)); - - return () => { - unlisten.then((fn) => fn()); - }; - }, [theme_mode]); - - const theme = useMemo(() => { - const setting = theme_setting || {}; - const dt = mode === "light" ? defaultTheme : defaultDarkTheme; - - let theme: Theme; - - try { - theme = createTheme({ - breakpoints: { - values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 }, - }, - palette: { - mode, - primary: { main: setting.primary_color || dt.primary_color }, - secondary: { main: setting.secondary_color || dt.secondary_color }, - info: { main: setting.info_color || dt.info_color }, - error: { main: setting.error_color || dt.error_color }, - warning: { main: setting.warning_color || dt.warning_color }, - success: { main: setting.success_color || dt.success_color }, - text: { - primary: setting.primary_text || dt.primary_text, - secondary: setting.secondary_text || dt.secondary_text, - }, - }, - typography: { - // todo - fontFamily: setting.font_family - ? `${setting.font_family}, ${dt.font_family}` - : dt.font_family, - }, - }); - } catch { - // fix #294 - theme = createTheme({ - breakpoints: { - values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 }, - }, - palette: { - mode, - primary: { main: dt.primary_color }, - secondary: { main: dt.secondary_color }, - info: { main: dt.info_color }, - error: { main: dt.error_color }, - warning: { main: dt.warning_color }, - success: { main: dt.success_color }, - text: { primary: dt.primary_text, secondary: dt.secondary_text }, - }, - typography: { fontFamily: dt.font_family }, - }); - } - - // css - const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5"; - const scrollColor = mode === "light" ? "#90939980" : "#54545480"; - - const rootEle = document.documentElement; - rootEle.style.setProperty("--selection-color", selectColor); - rootEle.style.setProperty("--scroller-color", scrollColor); - rootEle.style.setProperty("--primary-main", theme.palette.primary.main); - - // inject css - let style = document.querySelector("style#verge-theme"); - if (!style) { - style = document.createElement("style"); - style.id = "verge-theme"; - document.head.appendChild(style!); - } - if (style) { - style.innerHTML = setting.css_injection || ""; - } - - // update svg icon - const { palette } = theme; - - setTimeout(() => { - const dom = document.querySelector("#Gradient2"); - if (dom) { - dom.innerHTML = ` - - - - `; - } - }, 0); - - return theme; - }, [mode, theme_setting]); - - return { theme }; -}; diff --git a/src/components/layout/use-log-setup.ts b/src/components/layout/use-log-setup.ts deleted file mode 100644 index 0c130ac..0000000 --- a/src/components/layout/use-log-setup.ts +++ /dev/null @@ -1,39 +0,0 @@ -import dayjs from "dayjs"; -import { useEffect } from "react"; -import { useRecoilValue, useSetRecoilState } from "recoil"; -import { getClashLogs } from "@/services/cmds"; -import { useClashInfo } from "@/hooks/use-clash"; -import { atomEnableLog, atomLogData } from "@/services/states"; -import { useWebsocket } from "@/hooks/use-websocket"; - -const MAX_LOG_NUM = 1000; - -// setup the log websocket -export const useLogSetup = () => { - const { clashInfo } = useClashInfo(); - - const enableLog = useRecoilValue(atomEnableLog); - const setLogData = useSetRecoilState(atomLogData); - - const { connect, disconnect } = useWebsocket((event) => { - const data = JSON.parse(event.data) as ILogItem; - const time = dayjs().format("MM-DD HH:mm:ss"); - setLogData((l) => { - if (l.length >= MAX_LOG_NUM) l.shift(); - return [...l, { ...data, time }]; - }); - }); - - useEffect(() => { - if (!enableLog || !clashInfo) return; - - getClashLogs().then(setLogData); - - const { server = "", secret = "" } = clashInfo; - connect(`ws://${server}/logs?token=${encodeURIComponent(secret)}`); - - return () => { - disconnect(); - }; - }, [clashInfo, enableLog]); -}; diff --git a/src/components/log/log-item.tsx b/src/components/log/log-item.tsx deleted file mode 100644 index 1aa0804..0000000 --- a/src/components/log/log-item.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { styled, Box } from "@mui/material"; - -const Item = styled(Box)(({ theme: { palette, typography } }) => ({ - padding: "8px 0", - margin: "0 12px", - lineHeight: 1.35, - borderBottom: `1px solid ${palette.divider}`, - fontSize: "0.875rem", - fontFamily: typography.fontFamily, - userSelect: "text", - "& .time": { - color: palette.text.secondary, - }, - "& .type": { - display: "inline-block", - marginLeft: 8, - textAlign: "center", - borderRadius: 2, - textTransform: "uppercase", - fontWeight: "600", - }, - '& .type[data-type="error"], & .type[data-type="err"]': { - color: palette.error.main, - }, - '& .type[data-type="warning"], & .type[data-type="warn"]': { - color: palette.warning.main, - }, - '& .type[data-type="info"], & .type[data-type="inf"]': { - color: palette.info.main, - }, - "& .data": { - color: palette.text.primary, - }, -})); - -interface Props { - value: ILogItem; -} - -const LogItem = (props: Props) => { - const { value } = props; - - return ( - -
- {value.time} - - {value.type} - -
-
- {value.payload} -
-
- ); -}; - -export default LogItem; diff --git a/src/components/profile/editor-viewer.tsx b/src/components/profile/editor-viewer.tsx deleted file mode 100644 index 28608e9..0000000 --- a/src/components/profile/editor-viewer.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useEffect, useRef } from "react"; -import { useLockFn } from "ahooks"; -import { useRecoilValue } from "recoil"; -import { useTranslation } from "react-i18next"; -import { - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, -} from "@mui/material"; -import { atomThemeMode } from "@/services/states"; -import { readProfileFile, saveProfileFile } from "@/services/cmds"; -import { Notice } from "@/components/base"; - -import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js"; -import "monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution.js"; -import "monaco-editor/esm/vs/editor/contrib/folding/browser/folding.js"; -import { editor } from "monaco-editor/esm/vs/editor/editor.api"; - -interface Props { - uid: string; - open: boolean; - mode: "yaml" | "javascript"; - onClose: () => void; - onChange?: () => void; -} - -export const EditorViewer = (props: Props) => { - const { uid, open, mode, onClose, onChange } = props; - - const { t } = useTranslation(); - const editorRef = useRef(); - const instanceRef = useRef(null); - const themeMode = useRecoilValue(atomThemeMode); - - useEffect(() => { - if (!open) return; - - readProfileFile(uid).then((data) => { - const dom = editorRef.current; - - if (!dom) return; - if (instanceRef.current) instanceRef.current.dispose(); - - instanceRef.current = editor.create(editorRef.current, { - value: data, - language: mode, - theme: themeMode === "light" ? "vs" : "vs-dark", - minimap: { enabled: false }, - }); - }); - - return () => { - if (instanceRef.current) { - instanceRef.current.dispose(); - instanceRef.current = null; - } - }; - }, [open]); - - const onSave = useLockFn(async () => { - const value = instanceRef.current?.getValue(); - - if (value == null) return; - - try { - await saveProfileFile(uid, value); - onChange?.(); - onClose(); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); - - return ( - - {t("Edit File")} - - -
- - - - - - -
- ); -}; diff --git a/src/components/profile/file-input.tsx b/src/components/profile/file-input.tsx deleted file mode 100644 index 5357224..0000000 --- a/src/components/profile/file-input.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useRef, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { Box, Button, Typography } from "@mui/material"; - -interface Props { - onChange: (value: string) => void; -} - -export const FileInput = (props: Props) => { - const { onChange } = props; - - const { t } = useTranslation(); - // file input - const inputRef = useRef(); - const [loading, setLoading] = useState(false); - const [fileName, setFileName] = useState(""); - - const onFileInput = useLockFn(async (e: any) => { - const file = e.target.files?.[0] as File; - - if (!file) return; - - setFileName(file.name); - setLoading(true); - - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = (event) => { - resolve(null); - onChange(event.target?.result as string); - }; - reader.onerror = reject; - reader.readAsText(file); - }).finally(() => setLoading(false)); - }); - - return ( - - - - - - - {loading ? "Loading..." : fileName} - - - ); -}; diff --git a/src/components/profile/log-viewer.tsx b/src/components/profile/log-viewer.tsx deleted file mode 100644 index 4792468..0000000 --- a/src/components/profile/log-viewer.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Fragment } from "react"; -import { useTranslation } from "react-i18next"; -import { - Button, - Chip, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - Divider, - Typography, -} from "@mui/material"; -import { BaseEmpty } from "@/components/base"; - -interface Props { - open: boolean; - logInfo: [string, string][]; - onClose: () => void; -} - -export const LogViewer = (props: Props) => { - const { open, logInfo, onClose } = props; - - const { t } = useTranslation(); - - return ( - - {t("Script Console")} - - - {logInfo.map(([level, log], index) => ( - - - - {log} - - - - ))} - - {logInfo.length === 0 && } - - - - - - - ); -}; diff --git a/src/components/profile/profile-box.tsx b/src/components/profile/profile-box.tsx deleted file mode 100644 index 6e15a87..0000000 --- a/src/components/profile/profile-box.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { alpha, Box, styled } from "@mui/material"; - -export const ProfileBox = styled(Box)( - ({ theme, "aria-selected": selected }) => { - const { mode, primary, text, grey, background } = theme.palette; - const key = `${mode}-${!!selected}`; - - const backgroundColor = { - "light-true": alpha(primary.main, 0.2), - "light-false": alpha(background.paper, 0.75), - "dark-true": alpha(primary.main, 0.45), - "dark-false": alpha(grey[700], 0.45), - }[key]!; - - const color = { - "light-true": text.secondary, - "light-false": text.secondary, - "dark-true": alpha(text.secondary, 0.85), - "dark-false": alpha(text.secondary, 0.65), - }[key]!; - - const h2color = { - "light-true": primary.main, - "light-false": text.primary, - "dark-true": primary.light, - "dark-false": text.primary, - }[key]!; - - return { - position: "relative", - width: "100%", - display: "block", - cursor: "pointer", - textAlign: "left", - borderRadius: theme.shape.borderRadius, - boxShadow: theme.shadows[2], - padding: "8px 16px", - boxSizing: "border-box", - backgroundColor, - color, - "& h2": { color: h2color }, - }; - } -); diff --git a/src/components/profile/profile-item.tsx b/src/components/profile/profile-item.tsx deleted file mode 100644 index 72fda6f..0000000 --- a/src/components/profile/profile-item.tsx +++ /dev/null @@ -1,341 +0,0 @@ -import dayjs from "dayjs"; -import { mutate } from "swr"; -import { useEffect, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useRecoilState } from "recoil"; -import { useTranslation } from "react-i18next"; -import { - Box, - Typography, - LinearProgress, - IconButton, - keyframes, - MenuItem, - Menu, - CircularProgress, -} from "@mui/material"; -import { RefreshRounded } from "@mui/icons-material"; -import { atomLoadingCache } from "@/services/states"; -import { updateProfile, deleteProfile, viewProfile } from "@/services/cmds"; -import { Notice } from "@/components/base"; -import { EditorViewer } from "./editor-viewer"; -import { ProfileBox } from "./profile-box"; -import parseTraffic from "@/utils/parse-traffic"; - -const round = keyframes` - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -`; - -interface Props { - selected: boolean; - activating: boolean; - itemData: IProfileItem; - onSelect: (force: boolean) => void; - onEdit: () => void; -} - -export const ProfileItem = (props: Props) => { - const { selected, activating, itemData, onSelect, onEdit } = props; - - const { t } = useTranslation(); - const [anchorEl, setAnchorEl] = useState(null); - const [position, setPosition] = useState({ left: 0, top: 0 }); - const [loadingCache, setLoadingCache] = useRecoilState(atomLoadingCache); - - const { uid, name = "Profile", extra, updated = 0 } = itemData; - - // local file mode - // remote file mode - const hasUrl = !!itemData.url; - const hasExtra = !!extra; // only subscription url has extra info - - const { upload = 0, download = 0, total = 0 } = extra ?? {}; - const from = parseUrl(itemData.url); - const expire = parseExpire(extra?.expire); - const progress = Math.round(((download + upload) * 100) / (total + 0.1)); - - const loading = loadingCache[itemData.uid] ?? false; - - // interval update fromNow field - const [, setRefresh] = useState({}); - useEffect(() => { - if (!hasUrl) return; - - let timer: any = null; - - const handler = () => { - const now = Date.now(); - const lastUpdate = updated * 1000; - // 大于一天的不管 - if (now - lastUpdate >= 24 * 36e5) return; - - const wait = now - lastUpdate >= 36e5 ? 30e5 : 5e4; - - timer = setTimeout(() => { - setRefresh({}); - handler(); - }, wait); - }; - - handler(); - - return () => { - if (timer) clearTimeout(timer); - }; - }, [hasUrl, updated]); - - const [fileOpen, setFileOpen] = useState(false); - - const onEditInfo = () => { - setAnchorEl(null); - onEdit(); - }; - - const onEditFile = () => { - setAnchorEl(null); - setFileOpen(true); - }; - - const onForceSelect = () => { - setAnchorEl(null); - onSelect(true); - }; - - const onOpenFile = useLockFn(async () => { - setAnchorEl(null); - try { - await viewProfile(itemData.uid); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - /// 0 不使用任何代理 - /// 1 使用配置好的代理 - /// 2 至少使用一个代理,根据配置,如果没配置,默认使用系统代理 - const onUpdate = useLockFn(async (type: 0 | 1 | 2) => { - setAnchorEl(null); - setLoadingCache((cache) => ({ ...cache, [itemData.uid]: true })); - - const option: Partial = {}; - - if (type === 0) { - option.with_proxy = false; - option.self_proxy = false; - } else if (type === 1) { - // nothing - } else if (type === 2) { - if (itemData.option?.self_proxy) { - option.with_proxy = false; - option.self_proxy = true; - } else { - option.with_proxy = true; - option.self_proxy = false; - } - } - - try { - await updateProfile(itemData.uid, option); - mutate("getProfiles"); - } catch (err: any) { - const errmsg = err?.message || err.toString(); - Notice.error( - errmsg.replace(/error sending request for url (\S+?): /, "") - ); - } finally { - setLoadingCache((cache) => ({ ...cache, [itemData.uid]: false })); - } - }); - - const onDelete = useLockFn(async () => { - setAnchorEl(null); - try { - await deleteProfile(itemData.uid); - mutate("getProfiles"); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - const urlModeMenu = [ - { label: "Select", handler: onForceSelect }, - { label: "Edit Info", handler: onEditInfo }, - { label: "Edit File", handler: onEditFile }, - { label: "Open File", handler: onOpenFile }, - { label: "Update", handler: () => onUpdate(0) }, - { label: "Update(Proxy)", handler: () => onUpdate(2) }, - { label: "Delete", handler: onDelete }, - ]; - const fileModeMenu = [ - { label: "Select", handler: onForceSelect }, - { label: "Edit Info", handler: onEditInfo }, - { label: "Edit File", handler: onEditFile }, - { label: "Open File", handler: onOpenFile }, - { label: "Delete", handler: onDelete }, - ]; - - const boxStyle = { - height: 26, - display: "flex", - alignItems: "center", - justifyContent: "space-between", - }; - - return ( - <> - onSelect(false)} - onContextMenu={(event) => { - const { clientX, clientY } = event; - setPosition({ top: clientY, left: clientX }); - setAnchorEl(event.currentTarget); - event.preventDefault(); - }} - > - {activating && ( - - - - )} - - - - {name} - - - {/* only if has url can it be updated */} - {hasUrl && ( - { - e.stopPropagation(); - onUpdate(1); - }} - > - - - )} - - - {/* the second line show url's info or description */} - - {hasUrl ? ( - <> - - {from} - - - - {updated > 0 ? dayjs(updated * 1000).fromNow() : ""} - - - ) : ( - - {itemData.desc} - - )} - - - {/* the third line show extra info or last updated time */} - {hasExtra ? ( - - - {parseTraffic(upload + download)} / {parseTraffic(total)} - - {expire} - - ) : ( - - {parseExpire(updated)} - - )} - - - - - setAnchorEl(null)} - anchorPosition={position} - anchorReference="anchorPosition" - transitionDuration={225} - MenuListProps={{ sx: { py: 0.5 } }} - onContextMenu={(e) => { - setAnchorEl(null); - e.preventDefault(); - }} - > - {(hasUrl ? urlModeMenu : fileModeMenu).map((item) => ( - - {t(item.label)} - - ))} - - - setFileOpen(false)} - /> - - ); -}; - -function parseUrl(url?: string) { - if (!url) return ""; - const regex = /https?:\/\/(.+?)\//; - const result = url.match(regex); - return result ? result[1] : "local file"; -} - -function parseExpire(expire?: number) { - if (!expire) return "-"; - return dayjs(expire * 1000).format("YYYY-MM-DD"); -} diff --git a/src/components/profile/profile-more.tsx b/src/components/profile/profile-more.tsx deleted file mode 100644 index f979665..0000000 --- a/src/components/profile/profile-more.tsx +++ /dev/null @@ -1,243 +0,0 @@ -import dayjs from "dayjs"; -import { useState } from "react"; -import { useTranslation } from "react-i18next"; -import { useLockFn } from "ahooks"; -import { - Box, - Badge, - Chip, - Typography, - MenuItem, - Menu, - IconButton, -} from "@mui/material"; -import { FeaturedPlayListRounded } from "@mui/icons-material"; -import { viewProfile } from "@/services/cmds"; -import { Notice } from "@/components/base"; -import { EditorViewer } from "./editor-viewer"; -import { ProfileBox } from "./profile-box"; -import { LogViewer } from "./log-viewer"; - -interface Props { - selected: boolean; - itemData: IProfileItem; - enableNum: number; - logInfo?: [string, string][]; - onEnable: () => void; - onDisable: () => void; - onMoveTop: () => void; - onMoveEnd: () => void; - onDelete: () => void; - onEdit: () => void; -} - -// profile enhanced item -export const ProfileMore = (props: Props) => { - const { - selected, - itemData, - enableNum, - logInfo = [], - onEnable, - onDisable, - onMoveTop, - onMoveEnd, - onDelete, - onEdit, - } = props; - - const { uid, type } = itemData; - const { t, i18n } = useTranslation(); - const [anchorEl, setAnchorEl] = useState(null); - const [position, setPosition] = useState({ left: 0, top: 0 }); - const [fileOpen, setFileOpen] = useState(false); - const [logOpen, setLogOpen] = useState(false); - - const onEditInfo = () => { - setAnchorEl(null); - onEdit(); - }; - - const onEditFile = () => { - setAnchorEl(null); - setFileOpen(true); - }; - - const onOpenFile = useLockFn(async () => { - setAnchorEl(null); - try { - await viewProfile(itemData.uid); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - const fnWrapper = (fn: () => void) => () => { - setAnchorEl(null); - return fn(); - }; - - const hasError = !!logInfo.find((e) => e[0] === "exception"); - const showMove = enableNum > 1 && !hasError; - - const enableMenu = [ - { label: "Disable", handler: fnWrapper(onDisable) }, - { label: "Edit Info", handler: onEditInfo }, - { label: "Edit File", handler: onEditFile }, - { label: "Open File", handler: onOpenFile }, - { label: "To Top", show: showMove, handler: fnWrapper(onMoveTop) }, - { label: "To End", show: showMove, handler: fnWrapper(onMoveEnd) }, - { label: "Delete", handler: fnWrapper(onDelete) }, - ]; - - const disableMenu = [ - { label: "Enable", handler: fnWrapper(onEnable) }, - { label: "Edit Info", handler: onEditInfo }, - { label: "Edit File", handler: onEditFile }, - { label: "Open File", handler: onOpenFile }, - { label: "Delete", handler: fnWrapper(onDelete) }, - ]; - - const boxStyle = { - height: 26, - display: "flex", - alignItems: "center", - justifyContent: "space-between", - lineHeight: 1, - }; - - return ( - <> - onSelect(false)} - onContextMenu={(event) => { - const { clientX, clientY } = event; - setPosition({ top: clientY, left: clientX }); - setAnchorEl(event.currentTarget); - event.preventDefault(); - }} - > - - - {itemData.name} - - - - - - - {selected && type === "script" ? ( - hasError ? ( - - setLogOpen(true)} - > - - - - ) : ( - setLogOpen(true)} - > - - - ) - ) : ( - - {itemData.desc} - - )} - - - {!!itemData.updated - ? dayjs(itemData.updated! * 1000).fromNow() - : ""} - - - - - setAnchorEl(null)} - anchorPosition={position} - anchorReference="anchorPosition" - transitionDuration={225} - MenuListProps={{ sx: { py: 0.5 } }} - onContextMenu={(e) => { - setAnchorEl(null); - e.preventDefault(); - }} - > - {(selected ? enableMenu : disableMenu) - .filter((item: any) => item.show !== false) - .map((item) => ( - - {t(item.label)} - - ))} - - - setFileOpen(false)} - /> - - {selected && ( - setLogOpen(false)} - /> - )} - - ); -}; - -function parseExpire(expire?: number) { - if (!expire) return "-"; - return dayjs(expire * 1000).format("YYYY-MM-DD"); -} diff --git a/src/components/profile/profile-viewer.tsx b/src/components/profile/profile-viewer.tsx deleted file mode 100644 index f928053..0000000 --- a/src/components/profile/profile-viewer.tsx +++ /dev/null @@ -1,279 +0,0 @@ -import { - forwardRef, - useEffect, - useImperativeHandle, - useRef, - useState, -} from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { useForm, Controller } from "react-hook-form"; -import { - Box, - FormControl, - InputAdornment, - InputLabel, - MenuItem, - Select, - Switch, - styled, - TextField, -} from "@mui/material"; -import { createProfile, patchProfile } from "@/services/cmds"; -import { BaseDialog, Notice } from "@/components/base"; -import { version } from "@root/package.json"; -import { FileInput } from "./file-input"; - -interface Props { - onChange: () => void; -} - -export interface ProfileViewerRef { - create: () => void; - edit: (item: IProfileItem) => void; -} - -// create or edit the profile -// remote / local / merge / script -export const ProfileViewer = forwardRef( - (props, ref) => { - const { t } = useTranslation(); - const [open, setOpen] = useState(false); - const [openType, setOpenType] = useState<"new" | "edit">("new"); - - // file input - const fileDataRef = useRef(null); - - const { control, watch, register, ...formIns } = useForm({ - defaultValues: { - type: "remote", - name: "Remote File", - desc: "", - url: "", - option: { - // user_agent: "", - with_proxy: false, - self_proxy: false, - }, - }, - }); - - useImperativeHandle(ref, () => ({ - create: () => { - setOpenType("new"); - setOpen(true); - }, - edit: (item) => { - if (item) { - Object.entries(item).forEach(([key, value]) => { - formIns.setValue(key as any, value); - }); - } - setOpenType("edit"); - setOpen(true); - }, - })); - - const selfProxy = watch("option.self_proxy"); - const withProxy = watch("option.with_proxy"); - - useEffect(() => { - if (selfProxy) formIns.setValue("option.with_proxy", false); - }, [selfProxy]); - - useEffect(() => { - if (withProxy) formIns.setValue("option.self_proxy", false); - }, [withProxy]); - - const handleOk = useLockFn( - formIns.handleSubmit(async (form) => { - try { - if (!form.type) throw new Error("`Type` should not be null"); - if (form.type === "remote" && !form.url) { - throw new Error("The URL should not be null"); - } - if (form.type !== "remote" && form.type !== "local") { - delete form.option; - } - if (form.option?.update_interval) { - form.option.update_interval = +form.option.update_interval; - } - const name = form.name || `${form.type} file`; - const item = { ...form, name }; - - // 创建 - if (openType === "new") { - await createProfile(item, fileDataRef.current); - } - // 编辑 - else { - if (!form.uid) throw new Error("UID not found"); - await patchProfile(form.uid, item); - } - setOpen(false); - setTimeout(() => formIns.reset(), 500); - fileDataRef.current = null; - props.onChange(); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }) - ); - - const handleClose = () => { - setOpen(false); - fileDataRef.current = null; - setTimeout(() => formIns.reset(), 500); - }; - - const text = { - fullWidth: true, - size: "small", - margin: "normal", - variant: "outlined", - autoComplete: "off", - autoCorrect: "off", - } as const; - - const formType = watch("type"); - const isRemote = formType === "remote"; - const isLocal = formType === "local"; - - return ( - - ( - - {t("Type")} - - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - - {isRemote && ( - <> - ( - - )} - /> - - ( - - )} - /> - - )} - - {(isRemote || isLocal) && ( - ( - { - e.target.value = e.target.value - ?.replace(/\D/, "") - .slice(0, 10); - field.onChange(e); - }} - label={t("Update Interval")} - InputProps={{ - endAdornment: ( - mins - ), - }} - /> - )} - /> - )} - - {isLocal && openType === "new" && ( - (fileDataRef.current = val)} /> - )} - - {isRemote && ( - <> - ( - - {t("Use System Proxy")} - - - )} - /> - - ( - - {t("Use Clash Proxy")} - - - )} - /> - - )} - - ); - } -); - -const StyledBox = styled(Box)(() => ({ - margin: "8px 0 8px 8px", - display: "flex", - alignItems: "center", - justifyContent: "space-between", -})); diff --git a/src/components/proxy/provider-button.tsx b/src/components/proxy/provider-button.tsx deleted file mode 100644 index 5a63072..0000000 --- a/src/components/proxy/provider-button.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import dayjs from "dayjs"; -import useSWR, { mutate } from "swr"; -import { useState } from "react"; -import { - Button, - IconButton, - List, - ListItem, - ListItemText, -} from "@mui/material"; -import { RefreshRounded } from "@mui/icons-material"; -import { useTranslation } from "react-i18next"; -import { useLockFn } from "ahooks"; -import { getProviders, providerUpdate } from "@/services/api"; -import { BaseDialog } from "../base"; - -export const ProviderButton = () => { - const { t } = useTranslation(); - const { data } = useSWR("getProviders", getProviders); - - const [open, setOpen] = useState(false); - - const hasProvider = Object.keys(data || {}).length > 0; - - const handleUpdate = useLockFn(async (key: string) => { - await providerUpdate(key); - await mutate("getProxies"); - await mutate("getProviders"); - }); - - if (!hasProvider) return null; - - return ( - <> - - - setOpen(false)} - onCancel={() => setOpen(false)} - > - - {Object.entries(data || {}).map(([key, item]) => { - const time = dayjs(item.updatedAt); - return ( - - - - Type: {item.vehicleType} - - - Updated: {time.fromNow()} - - - } - /> - handleUpdate(key)} - > - - - - ); - })} - - - - ); -}; diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx deleted file mode 100644 index 4637cb4..0000000 --- a/src/components/proxy/proxy-groups.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { useRef } from "react"; -import { useLockFn } from "ahooks"; -import { Virtuoso, type VirtuosoHandle } from "react-virtuoso"; -import { - getConnections, - providerHealthCheck, - updateProxy, - deleteConnection, -} from "@/services/api"; -import { useProfiles } from "@/hooks/use-profiles"; -import { useVerge } from "@/hooks/use-verge"; -import { BaseEmpty } from "../base"; -import { useRenderList } from "./use-render-list"; -import { ProxyRender } from "./proxy-render"; -import delayManager from "@/services/delay"; - -interface Props { - mode: string; -} - -export const ProxyGroups = (props: Props) => { - const { mode } = props; - - const { renderList, onProxies, onHeadState } = useRenderList(mode); - - const { verge } = useVerge(); - const { current, patchCurrent } = useProfiles(); - - const virtuosoRef = useRef(null); - - // 切换分组的节点代理 - const handleChangeProxy = useLockFn( - async (group: IProxyGroupItem, proxy: IProxyItem) => { - if (group.type !== "Selector" && group.type !== "Fallback") return; - - const { name, now } = group; - await updateProxy(name, proxy.name); - onProxies(); - - // 断开连接 - if (verge?.auto_close_connection) { - getConnections().then(({ connections }) => { - connections.forEach((conn) => { - if (conn.chains.includes(now!)) { - deleteConnection(conn.id); - } - }); - }); - } - - // 保存到selected中 - if (!current) return; - if (!current.selected) current.selected = []; - - const index = current.selected.findIndex( - (item) => item.name === group.name - ); - - if (index < 0) { - current.selected.push({ name, now: proxy.name }); - } else { - current.selected[index] = { name, now: proxy.name }; - } - await patchCurrent({ selected: current.selected }); - } - ); - - // 测全部延迟 - const handleCheckAll = useLockFn(async (groupName: string) => { - const proxies = renderList - .filter( - (e) => e.group?.name === groupName && (e.type === 2 || e.type === 4) - ) - .flatMap((e) => e.proxyCol || e.proxy!) - .filter(Boolean); - - const providers = new Set(proxies.map((p) => p!.provider!).filter(Boolean)); - - if (providers.size) { - Promise.allSettled( - [...providers].map((p) => providerHealthCheck(p)) - ).then(() => onProxies()); - } - - const names = proxies.filter((p) => !p!.provider).map((p) => p!.name); - await delayManager.checkListDelay(names, groupName); - - onProxies(); - }); - - // 滚到对应的节点 - const handleLocation = (group: IProxyGroupItem) => { - if (!group) return; - const { name, now } = group; - - const index = renderList.findIndex( - (e) => - e.group?.name === name && - ((e.type === 2 && e.proxy?.name === now) || - (e.type === 4 && e.proxyCol?.some((p) => p.name === now))) - ); - - if (index >= 0) { - virtuosoRef.current?.scrollToIndex?.({ - index, - align: "center", - behavior: "smooth", - }); - } - }; - - if (mode === "direct") { - return ; - } - - return ( - ( - - )} - /> - ); -}; diff --git a/src/components/proxy/proxy-head.tsx b/src/components/proxy/proxy-head.tsx deleted file mode 100644 index fe29cb8..0000000 --- a/src/components/proxy/proxy-head.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { Box, IconButton, TextField, SxProps } from "@mui/material"; -import { - AccessTimeRounded, - MyLocationRounded, - NetworkCheckRounded, - FilterAltRounded, - FilterAltOffRounded, - VisibilityRounded, - VisibilityOffRounded, - WifiTetheringRounded, - WifiTetheringOffRounded, - SortByAlphaRounded, - SortRounded, -} from "@mui/icons-material"; -import { useVerge } from "@/hooks/use-verge"; -import type { HeadState } from "./use-head-state"; -import type { ProxySortType } from "./use-filter-sort"; -import delayManager from "@/services/delay"; - -interface Props { - sx?: SxProps; - groupName: string; - headState: HeadState; - onLocation: () => void; - onCheckDelay: () => void; - onHeadState: (val: Partial) => void; -} - -export const ProxyHead = (props: Props) => { - const { sx = {}, groupName, headState, onHeadState } = props; - - const { showType, sortType, filterText, textState, testUrl } = headState; - - const { t } = useTranslation(); - const [autoFocus, setAutoFocus] = useState(false); - - useEffect(() => { - // fix the focus conflict - const timer = setTimeout(() => setAutoFocus(true), 100); - return () => clearTimeout(timer); - }, []); - - const { verge } = useVerge(); - - useEffect(() => { - delayManager.setUrl(groupName, testUrl || verge?.default_latency_test!); - }, [groupName, testUrl, verge?.default_latency_test]); - - return ( - - - - - - { - // Remind the user that it is custom test url - if (testUrl?.trim() && textState !== "filter") { - onHeadState({ textState: "url" }); - } - props.onCheckDelay(); - }} - > - - - - - onHeadState({ sortType: ((sortType + 1) % 3) as ProxySortType }) - } - > - {sortType !== 1 && sortType !== 2 && } - {sortType === 1 && } - {sortType === 2 && } - - - - onHeadState({ textState: textState === "url" ? null : "url" }) - } - > - {textState === "url" ? ( - - ) : ( - - )} - - - onHeadState({ showType: !showType })} - > - {showType ? : } - - - - onHeadState({ textState: textState === "filter" ? null : "filter" }) - } - > - {textState === "filter" ? ( - - ) : ( - - )} - - - {textState === "filter" && ( - onHeadState({ filterText: e.target.value })} - sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }} - /> - )} - - {textState === "url" && ( - onHeadState({ testUrl: e.target.value })} - sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }} - /> - )} - - ); -}; diff --git a/src/components/proxy/proxy-item-mini.tsx b/src/components/proxy/proxy-item-mini.tsx deleted file mode 100644 index c7e98bc..0000000 --- a/src/components/proxy/proxy-item-mini.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import { useEffect, useState } from "react"; -import { useLockFn } from "ahooks"; -import { CheckCircleOutlineRounded } from "@mui/icons-material"; -import { alpha, Box, ListItemButton, styled, Typography } from "@mui/material"; -import { BaseLoading } from "@/components/base"; -import delayManager from "@/services/delay"; - -interface Props { - groupName: string; - proxy: IProxyItem; - selected: boolean; - showType?: boolean; - onClick?: (name: string) => void; -} - -// 多列布局 -export const ProxyItemMini = (props: Props) => { - const { groupName, proxy, selected, showType = true, onClick } = props; - - // -1/<=0 为 不显示 - // -2 为 loading - const [delay, setDelay] = useState(-1); - - useEffect(() => { - delayManager.setListener(proxy.name, groupName, setDelay); - - return () => { - delayManager.removeListener(proxy.name, groupName); - }; - }, [proxy.name, groupName]); - - useEffect(() => { - if (!proxy) return; - setDelay(delayManager.getDelayFix(proxy, groupName)); - }, [proxy]); - - const onDelay = useLockFn(async () => { - setDelay(-2); - setDelay(await delayManager.checkDelay(proxy.name, groupName)); - }); - - return ( - onClick?.(proxy.name)} - sx={[ - { - height: 56, - borderRadius: 1, - pl: 1.5, - pr: 1, - justifyContent: "space-between", - alignItems: "center", - }, - ({ palette: { mode, primary } }) => { - const bgcolor = - mode === "light" - ? alpha(primary.main, 0.15) - : alpha(primary.main, 0.35); - const color = mode === "light" ? primary.main : primary.light; - const showDelay = delay > 0; - - const shadowColor = - mode === "light" ? "rgba(0,0,0,0.04)" : "rgba(255,255,255,0.08)"; - - return { - "&:hover .the-check": { display: !showDelay ? "block" : "none" }, - "&:hover .the-delay": { display: showDelay ? "block" : "none" }, - "&:hover .the-icon": { display: "none" }, - "&.Mui-selected": { bgcolor, boxShadow: `0 0 0 1px ${bgcolor}` }, - "&.Mui-selected .MuiListItemText-secondary": { color }, - boxShadow: `0 0 0 1px ${shadowColor}`, - }; - }, - ]} - > - - - {proxy.name} - - - {showType && ( - - {!!proxy.provider && ( - {proxy.provider} - )} - {proxy.type} - {proxy.udp && UDP} - - )} - - - - {delay === -2 && ( - - - - )} - - {!proxy.provider && delay !== -2 && ( - // provider的节点不支持检测 - { - e.preventDefault(); - e.stopPropagation(); - onDelay(); - }} - sx={({ palette }) => ({ - display: "none", // hover才显示 - ":hover": { bgcolor: alpha(palette.primary.main, 0.15) }, - })} - > - Check - - )} - - {delay > 0 && ( - // 显示延迟 - { - if (proxy.provider) return; - e.preventDefault(); - e.stopPropagation(); - onDelay(); - }} - color={delayManager.formatDelayColor(delay)} - sx={({ palette }) => - !proxy.provider - ? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } } - : {} - } - > - {delayManager.formatDelay(delay)} - - )} - - {delay !== -2 && delay <= 0 && selected && ( - // 展示已选择的icon - - )} - - - ); -}; - -const Widget = styled(Box)(({ theme: { typography } }) => ({ - padding: "3px 6px", - fontSize: 14, - fontFamily: typography.fontFamily, - borderRadius: "4px", -})); - -const TypeBox = styled(Box)(({ theme: { palette, typography } }) => ({ - display: "inline-block", - border: "1px solid #ccc", - borderColor: alpha(palette.text.secondary, 0.36), - color: alpha(palette.text.secondary, 0.42), - borderRadius: 4, - fontSize: 10, - fontFamily: typography.fontFamily, - marginRight: "4px", - padding: "0 2px", - lineHeight: 1.25, -})); diff --git a/src/components/proxy/proxy-item.tsx b/src/components/proxy/proxy-item.tsx deleted file mode 100644 index d4c63c4..0000000 --- a/src/components/proxy/proxy-item.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { useEffect, useState } from "react"; -import { useLockFn } from "ahooks"; -import { CheckCircleOutlineRounded } from "@mui/icons-material"; -import { - alpha, - Box, - ListItem, - ListItemButton, - ListItemIcon, - ListItemText, - styled, - SxProps, - Theme, -} from "@mui/material"; -import { BaseLoading } from "@/components/base"; -import delayManager from "@/services/delay"; - -interface Props { - groupName: string; - proxy: IProxyItem; - selected: boolean; - showType?: boolean; - sx?: SxProps; - onClick?: (name: string) => void; -} - -const Widget = styled(Box)(() => ({ - padding: "3px 6px", - fontSize: 14, - borderRadius: "4px", -})); - -const TypeBox = styled(Box)(({ theme }) => ({ - display: "inline-block", - border: "1px solid #ccc", - borderColor: alpha(theme.palette.text.secondary, 0.36), - color: alpha(theme.palette.text.secondary, 0.42), - borderRadius: 4, - fontSize: 10, - marginRight: "4px", - padding: "0 2px", - lineHeight: 1.25, -})); - -export const ProxyItem = (props: Props) => { - const { groupName, proxy, selected, showType = true, sx, onClick } = props; - - // -1/<=0 为 不显示 - // -2 为 loading - const [delay, setDelay] = useState(-1); - - useEffect(() => { - delayManager.setListener(proxy.name, groupName, setDelay); - - return () => { - delayManager.removeListener(proxy.name, groupName); - }; - }, [proxy.name, groupName]); - - useEffect(() => { - if (!proxy) return; - setDelay(delayManager.getDelayFix(proxy, groupName)); - }, [proxy]); - - const onDelay = useLockFn(async () => { - setDelay(-2); - setDelay(await delayManager.checkDelay(proxy.name, groupName)); - }); - - return ( - - onClick?.(proxy.name)} - sx={[ - { borderRadius: 1 }, - ({ palette: { mode, primary } }) => { - const bgcolor = - mode === "light" - ? alpha(primary.main, 0.15) - : alpha(primary.main, 0.35); - const color = mode === "light" ? primary.main : primary.light; - const showDelay = delay > 0; - - return { - "&:hover .the-check": { display: !showDelay ? "block" : "none" }, - "&:hover .the-delay": { display: showDelay ? "block" : "none" }, - "&:hover .the-icon": { display: "none" }, - "&.Mui-selected": { bgcolor }, - "&.Mui-selected .MuiListItemText-secondary": { color }, - }; - }, - ]} - > - - {proxy.name} - - {showType && !!proxy.provider && ( - {proxy.provider} - )} - {showType && {proxy.type}} - {showType && proxy.udp && UDP} - - } - /> - - - {delay === -2 && ( - - - - )} - - {!proxy.provider && delay !== -2 && ( - // provider的节点不支持检测 - { - e.preventDefault(); - e.stopPropagation(); - onDelay(); - }} - sx={({ palette }) => ({ - display: "none", // hover才显示 - ":hover": { bgcolor: alpha(palette.primary.main, 0.15) }, - })} - > - Check - - )} - - {delay > 0 && ( - // 显示延迟 - { - if (proxy.provider) return; - e.preventDefault(); - e.stopPropagation(); - onDelay(); - }} - color={delayManager.formatDelayColor(delay)} - sx={({ palette }) => - !proxy.provider - ? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } } - : {} - } - > - {delayManager.formatDelay(delay)} - - )} - - {delay !== -2 && delay <= 0 && selected && ( - // 展示已选择的icon - - )} - - - - ); -}; diff --git a/src/components/proxy/proxy-render.tsx b/src/components/proxy/proxy-render.tsx deleted file mode 100644 index 012064a..0000000 --- a/src/components/proxy/proxy-render.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import { - alpha, - Box, - ListItemText, - ListItemButton, - Typography, - styled, -} from "@mui/material"; -import { - ExpandLessRounded, - ExpandMoreRounded, - InboxRounded, -} from "@mui/icons-material"; -import { HeadState } from "./use-head-state"; -import { ProxyHead } from "./proxy-head"; -import { ProxyItem } from "./proxy-item"; -import { ProxyItemMini } from "./proxy-item-mini"; -import type { IRenderItem } from "./use-render-list"; - -interface RenderProps { - item: IRenderItem; - indent: boolean; - onLocation: (group: IProxyGroupItem) => void; - onCheckAll: (groupName: string) => void; - onHeadState: (groupName: string, patch: Partial) => void; - onChangeProxy: (group: IProxyGroupItem, proxy: IProxyItem) => void; -} - -export const ProxyRender = (props: RenderProps) => { - const { indent, item, onLocation, onCheckAll, onHeadState, onChangeProxy } = - props; - const { type, group, headState, proxy, proxyCol } = item; - - if (type === 0) { - return ( - onHeadState(group.name, { open: !headState?.open })} - > - - {group.type} - {group.now} - - } - secondaryTypographyProps={{ - sx: { display: "flex", alignItems: "center" }, - }} - /> - {headState?.open ? : } - - ); - } - - if (type === 1) { - return ( - onLocation(group)} - onCheckDelay={() => onCheckAll(group.name)} - onHeadState={(p) => onHeadState(group.name, p)} - /> - ); - } - - if (type === 2) { - return ( - onChangeProxy(group, proxy!)} - /> - ); - } - - if (type === 3) { - return ( - - - No Proxies - - ); - } - - if (type === 4) { - return ( - - {proxyCol?.map((proxy) => ( - onChangeProxy(group, proxy!)} - /> - ))} - - ); - } - - return null; -}; - -const StyledSubtitle = styled("span")` - font-size: 0.8rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -`; - -const ListItemTextChild = styled("span")` - display: block; -`; - -const StyledTypeBox = styled(ListItemTextChild)(({ theme }) => ({ - display: "inline-block", - border: "1px solid #ccc", - borderColor: alpha(theme.palette.primary.main, 0.5), - color: alpha(theme.palette.primary.main, 0.8), - borderRadius: 4, - fontSize: 10, - padding: "0 2px", - lineHeight: 1.25, - marginRight: "4px", -})); diff --git a/src/components/proxy/use-filter-sort.ts b/src/components/proxy/use-filter-sort.ts deleted file mode 100644 index 3d7b7fd..0000000 --- a/src/components/proxy/use-filter-sort.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import delayManager from "@/services/delay"; - -// default | delay | alphabet -export type ProxySortType = 0 | 1 | 2; - -export default function useFilterSort( - proxies: IProxyItem[], - groupName: string, - filterText: string, - sortType: ProxySortType -) { - const [refresh, setRefresh] = useState({}); - - useEffect(() => { - let last = 0; - - delayManager.setGroupListener(groupName, () => { - // 简单节流 - const now = Date.now(); - if (now - last > 666) { - last = now; - setRefresh({}); - } - }); - - return () => { - delayManager.removeGroupListener(groupName); - }; - }, [groupName]); - - return useMemo(() => { - const fp = filterProxies(proxies, groupName, filterText); - const sp = sortProxies(fp, groupName, sortType); - return sp; - }, [proxies, groupName, filterText, sortType, refresh]); -} - -export function filterSort( - proxies: IProxyItem[], - groupName: string, - filterText: string, - sortType: ProxySortType -) { - const fp = filterProxies(proxies, groupName, filterText); - const sp = sortProxies(fp, groupName, sortType); - return sp; -} - -/** - * 可以通过延迟数/节点类型 过滤 - */ -const regex1 = /delay([=<>])(\d+|timeout|error)/i; -const regex2 = /type=(.*)/i; - -/** - * filter the proxy - * according to the regular conditions - */ -function filterProxies( - proxies: IProxyItem[], - groupName: string, - filterText: string -) { - if (!filterText) return proxies; - - const res1 = regex1.exec(filterText); - if (res1) { - const symbol = res1[1]; - const symbol2 = res1[2].toLowerCase(); - const value = - symbol2 === "error" ? 1e5 : symbol2 === "timeout" ? 3000 : +symbol2; - - return proxies.filter((p) => { - const delay = delayManager.getDelayFix(p, groupName); - - if (delay < 0) return false; - if (symbol === "=" && symbol2 === "error") return delay >= 1e5; - if (symbol === "=" && symbol2 === "timeout") - return delay < 1e5 && delay >= 3000; - if (symbol === "=") return delay == value; - if (symbol === "<") return delay <= value; - if (symbol === ">") return delay >= value; - return false; - }); - } - - const res2 = regex2.exec(filterText); - if (res2) { - const type = res2[1].toLowerCase(); - return proxies.filter((p) => p.type.toLowerCase().includes(type)); - } - - return proxies.filter((p) => p.name.includes(filterText.trim())); -} - -/** - * sort the proxy - */ -function sortProxies( - proxies: IProxyItem[], - groupName: string, - sortType: ProxySortType -) { - if (!proxies) return []; - if (sortType === 0) return proxies; - - const list = proxies.slice(); - - if (sortType === 1) { - list.sort((a, b) => { - const ad = delayManager.getDelayFix(a, groupName); - const bd = delayManager.getDelayFix(b, groupName); - - if (ad === -1 || ad === -2) return 1; - if (bd === -1 || bd === -2) return -1; - - return ad - bd; - }); - } else { - list.sort((a, b) => a.name.localeCompare(b.name)); - } - - return list; -} diff --git a/src/components/proxy/use-head-state.ts b/src/components/proxy/use-head-state.ts deleted file mode 100644 index d1bce2f..0000000 --- a/src/components/proxy/use-head-state.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { ProxySortType } from "./use-filter-sort"; -import { useProfiles } from "@/hooks/use-profiles"; - -export interface HeadState { - open?: boolean; - showType: boolean; - sortType: ProxySortType; - filterText: string; - textState: "url" | "filter" | null; - testUrl: string; -} - -type HeadStateStorage = Record>; - -const HEAD_STATE_KEY = "proxy-head-state"; -export const DEFAULT_STATE: HeadState = { - open: false, - showType: false, - sortType: 0, - filterText: "", - textState: null, - testUrl: "", -}; - -export function useHeadStateNew() { - const { profiles } = useProfiles(); - const current = profiles?.current || ""; - - const [state, setState] = useState>({}); - - useEffect(() => { - if (!current) { - setState({}); - return; - } - - try { - const data = JSON.parse( - localStorage.getItem(HEAD_STATE_KEY)! - ) as HeadStateStorage; - - const value = data[current] || {}; - - if (value && typeof value === "object") { - setState(value); - } else { - setState({}); - } - } catch {} - }, [current]); - - const setHeadState = useCallback( - (groupName: string, obj: Partial) => { - setState((old) => { - const state = old[groupName] || DEFAULT_STATE; - const ret = { ...old, [groupName]: { ...state, ...obj } }; - - // 保存到存储中 - setTimeout(() => { - try { - const item = localStorage.getItem(HEAD_STATE_KEY); - - let data = (item ? JSON.parse(item) : {}) as HeadStateStorage; - - if (!data || typeof data !== "object") data = {}; - - data[current] = ret; - - localStorage.setItem(HEAD_STATE_KEY, JSON.stringify(data)); - } catch {} - }); - - return ret; - }); - }, - [current] - ); - - return [state, setHeadState] as const; -} diff --git a/src/components/proxy/use-render-list.ts b/src/components/proxy/use-render-list.ts deleted file mode 100644 index 9f8bc0a..0000000 --- a/src/components/proxy/use-render-list.ts +++ /dev/null @@ -1,141 +0,0 @@ -import useSWR from "swr"; -import { useEffect, useMemo } from "react"; -import { getProxies } from "@/services/api"; -import { useVerge } from "@/hooks/use-verge"; -import { filterSort } from "./use-filter-sort"; -import { useWindowWidth } from "./use-window-width"; -import { - useHeadStateNew, - DEFAULT_STATE, - type HeadState, -} from "./use-head-state"; - -export interface IRenderItem { - // 组 | head | item | empty | item col - type: 0 | 1 | 2 | 3 | 4; - key: string; - group: IProxyGroupItem; - proxy?: IProxyItem; - col?: number; - proxyCol?: IProxyItem[]; - headState?: HeadState; -} - -export const useRenderList = (mode: string) => { - const { data: proxiesData, mutate: mutateProxies } = useSWR( - "getProxies", - getProxies, - { refreshInterval: 45000 } - ); - - const { verge } = useVerge(); - const { width } = useWindowWidth(); - - let col = Math.floor(verge?.proxy_layout_column || 6); - - // 自适应 - if (col >= 6 || col <= 0) { - if (width > 1450) col = 5; - else if (width > 1024) col = 4; - else if (width > 900) col = 3; - else if (width >= 600) col = 2; - else col = 1; - } - - const [headStates, setHeadState] = useHeadStateNew(); - - // make sure that fetch the proxies successfully - useEffect(() => { - if (!proxiesData) return; - const { groups, proxies } = proxiesData; - - if ( - (mode === "rule" && !groups.length) || - (mode === "global" && proxies.length < 2) - ) { - setTimeout(() => mutateProxies(), 500); - } - }, [proxiesData, mode]); - - const renderList: IRenderItem[] = useMemo(() => { - if (!proxiesData) return []; - - // global 和 direct 使用展开的样式 - const useRule = mode === "rule" || mode === "script"; - const renderGroups = - (useRule && proxiesData.groups.length - ? proxiesData.groups - : [proxiesData.global!]) || []; - - const retList = renderGroups.flatMap((group) => { - const headState = headStates[group.name] || DEFAULT_STATE; - const ret: IRenderItem[] = [ - { type: 0, key: group.name, group, headState }, - ]; - - if (headState?.open || !useRule) { - const proxies = filterSort( - group.all, - group.name, - headState.filterText, - headState.sortType - ); - - ret.push({ type: 1, key: `head-${group.name}`, group, headState }); - - if (!proxies.length) { - ret.push({ type: 3, key: `empty-${group.name}`, group, headState }); - } - - // 支持多列布局 - if (col > 1) { - return ret.concat( - groupList(proxies, col).map((proxyCol) => ({ - type: 4, - key: `col-${group.name}-${proxyCol[0].name}`, - group, - headState, - col, - proxyCol, - })) - ); - } - - return ret.concat( - proxies.map((proxy) => ({ - type: 2, - key: `${group.name}-${proxy!.name}`, - group, - proxy, - headState, - })) - ); - } - return ret; - }); - - if (!useRule) return retList.slice(1); - return retList; - }, [headStates, proxiesData, mode, col]); - - return { - renderList, - onProxies: mutateProxies, - onHeadState: setHeadState, - }; -}; - -function groupList(list: T[], size: number): T[][] { - return list.reduce((p, n) => { - if (!p.length) return [[n]]; - - const i = p.length - 1; - if (p[i].length < size) { - p[i].push(n); - return p; - } - - p.push([n]); - return p; - }, [] as T[][]); -} diff --git a/src/components/proxy/use-window-width.ts b/src/components/proxy/use-window-width.ts deleted file mode 100644 index d1de3c3..0000000 --- a/src/components/proxy/use-window-width.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useEffect, useState } from "react"; - -export const useWindowWidth = () => { - const [width, setWidth] = useState(() => document.body.clientWidth); - - useEffect(() => { - const handleResize = () => setWidth(document.body.clientWidth); - - window.addEventListener("resize", handleResize); - return () => { - window.removeEventListener("resize", handleResize); - }; - }, []); - - return { width }; -}; diff --git a/src/components/rule/rule-item.tsx b/src/components/rule/rule-item.tsx deleted file mode 100644 index 3bf2291..0000000 --- a/src/components/rule/rule-item.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { styled, Box, Typography } from "@mui/material"; - -const Item = styled(Box)(({ theme }) => ({ - display: "flex", - padding: "4px 16px", - color: theme.palette.text.primary, -})); - -const COLOR = [ - "primary", - "secondary", - "info.main", - "warning.main", - "success.main", -]; - -interface Props { - index: number; - value: IRuleItem; -} - -const parseColor = (text: string) => { - if (text === "REJECT") return "error.main"; - if (text === "DIRECT") return "text.primary"; - - let sum = 0; - for (let i = 0; i < text.length; i++) { - sum += text.charCodeAt(i); - } - return COLOR[sum % COLOR.length]; -}; - -const RuleItem = (props: Props) => { - const { index, value } = props; - - return ( - - - {index} - - - - - {value.payload || "-"} - - - - {value.type} - - - - {value.proxy} - - - - ); -}; - -export default RuleItem; diff --git a/src/components/setting/mods/clash-core-viewer.tsx b/src/components/setting/mods/clash-core-viewer.tsx deleted file mode 100644 index f043684..0000000 --- a/src/components/setting/mods/clash-core-viewer.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { mutate } from "swr"; -import { forwardRef, useImperativeHandle, useState } from "react"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; -import { useTranslation } from "react-i18next"; -import { useVerge } from "@/hooks/use-verge"; -import { useLockFn } from "ahooks"; -import { Lock } from "@mui/icons-material"; -import { - Box, - Button, - IconButton, - List, - ListItemButton, - ListItemText, -} from "@mui/material"; -import { changeClashCore, restartSidecar } from "@/services/cmds"; -import { closeAllConnections } from "@/services/api"; -import { grantPermission } from "@/services/cmds"; -import getSystem from "@/utils/get-system"; - -const VALID_CORE = [ - { name: "Clash", core: "clash" }, - { name: "Clash Meta", core: "clash-meta" }, -]; - -const OS = getSystem(); - -export const ClashCoreViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const { verge, mutateVerge } = useVerge(); - - const [open, setOpen] = useState(false); - - useImperativeHandle(ref, () => ({ - open: () => setOpen(true), - close: () => setOpen(false), - })); - - const { clash_core = "clash" } = verge ?? {}; - - const onCoreChange = useLockFn(async (core: string) => { - if (core === clash_core) return; - - try { - closeAllConnections(); - await changeClashCore(core); - mutateVerge(); - setTimeout(() => { - mutate("getClashConfig"); - mutate("getVersion"); - }, 100); - Notice.success(`Successfully switch to ${core}`, 1000); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - const onGrant = useLockFn(async (core: string) => { - try { - await grantPermission(core); - // 自动重启 - if (core === clash_core) await restartSidecar(); - Notice.success(`Successfully grant permission to ${core}`, 1000); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - const onRestart = useLockFn(async () => { - try { - await restartSidecar(); - Notice.success(`Successfully restart core`, 1000); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - return ( - - {t("Clash Core")} - - - - } - contentSx={{ - pb: 0, - width: 320, - height: 200, - overflowY: "auto", - userSelect: "text", - marginTop: "-8px", - }} - disableOk - cancelBtn={t("Back")} - onClose={() => setOpen(false)} - onCancel={() => setOpen(false)} - > - - {VALID_CORE.map((each) => ( - onCoreChange(each.core)} - > - - - {(OS === "macos" || OS === "linux") && ( - { - e.preventDefault(); - e.stopPropagation(); - onGrant(each.core); - }} - > - - - )} - - ))} - - - ); -}); diff --git a/src/components/setting/mods/clash-field-viewer.tsx b/src/components/setting/mods/clash-field-viewer.tsx deleted file mode 100644 index 8185cba..0000000 --- a/src/components/setting/mods/clash-field-viewer.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import useSWR from "swr"; -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { Checkbox, Divider, Stack, Tooltip, Typography } from "@mui/material"; -import { InfoRounded } from "@mui/icons-material"; -import { getRuntimeExists } from "@/services/cmds"; -import { - HANDLE_FIELDS, - DEFAULT_FIELDS, - OTHERS_FIELDS, -} from "@/utils/clash-fields"; -import { BaseDialog, DialogRef } from "@/components/base"; -import { useProfiles } from "@/hooks/use-profiles"; -import { Notice } from "@/components/base"; - -const otherFields = [...OTHERS_FIELDS]; -const handleFields = [...HANDLE_FIELDS, ...DEFAULT_FIELDS]; - -export const ClashFieldViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const { profiles = {}, patchProfiles } = useProfiles(); - const { data: existsKeys = [], mutate: mutateExists } = useSWR( - "getRuntimeExists", - getRuntimeExists - ); - - const [open, setOpen] = useState(false); - const [selected, setSelected] = useState([]); - - useImperativeHandle(ref, () => ({ - open: () => { - mutateExists(); - setSelected(profiles.valid || []); - setOpen(true); - }, - close: () => setOpen(false), - })); - - const handleChange = (item: string) => { - if (!item) return; - - setSelected((old) => - old.includes(item) ? old.filter((e) => e !== item) : [...old, item] - ); - }; - - const handleSave = async () => { - setOpen(false); - - const oldSet = new Set(profiles.valid || []); - const curSet = new Set(selected); - const joinSet = new Set(selected.concat([...oldSet])); - - if (curSet.size === oldSet.size && curSet.size === joinSet.size) return; - - try { - await patchProfiles({ valid: [...curSet] }); - // Notice.success("Refresh clash config", 1000); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }; - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={handleSave} - > - {otherFields.map((item) => { - const inSelect = selected.includes(item); - const inConfig = existsKeys.includes(item); - - return ( - - handleChange(item)} - /> - {item} - - {!inSelect && inConfig && } - - ); - })} - - - - Clash Verge Control Fields - - - - {handleFields.map((item) => ( - - - {item} - - ))} - - ); -}); - -function WarnIcon() { - return ( - - - - ); -} diff --git a/src/components/setting/mods/clash-port-viewer.tsx b/src/components/setting/mods/clash-port-viewer.tsx deleted file mode 100644 index 2079740..0000000 --- a/src/components/setting/mods/clash-port-viewer.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { useLockFn } from "ahooks"; -import { List, ListItem, ListItemText, TextField } from "@mui/material"; -import { useClashInfo } from "@/hooks/use-clash"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; - -export const ClashPortViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const { clashInfo, patchInfo } = useClashInfo(); - - const [open, setOpen] = useState(false); - const [port, setPort] = useState(clashInfo?.port ?? 7890); - - useImperativeHandle(ref, () => ({ - open: () => { - if (clashInfo?.port) setPort(clashInfo?.port); - setOpen(true); - }, - close: () => setOpen(false), - })); - - const onSave = useLockFn(async () => { - if (port === clashInfo?.port) { - setOpen(false); - return; - } - try { - await patchInfo({ "mixed-port": port }); - setOpen(false); - Notice.success("Change Clash port successfully!", 1000); - } catch (err: any) { - Notice.error(err.message || err.toString(), 4000); - } - }); - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onSave} - > - - - - - setPort(+e.target.value?.replace(/\D+/, "").slice(0, 5)) - } - /> - - - - ); -}); diff --git a/src/components/setting/mods/config-viewer.tsx b/src/components/setting/mods/config-viewer.tsx deleted file mode 100644 index 22c169c..0000000 --- a/src/components/setting/mods/config-viewer.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { - forwardRef, - useEffect, - useImperativeHandle, - useRef, - useState, -} from "react"; -import { useTranslation } from "react-i18next"; -import { useRecoilValue } from "recoil"; -import { Chip } from "@mui/material"; -import { atomThemeMode } from "@/services/states"; -import { getRuntimeYaml } from "@/services/cmds"; -import { BaseDialog, DialogRef } from "@/components/base"; -import { editor } from "monaco-editor/esm/vs/editor/editor.api"; - -import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js"; -import "monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution.js"; -import "monaco-editor/esm/vs/editor/contrib/folding/browser/folding.js"; - -export const ConfigViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - const [open, setOpen] = useState(false); - - const editorRef = useRef(); - const instanceRef = useRef(null); - const themeMode = useRecoilValue(atomThemeMode); - - useEffect(() => { - return () => { - if (instanceRef.current) { - instanceRef.current.dispose(); - instanceRef.current = null; - } - }; - }, []); - - useImperativeHandle(ref, () => ({ - open: () => { - setOpen(true); - - getRuntimeYaml().then((data) => { - const dom = editorRef.current; - - if (!dom) return; - if (instanceRef.current) instanceRef.current.dispose(); - - instanceRef.current = editor.create(editorRef.current, { - value: data ?? "# Error\n", - language: "yaml", - theme: themeMode === "light" ? "vs" : "vs-dark", - minimap: { enabled: false }, - readOnly: true, - }); - }); - }, - close: () => setOpen(false), - })); - - return ( - - {t("Runtime Config")} - - } - contentSx={{ width: 520, pb: 1, userSelect: "text" }} - cancelBtn={t("Back")} - disableOk - onClose={() => setOpen(false)} - onCancel={() => setOpen(false)} - > -
- - ); -}); diff --git a/src/components/setting/mods/controller-viewer.tsx b/src/components/setting/mods/controller-viewer.tsx deleted file mode 100644 index 17205d9..0000000 --- a/src/components/setting/mods/controller-viewer.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { List, ListItem, ListItemText, TextField } from "@mui/material"; -import { useClashInfo } from "@/hooks/use-clash"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; - -export const ControllerViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - const [open, setOpen] = useState(false); - - const { clashInfo, patchInfo } = useClashInfo(); - - const [controller, setController] = useState(clashInfo?.server || ""); - const [secret, setSecret] = useState(clashInfo?.secret || ""); - - useImperativeHandle(ref, () => ({ - open: () => { - setOpen(true); - setController(clashInfo?.server || ""); - setSecret(clashInfo?.secret || ""); - }, - close: () => setOpen(false), - })); - - const onSave = useLockFn(async () => { - try { - await patchInfo({ "external-controller": controller, secret }); - Notice.success("Change Clash Config successfully!", 1000); - setOpen(false); - } catch (err: any) { - Notice.error(err.message || err.toString(), 4000); - } - }); - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onSave} - > - - - - setController(e.target.value)} - /> - - - - - setSecret(e.target.value)} - /> - - - - ); -}); diff --git a/src/components/setting/mods/guard-state.tsx b/src/components/setting/mods/guard-state.tsx deleted file mode 100644 index 5ab8e99..0000000 --- a/src/components/setting/mods/guard-state.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { cloneElement, isValidElement, ReactNode, useRef } from "react"; -import noop from "@/utils/noop"; - -interface Props { - value?: Value; - valueProps?: string; - onChangeProps?: string; - waitTime?: number; - onChange?: (value: Value) => void; - onFormat?: (...args: any[]) => Value; - onGuard?: (value: Value, oldValue: Value) => Promise; - onCatch?: (error: Error) => void; - children: ReactNode; -} - -export function GuardState(props: Props) { - const { - value, - children, - valueProps = "value", - onChangeProps = "onChange", - waitTime = 0, // debounce wait time default 0 - onGuard = noop, - onCatch = noop, - onChange = noop, - onFormat = (v: T) => v, - } = props; - - const lockRef = useRef(false); - const saveRef = useRef(value); - const lastRef = useRef(0); - const timeRef = useRef(); - - if (!isValidElement(children)) { - return children as any; - } - - const childProps = { ...children.props }; - - childProps[valueProps] = value; - childProps[onChangeProps] = async (...args: any[]) => { - // 多次操作无效 - if (lockRef.current) return; - - lockRef.current = true; - - try { - const newValue = (onFormat as any)(...args); - // 先在ui上响应操作 - onChange(newValue); - - const now = Date.now(); - - // save the old value - if (waitTime <= 0 || now - lastRef.current >= waitTime) { - saveRef.current = value; - } - - lastRef.current = now; - - if (waitTime <= 0) { - await onGuard(newValue, value!); - } else { - // debounce guard - clearTimeout(timeRef.current); - - timeRef.current = setTimeout(async () => { - try { - await onGuard(newValue, saveRef.current!); - } catch (err: any) { - // 状态回退 - onChange(saveRef.current!); - onCatch(err); - } - }, waitTime); - } - } catch (err: any) { - // 状态回退 - onChange(saveRef.current!); - onCatch(err); - } - lockRef.current = false; - }; - return cloneElement(children, childProps); -} diff --git a/src/components/setting/mods/hotkey-input.tsx b/src/components/setting/mods/hotkey-input.tsx deleted file mode 100644 index a14658a..0000000 --- a/src/components/setting/mods/hotkey-input.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { useRef, useState } from "react"; -import { alpha, Box, IconButton, styled } from "@mui/material"; -import { DeleteRounded } from "@mui/icons-material"; -import { parseHotkey } from "@/utils/parse-hotkey"; - -const KeyWrapper = styled("div")(({ theme }) => ({ - position: "relative", - width: 165, - minHeight: 36, - - "> input": { - position: "absolute", - top: 0, - left: 0, - width: "100%", - height: "100%", - zIndex: 1, - opacity: 0, - }, - "> input:focus + .list": { - borderColor: alpha(theme.palette.primary.main, 0.75), - }, - ".list": { - display: "flex", - alignItems: "center", - flexWrap: "wrap", - width: "100%", - height: "100%", - minHeight: 36, - boxSizing: "border-box", - padding: "3px 4px", - border: "1px solid", - borderRadius: 4, - borderColor: alpha(theme.palette.text.secondary, 0.15), - "&:last-child": { - marginRight: 0, - }, - }, - ".item": { - color: theme.palette.text.primary, - border: "1px solid", - borderColor: alpha(theme.palette.text.secondary, 0.2), - borderRadius: "2px", - padding: "1px 1px", - margin: "2px 0", - marginRight: 8, - }, -})); - -interface Props { - value: string[]; - onChange: (value: string[]) => void; -} - -export const HotkeyInput = (props: Props) => { - const { value, onChange } = props; - - const changeRef = useRef([]); - const [keys, setKeys] = useState(value); - - return ( - - - { - const ret = changeRef.current.slice(); - if (ret.length) { - onChange(ret); - changeRef.current = []; - } - }} - onKeyDown={(e) => { - const evt = e.nativeEvent; - e.preventDefault(); - e.stopPropagation(); - - const key = parseHotkey(evt.key); - if (key === "UNIDENTIFIED") return; - - changeRef.current = [...new Set([...changeRef.current, key])]; - setKeys(changeRef.current); - }} - /> - -
- {keys.map((key) => ( -
- {key} -
- ))} -
-
- - { - onChange([]); - setKeys([]); - }} - > - - -
- ); -}; diff --git a/src/components/setting/mods/hotkey-viewer.tsx b/src/components/setting/mods/hotkey-viewer.tsx deleted file mode 100644 index a47d30e..0000000 --- a/src/components/setting/mods/hotkey-viewer.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { useLockFn } from "ahooks"; -import { styled, Typography } from "@mui/material"; -import { useVerge } from "@/hooks/use-verge"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; -import { HotkeyInput } from "./hotkey-input"; - -const ItemWrapper = styled("div")` - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 8px; -`; - -const HOTKEY_FUNC = [ - "open_dashboard", - "clash_mode_rule", - "clash_mode_global", - "clash_mode_direct", - "clash_mode_script", - "toggle_system_proxy", - "enable_system_proxy", - "disable_system_proxy", - "toggle_tun_mode", - "enable_tun_mode", - "disable_tun_mode", -]; - -export const HotkeyViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - const [open, setOpen] = useState(false); - - const { verge, patchVerge } = useVerge(); - - const [hotkeyMap, setHotkeyMap] = useState>({}); - - useImperativeHandle(ref, () => ({ - open: () => { - setOpen(true); - - const map = {} as typeof hotkeyMap; - - verge?.hotkeys?.forEach((text) => { - const [func, key] = text.split(",").map((e) => e.trim()); - - if (!func || !key) return; - - map[func] = key - .split("+") - .map((e) => e.trim()) - .map((k) => (k === "PLUS" ? "+" : k)); - }); - - setHotkeyMap(map); - }, - close: () => setOpen(false), - })); - - const onSave = useLockFn(async () => { - const hotkeys = Object.entries(hotkeyMap) - .map(([func, keys]) => { - if (!func || !keys?.length) return ""; - - const key = keys - .map((k) => k.trim()) - .filter(Boolean) - .map((k) => (k === "+" ? "PLUS" : k)) - .join("+"); - - if (!key) return ""; - return `${func},${key}`; - }) - .filter(Boolean); - - try { - await patchVerge({ hotkeys }); - setOpen(false); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onSave} - > - {HOTKEY_FUNC.map((func) => ( - - {t(func)} - setHotkeyMap((m) => ({ ...m, [func]: v }))} - /> - - ))} - - ); -}); diff --git a/src/components/setting/mods/layout-viewer.tsx b/src/components/setting/mods/layout-viewer.tsx deleted file mode 100644 index baeca95..0000000 --- a/src/components/setting/mods/layout-viewer.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { List, Switch } from "@mui/material"; -import { useVerge } from "@/hooks/use-verge"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; -import { SettingItem } from "./setting-comp"; -import { GuardState } from "./guard-state"; - -export const LayoutViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - const { verge, patchVerge, mutateVerge } = useVerge(); - - const [open, setOpen] = useState(false); - - useImperativeHandle(ref, () => ({ - open: () => setOpen(true), - close: () => setOpen(false), - })); - - const onSwitchFormat = (_e: any, value: boolean) => value; - const onError = (err: any) => { - Notice.error(err.message || err.toString()); - }; - const onChangeData = (patch: Partial) => { - mutateVerge({ ...verge, ...patch }, false); - }; - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - > - - - onChangeData({ theme_blur: e })} - onGuard={(e) => patchVerge({ theme_blur: e })} - > - - - - - - onChangeData({ traffic_graph: e })} - onGuard={(e) => patchVerge({ traffic_graph: e })} - > - - - - - - onChangeData({ enable_memory_usage: e })} - onGuard={(e) => patchVerge({ enable_memory_usage: e })} - > - - - - - - ); -}); diff --git a/src/components/setting/mods/misc-viewer.tsx b/src/components/setting/mods/misc-viewer.tsx deleted file mode 100644 index 7d63264..0000000 --- a/src/components/setting/mods/misc-viewer.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { - List, - ListItem, - ListItemText, - MenuItem, - Select, - Switch, - TextField, -} from "@mui/material"; -import { useVerge } from "@/hooks/use-verge"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; - -export const MiscViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - const { verge, patchVerge } = useVerge(); - - const [open, setOpen] = useState(false); - const [values, setValues] = useState({ - appLogLevel: "info", - autoCloseConnection: false, - enableClashFields: true, - enableBuiltinEnhanced: true, - proxyLayoutColumn: 6, - defaultLatencyTest: "", - autoLogClean: 0, - }); - - useImperativeHandle(ref, () => ({ - open: () => { - setOpen(true); - setValues({ - appLogLevel: verge?.app_log_level ?? "info", - autoCloseConnection: verge?.auto_close_connection ?? false, - enableClashFields: verge?.enable_clash_fields ?? true, - enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true, - proxyLayoutColumn: verge?.proxy_layout_column || 6, - defaultLatencyTest: verge?.default_latency_test || "", - autoLogClean: verge?.auto_log_clean || 0, - }); - }, - close: () => setOpen(false), - })); - - const onSave = useLockFn(async () => { - try { - await patchVerge({ - app_log_level: values.appLogLevel, - auto_close_connection: values.autoCloseConnection, - enable_clash_fields: values.enableClashFields, - enable_builtin_enhanced: values.enableBuiltinEnhanced, - proxy_layout_column: values.proxyLayoutColumn, - default_latency_test: values.defaultLatencyTest, - auto_log_clean: values.autoLogClean as any, - }); - setOpen(false); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onSave} - > - - - - - - - - - - setValues((v) => ({ ...v, autoCloseConnection: c })) - } - /> - - - - - - setValues((v) => ({ ...v, enableClashFields: c })) - } - /> - - - - - - setValues((v) => ({ ...v, enableBuiltinEnhanced: c })) - } - /> - - - - - - - - - - - - - - - - setValues((v) => ({ ...v, defaultLatencyTest: e.target.value })) - } - /> - - - - ); -}); diff --git a/src/components/setting/mods/service-viewer.tsx b/src/components/setting/mods/service-viewer.tsx deleted file mode 100644 index 839c8c2..0000000 --- a/src/components/setting/mods/service-viewer.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import useSWR from "swr"; -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { Button, Stack, Typography } from "@mui/material"; -import { - checkService, - installService, - uninstallService, - patchVergeConfig, -} from "@/services/cmds"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; - -interface Props { - enable: boolean; -} - -export const ServiceViewer = forwardRef((props, ref) => { - const { enable } = props; - - const { t } = useTranslation(); - const [open, setOpen] = useState(false); - - const { data: status, mutate: mutateCheck } = useSWR( - "checkService", - checkService, - { - revalidateIfStale: false, - shouldRetryOnError: false, - focusThrottleInterval: 36e5, // 1 hour - } - ); - - useImperativeHandle(ref, () => ({ - open: () => setOpen(true), - close: () => setOpen(false), - })); - - const state = status != null ? status : "pending"; - - const onInstall = useLockFn(async () => { - try { - await installService(); - mutateCheck(); - setOpen(false); - Notice.success("Service installed successfully"); - } catch (err: any) { - mutateCheck(); - Notice.error(err.message || err.toString()); - } - }); - - const onUninstall = useLockFn(async () => { - try { - if (enable) { - await patchVergeConfig({ enable_service_mode: false }); - } - - await uninstallService(); - mutateCheck(); - setOpen(false); - Notice.success("Service uninstalled successfully"); - } catch (err: any) { - mutateCheck(); - Notice.error(err.message || err.toString()); - } - }); - - // fix unhandled error of the service mode - const onDisable = useLockFn(async () => { - try { - await patchVergeConfig({ enable_service_mode: false }); - mutateCheck(); - setOpen(false); - } catch (err: any) { - mutateCheck(); - Notice.error(err.message || err.toString()); - } - }); - - return ( - setOpen(false)} - > - Current State: {state} - - {(state === "unknown" || state === "uninstall") && ( - - Information: Please make sure that the Clash Verge Service is - installed and enabled - - )} - - - {state === "uninstall" && enable && ( - - )} - - {state === "uninstall" && ( - - )} - - {(state === "active" || state === "installed") && ( - - )} - - - ); -}); diff --git a/src/components/setting/mods/setting-comp.tsx b/src/components/setting/mods/setting-comp.tsx deleted file mode 100644 index e0cd181..0000000 --- a/src/components/setting/mods/setting-comp.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React, { ReactNode } from "react"; -import { - Box, - List, - ListItem, - ListItemText, - ListSubheader, -} from "@mui/material"; - -interface ItemProps { - label: ReactNode; - extra?: ReactNode; - children?: ReactNode; - secondary?: ReactNode; -} - -export const SettingItem: React.FC = (props) => { - const { label, extra, children, secondary } = props; - - const primary = !extra ? ( - label - ) : ( - - {label} - {extra} - - ); - - return ( - - - {children} - - ); -}; - -export const SettingList: React.FC<{ - title: string; - children: ReactNode; -}> = (props) => ( - - - {props.title} - - - {props.children} - -); diff --git a/src/components/setting/mods/sysproxy-viewer.tsx b/src/components/setting/mods/sysproxy-viewer.tsx deleted file mode 100644 index 44682dc..0000000 --- a/src/components/setting/mods/sysproxy-viewer.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { - Box, - InputAdornment, - List, - ListItem, - ListItemText, - styled, - Switch, - TextField, - Typography, -} from "@mui/material"; -import { useVerge } from "@/hooks/use-verge"; -import { getSystemProxy } from "@/services/cmds"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; - -export const SysproxyViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const [open, setOpen] = useState(false); - - const { verge, patchVerge } = useVerge(); - - type SysProxy = Awaited>; - const [sysproxy, setSysproxy] = useState(); - - const { - enable_system_proxy: enabled, - enable_proxy_guard, - system_proxy_bypass, - proxy_guard_duration, - } = verge ?? {}; - - const [value, setValue] = useState({ - guard: enable_proxy_guard, - bypass: system_proxy_bypass, - duration: proxy_guard_duration ?? 10, - }); - - useImperativeHandle(ref, () => ({ - open: () => { - setOpen(true); - setValue({ - guard: enable_proxy_guard, - bypass: system_proxy_bypass, - duration: proxy_guard_duration ?? 10, - }); - getSystemProxy().then((p) => setSysproxy(p)); - }, - close: () => setOpen(false), - })); - - const onSave = useLockFn(async () => { - if (value.duration < 1) { - Notice.error("Proxy guard duration at least 1 seconds"); - return; - } - - const patch: Partial = {}; - - if (value.guard !== enable_proxy_guard) { - patch.enable_proxy_guard = value.guard; - } - if (value.duration !== proxy_guard_duration) { - patch.proxy_guard_duration = value.duration; - } - if (value.bypass !== system_proxy_bypass) { - patch.system_proxy_bypass = value.bypass; - } - - try { - await patchVerge(patch); - setOpen(false); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onSave} - > - - - - setValue((v) => ({ ...v, guard: e }))} - /> - - - - - s, - }} - onChange={(e) => { - setValue((v) => ({ - ...v, - duration: +e.target.value.replace(/\D/, ""), - })); - }} - /> - - - - - - setValue((v) => ({ ...v, bypass: e.target.value })) - } - /> - - - - - - {t("Current System Proxy")} - - - - Enable: - - {(!!sysproxy?.enable).toString()} - - - - - Server: - {sysproxy?.server || "-"} - - - - Bypass: - {sysproxy?.bypass || "-"} - - - - ); -}); - -const FlexBox = styled("div")` - display: flex; - margin-top: 4px; - - .label { - flex: none; - width: 80px; - } -`; diff --git a/src/components/setting/mods/theme-mode-switch.tsx b/src/components/setting/mods/theme-mode-switch.tsx deleted file mode 100644 index 29ae9ef..0000000 --- a/src/components/setting/mods/theme-mode-switch.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { Button, ButtonGroup } from "@mui/material"; - -type ThemeValue = IVergeConfig["theme_mode"]; - -interface Props { - value?: ThemeValue; - onChange?: (value: ThemeValue) => void; -} - -export const ThemeModeSwitch = (props: Props) => { - const { value, onChange } = props; - const { t } = useTranslation(); - - const modes = ["light", "dark", "system"] as const; - - return ( - - {modes.map((mode) => ( - - ))} - - ); -}; diff --git a/src/components/setting/mods/theme-viewer.tsx b/src/components/setting/mods/theme-viewer.tsx deleted file mode 100644 index c68ada2..0000000 --- a/src/components/setting/mods/theme-viewer.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { - List, - ListItem, - ListItemText, - styled, - TextField, - useTheme, -} from "@mui/material"; -import { useVerge } from "@/hooks/use-verge"; -import { defaultTheme, defaultDarkTheme } from "@/pages/_theme"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; - -export const ThemeViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const [open, setOpen] = useState(false); - const { verge, patchVerge } = useVerge(); - const { theme_setting } = verge ?? {}; - const [theme, setTheme] = useState(theme_setting || {}); - - useImperativeHandle(ref, () => ({ - open: () => { - setOpen(true); - setTheme({ ...theme_setting } || {}); - }, - close: () => setOpen(false), - })); - - const textProps = { - size: "small", - autoComplete: "off", - sx: { width: 135 }, - } as const; - - const handleChange = (field: keyof typeof theme) => (e: any) => { - setTheme((t) => ({ ...t, [field]: e.target.value })); - }; - - const onSave = useLockFn(async () => { - try { - await patchVerge({ theme_setting: theme }); - setOpen(false); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); - - // default theme - const { palette } = useTheme(); - - const dt = palette.mode === "light" ? defaultTheme : defaultDarkTheme; - - type ThemeKey = keyof typeof theme & keyof typeof defaultTheme; - - const renderItem = (label: string, key: ThemeKey) => { - return ( - - - - e.key === "Enter" && onSave()} - /> - - ); - }; - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onSave} - > - - {renderItem("Primary Color", "primary_color")} - - {renderItem("Secondary Color", "secondary_color")} - - {renderItem("Primary Text", "primary_text")} - - {renderItem("Secondary Text", "secondary_text")} - - {renderItem("Info Color", "info_color")} - - {renderItem("Error Color", "error_color")} - - {renderItem("Warning Color", "warning_color")} - - {renderItem("Success Color", "success_color")} - - - - e.key === "Enter" && onSave()} - /> - - - - - e.key === "Enter" && onSave()} - /> - - - - ); -}); - -const Item = styled(ListItem)(() => ({ - padding: "5px 2px", -})); - -const Round = styled("div")(() => ({ - width: "24px", - height: "24px", - borderRadius: "18px", - display: "inline-block", - marginRight: "8px", -})); diff --git a/src/components/setting/mods/update-viewer.tsx b/src/components/setting/mods/update-viewer.tsx deleted file mode 100644 index 8b4e68a..0000000 --- a/src/components/setting/mods/update-viewer.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import useSWR from "swr"; -import snarkdown from "snarkdown"; -import { forwardRef, useImperativeHandle, useState, useMemo } from "react"; -import { useLockFn } from "ahooks"; -import { Box, styled } from "@mui/material"; -import { useRecoilState } from "recoil"; -import { useTranslation } from "react-i18next"; -import { relaunch } from "@tauri-apps/api/process"; -import { checkUpdate, installUpdate } from "@tauri-apps/api/updater"; -import { BaseDialog, DialogRef, Notice } from "@/components/base"; -import { atomUpdateState } from "@/services/states"; - -const UpdateLog = styled(Box)(() => ({ - "h1,h2,h3,ul,ol,p": { margin: "0.5em 0", color: "inherit" }, -})); - -export const UpdateViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const [open, setOpen] = useState(false); - const [updateState, setUpdateState] = useRecoilState(atomUpdateState); - - const { data: updateInfo } = useSWR("checkUpdate", checkUpdate, { - errorRetryCount: 2, - revalidateIfStale: false, - focusThrottleInterval: 36e5, // 1 hour - }); - - useImperativeHandle(ref, () => ({ - open: () => setOpen(true), - close: () => setOpen(false), - })); - - // markdown parser - const parseContent = useMemo(() => { - if (!updateInfo?.manifest?.body) { - return "New Version is available"; - } - return snarkdown(updateInfo?.manifest?.body); - }, [updateInfo]); - - const onUpdate = useLockFn(async () => { - if (updateState) return; - setUpdateState(true); - - try { - await installUpdate(); - await relaunch(); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } finally { - setUpdateState(false); - } - }); - - return ( - setOpen(false)} - onCancel={() => setOpen(false)} - onOk={onUpdate} - > - - - ); -}); diff --git a/src/components/setting/mods/web-ui-item.tsx b/src/components/setting/mods/web-ui-item.tsx deleted file mode 100644 index 5d3d84d..0000000 --- a/src/components/setting/mods/web-ui-item.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { useState } from "react"; -import { - Divider, - IconButton, - Stack, - TextField, - Typography, -} from "@mui/material"; -import { - CheckRounded, - CloseRounded, - DeleteRounded, - EditRounded, - OpenInNewRounded, -} from "@mui/icons-material"; - -interface Props { - value?: string; - onlyEdit?: boolean; - onChange: (value?: string) => void; - onOpenUrl?: (value?: string) => void; - onDelete?: () => void; - onCancel?: () => void; -} - -export const WebUIItem = (props: Props) => { - const { - value, - onlyEdit = false, - onChange, - onDelete, - onOpenUrl, - onCancel, - } = props; - - const [editing, setEditing] = useState(false); - const [editValue, setEditValue] = useState(value); - - if (editing || onlyEdit) { - return ( - <> - - setEditValue(e.target.value)} - placeholder={`Support %host %port %secret`} - autoComplete="off" - /> - { - onChange(editValue); - setEditing(false); - }} - > - - - { - onCancel?.(); - setEditing(false); - }} - > - - - - - - ); - } - - const html = value - ?.replace("%host", "%host") - .replace("%port", "%port") - .replace("%secret", "%secret"); - - return ( - <> - - ({ - "> span": { - color: palette.primary.main, - }, - })} - dangerouslySetInnerHTML={{ __html: html || "NULL" }} - /> - onOpenUrl?.(value)} - > - - - { - setEditing(true); - setEditValue(value); - }} - > - - - - - - - - - ); -}; diff --git a/src/components/setting/mods/web-ui-viewer.tsx b/src/components/setting/mods/web-ui-viewer.tsx deleted file mode 100644 index 8588d3d..0000000 --- a/src/components/setting/mods/web-ui-viewer.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { forwardRef, useImperativeHandle, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { Button, Box, Typography } from "@mui/material"; -import { useVerge } from "@/hooks/use-verge"; -import { openWebUrl } from "@/services/cmds"; -import { BaseDialog, BaseEmpty, DialogRef, Notice } from "@/components/base"; -import { useClashInfo } from "@/hooks/use-clash"; -import { WebUIItem } from "./web-ui-item"; - -export const WebUIViewer = forwardRef((props, ref) => { - const { t } = useTranslation(); - - const { clashInfo } = useClashInfo(); - const { verge, patchVerge, mutateVerge } = useVerge(); - - const [open, setOpen] = useState(false); - const [editing, setEditing] = useState(false); - - useImperativeHandle(ref, () => ({ - open: () => setOpen(true), - close: () => setOpen(false), - })); - - const webUIList = verge?.web_ui_list || []; - - const handleAdd = useLockFn(async (value: string) => { - const newList = [value, ...webUIList]; - mutateVerge((old) => (old ? { ...old, web_ui_list: newList } : old), false); - await patchVerge({ web_ui_list: newList }); - }); - - const handleChange = useLockFn(async (index: number, value?: string) => { - const newList = [...webUIList]; - newList[index] = value ?? ""; - mutateVerge((old) => (old ? { ...old, web_ui_list: newList } : old), false); - await patchVerge({ web_ui_list: newList }); - }); - - const handleDelete = useLockFn(async (index: number) => { - const newList = [...webUIList]; - newList.splice(index, 1); - mutateVerge((old) => (old ? { ...old, web_ui_list: newList } : old), false); - await patchVerge({ web_ui_list: newList }); - }); - - const handleOpenUrl = useLockFn(async (value?: string) => { - if (!value) return; - try { - let url = value.trim().replaceAll("%host", "127.0.0.1"); - - if (url.includes("%port") || url.includes("%secret")) { - if (!clashInfo) throw new Error("failed to get clash info"); - if (!clashInfo.server?.includes(":")) { - throw new Error(`failed to parse the server "${clashInfo.server}"`); - } - - const port = clashInfo.server - .slice(clashInfo.server.indexOf(":") + 1) - .trim(); - - url = url.replaceAll("%port", port || "9090"); - url = url.replaceAll( - "%secret", - encodeURIComponent(clashInfo.secret || "") - ); - } - - await openWebUrl(url); - } catch (e: any) { - Notice.error(e.message || e.toString()); - } - }); - - return ( - - {t("Web UI")} - - - } - contentSx={{ - width: 450, - height: 300, - pb: 1, - overflowY: "auto", - userSelect: "text", - }} - cancelBtn={t("Back")} - disableOk - onClose={() => setOpen(false)} - onCancel={() => setOpen(false)} - > - {editing && ( - { - setEditing(false); - handleAdd(v || ""); - }} - onCancel={() => setEditing(false)} - /> - )} - - {!editing && webUIList.length === 0 && ( - - Replace host, port, secret with "%host" "%port" "%secret" - - } - /> - )} - - {webUIList.map((item, index) => ( - handleChange(index, v)} - onDelete={() => handleDelete(index)} - onOpenUrl={handleOpenUrl} - /> - ))} - - ); -}); diff --git a/src/components/setting/setting-clash.tsx b/src/components/setting/setting-clash.tsx deleted file mode 100644 index 19f77ca..0000000 --- a/src/components/setting/setting-clash.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import { useRef } from "react"; -import { useTranslation } from "react-i18next"; -import { - TextField, - Switch, - Select, - MenuItem, - Typography, - IconButton, -} from "@mui/material"; -import { ArrowForward, Settings } from "@mui/icons-material"; -import { DialogRef } from "@/components/base"; -import { useClash } from "@/hooks/use-clash"; -import { GuardState } from "./mods/guard-state"; -import { WebUIViewer } from "./mods/web-ui-viewer"; -import { ClashFieldViewer } from "./mods/clash-field-viewer"; -import { ClashPortViewer } from "./mods/clash-port-viewer"; -import { ControllerViewer } from "./mods/controller-viewer"; -import { SettingList, SettingItem } from "./mods/setting-comp"; -import { ClashCoreViewer } from "./mods/clash-core-viewer"; - -interface Props { - onError: (err: Error) => void; -} - -const SettingClash = ({ onError }: Props) => { - const { t } = useTranslation(); - - const { clash, version, mutateClash, patchClash } = useClash(); - - const { - ipv6, - "allow-lan": allowLan, - "log-level": logLevel, - "mixed-port": mixedPort, - } = clash ?? {}; - - const webRef = useRef(null); - const fieldRef = useRef(null); - const portRef = useRef(null); - const ctrlRef = useRef(null); - const coreRef = useRef(null); - - const onSwitchFormat = (_e: any, value: boolean) => value; - const onChangeData = (patch: Partial) => { - mutateClash((old) => ({ ...(old! || {}), ...patch }), false); - }; - - return ( - - - - - - - - - onChangeData({ "allow-lan": e })} - onGuard={(e) => patchClash({ "allow-lan": e })} - > - - - - - - onChangeData({ ipv6: e })} - onGuard={(e) => patchClash({ ipv6: e })} - > - - - - - - e.target.value} - onChange={(e) => onChangeData({ "log-level": e })} - onGuard={(e) => patchClash({ "log-level": e })} - > - - - - - - { - portRef.current?.open(); - (e.target as any).blur(); - }} - /> - - - - ctrlRef.current?.open()} - > - - - - - - webRef.current?.open()} - > - - - - - - fieldRef.current?.open()} - > - - - - - coreRef.current?.open()} - > - - - } - > - {version} - - - ); -}; - -export default SettingClash; diff --git a/src/components/setting/setting-system.tsx b/src/components/setting/setting-system.tsx deleted file mode 100644 index 7fdeb8f..0000000 --- a/src/components/setting/setting-system.tsx +++ /dev/null @@ -1,163 +0,0 @@ -import useSWR from "swr"; -import { useRef } from "react"; -import { useTranslation } from "react-i18next"; -import { IconButton, Switch } from "@mui/material"; -import { ArrowForward, PrivacyTipRounded, Settings } from "@mui/icons-material"; -import { checkService } from "@/services/cmds"; -import { useVerge } from "@/hooks/use-verge"; -import { DialogRef } from "@/components/base"; -import { SettingList, SettingItem } from "./mods/setting-comp"; -import { GuardState } from "./mods/guard-state"; -import { ServiceViewer } from "./mods/service-viewer"; -import { SysproxyViewer } from "./mods/sysproxy-viewer"; -import getSystem from "@/utils/get-system"; - -interface Props { - onError?: (err: Error) => void; -} - -const isWIN = getSystem() === "windows"; - -const SettingSystem = ({ onError }: Props) => { - const { t } = useTranslation(); - - const { verge, mutateVerge, patchVerge } = useVerge(); - - // service mode - const { data: serviceStatus } = useSWR( - isWIN ? "checkService" : null, - checkService, - { - revalidateIfStale: false, - shouldRetryOnError: false, - focusThrottleInterval: 36e5, // 1 hour - } - ); - - const serviceRef = useRef(null); - const sysproxyRef = useRef(null); - - const { - enable_tun_mode, - enable_auto_launch, - enable_service_mode, - enable_silent_start, - enable_system_proxy, - } = verge ?? {}; - - const onSwitchFormat = (_e: any, value: boolean) => value; - const onChangeData = (patch: Partial) => { - mutateVerge({ ...verge, ...patch }, false); - }; - - return ( - - - {isWIN && ( - - )} - - - onChangeData({ enable_tun_mode: e })} - onGuard={(e) => patchVerge({ enable_tun_mode: e })} - > - - - - - {isWIN && ( - serviceRef.current?.open()} - > - - - } - > - onChangeData({ enable_service_mode: e })} - onGuard={(e) => patchVerge({ enable_service_mode: e })} - > - - - - )} - - sysproxyRef.current?.open()} - > - - - } - > - onChangeData({ enable_system_proxy: e })} - onGuard={(e) => patchVerge({ enable_system_proxy: e })} - > - - - - - - onChangeData({ enable_auto_launch: e })} - onGuard={(e) => patchVerge({ enable_auto_launch: e })} - > - - - - - - onChangeData({ enable_silent_start: e })} - onGuard={(e) => patchVerge({ enable_silent_start: e })} - > - - - - - ); -}; - -export default SettingSystem; diff --git a/src/components/setting/setting-verge.tsx b/src/components/setting/setting-verge.tsx deleted file mode 100644 index d54094d..0000000 --- a/src/components/setting/setting-verge.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import { useRef } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { IconButton, MenuItem, Select, Typography } from "@mui/material"; -import { openAppDir, openCoreDir, openLogsDir } from "@/services/cmds"; -import { ArrowForward } from "@mui/icons-material"; -import { checkUpdate } from "@tauri-apps/api/updater"; -import { useVerge } from "@/hooks/use-verge"; -import { version } from "@root/package.json"; -import { DialogRef, Notice } from "@/components/base"; -import { SettingList, SettingItem } from "./mods/setting-comp"; -import { ThemeModeSwitch } from "./mods/theme-mode-switch"; -import { ConfigViewer } from "./mods/config-viewer"; -import { HotkeyViewer } from "./mods/hotkey-viewer"; -import { MiscViewer } from "./mods/misc-viewer"; -import { ThemeViewer } from "./mods/theme-viewer"; -import { GuardState } from "./mods/guard-state"; -import { LayoutViewer } from "./mods/layout-viewer"; -import { UpdateViewer } from "./mods/update-viewer"; -import getSystem from "@/utils/get-system"; - -interface Props { - onError?: (err: Error) => void; -} - -const OS = getSystem(); - -const SettingVerge = ({ onError }: Props) => { - const { t } = useTranslation(); - - const { verge, patchVerge, mutateVerge } = useVerge(); - const { theme_mode, language } = verge ?? {}; - - const configRef = useRef(null); - const hotkeyRef = useRef(null); - const miscRef = useRef(null); - const themeRef = useRef(null); - const layoutRef = useRef(null); - const updateRef = useRef(null); - - const onChangeData = (patch: Partial) => { - mutateVerge({ ...verge, ...patch }, false); - }; - - const onCheckUpdate = useLockFn(async () => { - try { - const info = await checkUpdate(); - if (!info?.shouldUpdate) { - Notice.success("No Updates Available"); - } else { - updateRef.current?.open(); - } - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); - - return ( - - - - - - - - - - e.target.value} - onChange={(e) => onChangeData({ language: e })} - onGuard={(e) => patchVerge({ language: e })} - > - - - - - - onChangeData({ theme_mode: e })} - onGuard={(e) => patchVerge({ theme_mode: e })} - > - - - - - - themeRef.current?.open()} - > - - - - - - layoutRef.current?.open()} - > - - - - - - miscRef.current?.open()} - > - - - - - - hotkeyRef.current?.open()} - > - - - - - - configRef.current?.open()} - > - - - - - - - - - - - - - - - - - - - - - - - {!(OS === "windows" && WIN_PORTABLE) && ( - - - - - - )} - - - v{version} - - - ); -}; - -export default SettingVerge; diff --git a/src/hooks/use-clash.ts b/src/hooks/use-clash.ts deleted file mode 100644 index 9804c5f..0000000 --- a/src/hooks/use-clash.ts +++ /dev/null @@ -1,83 +0,0 @@ -import useSWR, { mutate } from "swr"; -import { useLockFn } from "ahooks"; -import { - getAxios, - getClashConfig, - getVersion, - updateConfigs, -} from "@/services/api"; -import { getClashInfo, patchClashConfig } from "@/services/cmds"; - -export const useClash = () => { - const { data: clash, mutate: mutateClash } = useSWR( - "getClashConfig", - getClashConfig - ); - - const { data: versionData, mutate: mutateVersion } = useSWR( - "getVersion", - getVersion - ); - - const patchClash = useLockFn(async (patch: Partial) => { - await updateConfigs(patch); - await patchClashConfig(patch); - mutateClash(); - }); - - const version = versionData?.premium - ? `${versionData.version} Premium` - : versionData?.meta - ? `${versionData.version} Meta` - : versionData?.version || "-"; - - return { - clash, - version, - mutateClash, - mutateVersion, - patchClash, - }; -}; - -export const useClashInfo = () => { - const { data: clashInfo, mutate: mutateInfo } = useSWR( - "getClashInfo", - getClashInfo - ); - - const patchInfo = async ( - patch: Partial< - Pick - > - ) => { - const hasInfo = - patch["mixed-port"] != null || - patch["external-controller"] != null || - patch.secret != null; - - if (!hasInfo) return; - - if (patch["mixed-port"]) { - const port = patch["mixed-port"]; - if (port < 1000) { - throw new Error("The port should not < 1000"); - } - if (port > 65536) { - throw new Error("The port should not > 65536"); - } - } - - await patchClashConfig(patch); - mutateInfo(); - mutate("getClashConfig"); - // 刷新接口 - getAxios(true); - }; - - return { - clashInfo, - mutateInfo, - patchInfo, - }; -}; diff --git a/src/hooks/use-profiles.ts b/src/hooks/use-profiles.ts deleted file mode 100644 index 5faa3ca..0000000 --- a/src/hooks/use-profiles.ts +++ /dev/null @@ -1,74 +0,0 @@ -import useSWR, { mutate } from "swr"; -import { - getProfiles, - patchProfile, - patchProfilesConfig, -} from "@/services/cmds"; -import { getProxies, updateProxy } from "@/services/api"; - -export const useProfiles = () => { - const { data: profiles, mutate: mutateProfiles } = useSWR( - "getProfiles", - getProfiles - ); - - const patchProfiles = async (value: Partial) => { - await patchProfilesConfig(value); - mutateProfiles(); - }; - - const patchCurrent = async (value: Partial) => { - if (profiles?.current) { - await patchProfile(profiles.current, value); - mutateProfiles(); - } - }; - - // 根据selected的节点选择 - const activateSelected = async () => { - const proxiesData = await getProxies(); - const profileData = await getProfiles(); - - if (!profileData || !proxiesData) return; - - const current = profileData.items?.find( - (e) => e && e.uid === profileData.current - ); - - if (!current) return; - - // init selected array - const { selected = [] } = current; - const selectedMap = Object.fromEntries( - selected.map((each) => [each.name!, each.now!]) - ); - - let hasChange = false; - - const newSelected: typeof selected = []; - const { global, groups } = proxiesData; - - [global, ...groups].forEach(({ type, name, now }) => { - if (!now || type !== "Selector") return; - if (selectedMap[name] != null && selectedMap[name] !== now) { - hasChange = true; - updateProxy(name, selectedMap[name]); - } - newSelected.push({ name, now: selectedMap[name] }); - }); - - if (hasChange) { - patchProfile(profileData.current!, { selected: newSelected }); - mutate("getProxies", getProxies()); - } - }; - - return { - profiles, - current: profiles?.items?.find((p) => p && p.uid === profiles.current), - activateSelected, - patchProfiles, - patchCurrent, - mutateProfiles, - }; -}; diff --git a/src/hooks/use-verge.ts b/src/hooks/use-verge.ts deleted file mode 100644 index 6eeebe8..0000000 --- a/src/hooks/use-verge.ts +++ /dev/null @@ -1,20 +0,0 @@ -import useSWR from "swr"; -import { getVergeConfig, patchVergeConfig } from "@/services/cmds"; - -export const useVerge = () => { - const { data: verge, mutate: mutateVerge } = useSWR( - "getVergeConfig", - getVergeConfig - ); - - const patchVerge = async (value: Partial) => { - await patchVergeConfig(value); - mutateVerge(); - }; - - return { - verge, - mutateVerge, - patchVerge, - }; -}; diff --git a/src/hooks/use-visibility.ts b/src/hooks/use-visibility.ts deleted file mode 100644 index 31d6d3d..0000000 --- a/src/hooks/use-visibility.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { useEffect, useState } from "react"; - -export const useVisibility = () => { - const [visible, setVisible] = useState(true); - - useEffect(() => { - const handleVisibilityChange = () => { - setVisible(document.visibilityState === "visible"); - }; - - const handleFocus = () => setVisible(true); - const handleClick = () => setVisible(true); - - handleVisibilityChange(); - document.addEventListener("focus", handleFocus); - document.addEventListener("pointerdown", handleClick); - document.addEventListener("visibilitychange", handleVisibilityChange); - - return () => { - document.removeEventListener("focus", handleFocus); - document.removeEventListener("pointerdown", handleClick); - document.removeEventListener("visibilitychange", handleVisibilityChange); - }; - }, []); - - return visible; -}; diff --git a/src/hooks/use-websocket.ts b/src/hooks/use-websocket.ts deleted file mode 100644 index 810c7b1..0000000 --- a/src/hooks/use-websocket.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { useRef } from "react"; - -export type WsMsgFn = (event: MessageEvent) => void; - -export interface WsOptions { - errorCount?: number; // default is 5 - retryInterval?: number; // default is 2500 - onError?: () => void; -} - -export const useWebsocket = (onMessage: WsMsgFn, options?: WsOptions) => { - const wsRef = useRef(null); - const timerRef = useRef(null); - - const disconnect = () => { - if (wsRef.current) { - wsRef.current.close(); - wsRef.current = null; - } - if (timerRef.current) { - clearTimeout(timerRef.current); - } - }; - - const connect = (url: string) => { - let errorCount = options?.errorCount ?? 5; - - if (!url) return; - - const connectHelper = () => { - disconnect(); - - const ws = new WebSocket(url); - wsRef.current = ws; - - ws.addEventListener("message", onMessage); - ws.addEventListener("error", () => { - errorCount -= 1; - - if (errorCount >= 0) { - timerRef.current = setTimeout(connectHelper, 2500); - } else { - disconnect(); - options?.onError?.(); - } - }); - }; - - connectHelper(); - }; - - return { connect, disconnect }; -}; diff --git a/src/index.html b/src/index.html deleted file mode 100644 index 90966cb..0000000 --- a/src/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - Clash Verge - - - -
- - - diff --git a/src/locales/en.json b/src/locales/en.json deleted file mode 100644 index 10c92ef..0000000 --- a/src/locales/en.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "Label-Proxies": "Proxies", - "Label-Profiles": "Profiles", - "Label-Connections": "Connections", - "Label-Logs": "Logs", - "Label-Rules": "Rules", - "Label-Settings": "Settings", - - "Connections": "Connections", - "Logs": "Logs", - "Clear": "Clear", - "Proxies": "Proxies", - "Proxy Groups": "Proxy Groups", - "rule": "rule", - "global": "global", - "direct": "direct", - "script": "script", - - "Profiles": "Profiles", - "Profile URL": "Profile URL", - "Import": "Import", - "New": "New", - "Create Profile": "Create Profile", - "Choose File": "Choose File", - "Close All": "Close All", - "Select": "Select", - "Edit Info": "Edit Info", - "Edit File": "Edit File", - "Open File": "Open File", - "Update": "Update", - "Update(Proxy)": "Update(Proxy)", - "Delete": "Delete", - "Enable": "Enable", - "Disable": "Disable", - "Refresh": "Refresh", - "To Top": "To Top", - "To End": "To End", - "Update All Profiles": "Update All Profiles", - "View Runtime Config": "View Runtime Config", - "Reactivate Profiles": "Reactivate Profiles", - - "Location": "Location", - "Delay check": "Delay check", - "Sort by default": "Sort by default", - "Sort by delay": "Sort by delay", - "Sort by name": "Sort by name", - "Delay check URL": "Delay check URL", - "Proxy detail": "Proxy detail", - "Filter": "Filter", - "Filter conditions": "Filter conditions", - "Refresh profiles": "Refresh profiles", - - "Type": "Type", - "Name": "Name", - "Descriptions": "Descriptions", - "Subscription URL": "Subscription URL", - "Update Interval": "Update Interval", - "Use System Proxy": "Use System Proxy", - "Use Clash Proxy": "Use Clash Proxy", - - "Settings": "Settings", - "Clash Setting": "Clash Setting", - "System Setting": "System Setting", - "Verge Setting": "Verge Setting", - "Allow Lan": "Allow Lan", - "IPv6": "IPv6", - "Log Level": "Log Level", - "Mixed Port": "Mixed Port", - "External": "External", - "Clash Core": "Clash Core", - "Tun Mode": "Tun Mode", - "Service Mode": "Service Mode", - "Auto Launch": "Auto Launch", - "Silent Start": "Silent Start", - "System Proxy": "System Proxy", - "System Proxy Setting": "System Proxy Setting", - "Proxy Guard": "Proxy Guard", - "Guard Duration": "Guard Duration", - "Proxy Bypass": "Proxy Bypass", - "Current System Proxy": "Current System Proxy", - "Theme Mode": "Theme Mode", - "Theme Blur": "Theme Blur", - "Theme Setting": "Theme Setting", - "Layout Setting": "Layout Setting", - "Miscellaneous": "Miscellaneous", - "Hotkey Setting": "Hotkey Setting", - "Traffic Graph": "Traffic Graph", - "Memory Usage": "Memory Usage", - "Language": "Language", - "Open App Dir": "Open App Dir", - "Open Core Dir": "Open Core Dir", - "Open Logs Dir": "Open Logs Dir", - "Check for Updates": "Check for Updates", - "Verge Version": "Verge Version", - "theme.light": "Light", - "theme.dark": "Dark", - "theme.system": "System", - "Clash Field": "Clash Field", - "Runtime Config": "Runtime Config", - "ReadOnly": "ReadOnly", - "Restart": "Restart", - - "Back": "Back", - "Save": "Save", - "Cancel": "Cancel", - - "Default": "Default", - "Download Speed": "Download Speed", - "Upload Speed": "Upload Speed", - - "open_dashboard": "Open Dashboard", - "clash_mode_rule": "Rule Mode", - "clash_mode_global": "Global Mode", - "clash_mode_direct": "Direct Mode", - "clash_mode_script": "Script Mode", - "toggle_system_proxy": "Toggle System Proxy", - "enable_system_proxy": "Enable System Proxy", - "disable_system_proxy": "Disable System Proxy", - "toggle_tun_mode": "Toggle Tun Mode", - "enable_tun_mode": "Enable Tun Mode", - "disable_tun_mode": "Disable Tun Mode", - - "App Log Level": "App Log Level", - "Auto Close Connections": "Auto Close Connections", - "Enable Clash Fields Filter": "Enable Clash Fields Filter", - "Enable Builtin Enhanced": "Enable Builtin Enhanced", - "Proxy Layout Column": "Proxy Layout Column", - "Default Latency Test": "Default Latency Test", - - "Auto Log Clean": "Auto Log Clean", - "Never Clean": "Never Clean", - "Retain 7 Days": "Retain 7 Days", - "Retain 30 Days": "Retain 30 Days", - "Retain 90 Days": "Retain 90 Days" -} diff --git a/src/locales/ru.json b/src/locales/ru.json deleted file mode 100644 index f8ea10b..0000000 --- a/src/locales/ru.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "Label-Proxies": "Прокси", - "Label-Profiles": "Профили", - "Label-Connections": "Соединения", - "Label-Logs": "Логи", - "Label-Rules": "Правила", - "Label-Settings": "Настройки", - - "Connections": "Соединения", - "Logs": "Логи", - "Clear": "Очистить", - "Proxies": "Прокси", - "Proxy Groups": "Группы прокси", - "rule": "правила", - "global": "глобальный", - "direct": "прямой", - "script": "скриптовый", - - "Profiles": "Профили", - "Profile URL": "URL профиля", - "Import": "Импорт", - "New": "Новый", - "Create Profile": "Создать профиль", - "Choose File": "Выбрать файл", - "Close All": "Закрыть всё", - "Select": "Выбрать", - "Edit Info": "Изменить информацию", - "Edit File": "Изменить файл", - "Open File": "Открыть файл", - "Update": "Обновить", - "Update(Proxy)": "Обновить (прокси)", - "Delete": "Удалить", - "Enable": "Включить", - "Disable": "Отключить", - "Refresh": "Обновить", - "To Top": "Наверх", - "To End": "Вниз", - "Update All Profiles": "Обновить все профили", - "View Runtime Config": "Просмотреть используемый конфиг", - "Reactivate Profiles": "Реактивировать профили", - - "Location": "Местоположение", - "Delay check": "Проверка задержки", - "Sort by default": "Сортировать по умолчанию", - "Sort by delay": "Сортировать по задержке", - "Sort by name": "Сортировать по названию", - "Delay check URL": "URL проверки задержки", - "Proxy detail": "Подробности о прокси", - "Filter": "Фильтр", - "Filter conditions": "Условия фильтрации", - "Refresh profiles": "Обновить профили", - - "Type": "Тип", - "Name": "Название", - "Descriptions": "Описания", - "Subscription URL": "URL подписки", - "Update Interval": "Интервал обновления", - - "Settings": "Настройки", - "Clash Setting": "Настройки Clash", - "System Setting": "Настройки системы", - "Verge Setting": "Настройки Verge", - "Allow Lan": "Разрешить локальную сеть", - "IPv6": "IPv6", - "Log Level": "Уровень логов", - "Mixed Port": "Смешанный порт", - "Clash Core": "Ядро Clash", - "Tun Mode": "Режим туннеля", - "Service Mode": "Режим сервиса", - "Auto Launch": "Автозапуск", - "Silent Start": "Тихий запуск", - "System Proxy": "Системный прокси", - "System Proxy Setting": "Настройка системного прокси", - "Proxy Guard": "Защита прокси", - "Guard Duration": "Период защиты", - "Proxy Bypass": "Игнорирование прокси", - "Current System Proxy": "Текущий системный прокси", - "Theme Mode": "Режим темы", - "Theme Blur": "Размытие темы", - "Theme Setting": "Настройка темы", - "Hotkey Setting": "Настройка клавиатурных сокращений", - "Traffic Graph": "График трафика", - "Language": "Язык", - "Open App Dir": "Открыть папку приложения", - "Open Core Dir": "Открыть папку ядра", - "Open Logs Dir": "Открыть папку логов", - "Verge Version": "Версия Verge", - "theme.light": "Светлая", - "theme.dark": "Тёмная", - "theme.system": "Системная", - "Clash Field": "Используемые настройки Clash", - "Runtime Config": "Используемый конфиг", - "ReadOnly": "Только для чтения", - "Restart": "Перезапуск", - - "Back": "Назад", - "Save": "Сохранить", - "Cancel": "Отмена", - - "open_dashboard": "Open Dashboard", - "clash_mode_rule": "Режим правил", - "clash_mode_global": "Глобальный режим", - "clash_mode_direct": "Прямой режим", - "clash_mode_script": "Скриптовый режим", - "toggle_system_proxy": "Переключить режим системного прокси", - "enable_system_proxy": "Включить системный прокси", - "disable_system_proxy": "Отключить системный прокси", - "toggle_tun_mode": "Переключить режим туннеля", - "enable_tun_mode": "Включить режим туннеля", - "disable_tun_mode": "Отключить режим туннеля" -} diff --git a/src/locales/zh.json b/src/locales/zh.json deleted file mode 100644 index 27b358c..0000000 --- a/src/locales/zh.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "Label-Proxies": "代 理", - "Label-Profiles": "配 置", - "Label-Connections": "连 接", - "Label-Logs": "日 志", - "Label-Rules": "规 则", - "Label-Settings": "设 置", - - "Connections": "连接", - "Logs": "日志", - "Clear": "清除", - "Proxies": "代理", - "Proxy Groups": "代理组", - "rule": "规则", - "global": "全局", - "direct": "直连", - "script": "脚本", - - "Profiles": "配置", - "Profile URL": "配置文件链接", - "Import": "导入", - "New": "新建", - "Create Profile": "新建配置", - "Choose File": "选择文件", - "Close All": "关闭全部", - "Select": "使用", - "Edit Info": "编辑信息", - "Edit File": "编辑文件", - "Open File": "打开文件", - "Update": "更新", - "Update(Proxy)": "更新(代理)", - "Delete": "删除", - "Enable": "启用", - "Disable": "禁用", - "Refresh": "刷新", - "To Top": "移到最前", - "To End": "移到末尾", - "Update All Profiles": "更新所有配置", - "View Runtime Config": "查看运行时配置", - "Reactivate Profiles": "重新激活配置", - - "Location": "当前节点", - "Delay check": "延迟测试", - "Sort by default": "默认排序", - "Sort by delay": "按延迟排序", - "Sort by name": "按名称排序", - "Delay check URL": "延迟测试链接", - "Proxy detail": "展示节点细节", - "Filter": "过滤节点", - "Filter conditions": "过滤条件", - "Refresh profiles": "刷新配置", - - "Type": "类型", - "Name": "名称", - "Descriptions": "描述", - "Subscription URL": "订阅链接", - "Update Interval": "更新间隔", - "Use System Proxy": "使用系统代理更新", - "Use Clash Proxy": "使用Clash代理更新", - - "Settings": "设置", - "Clash Setting": "Clash 设置", - "System Setting": "系统设置", - "Verge Setting": "Verge 设置", - "Allow Lan": "局域网连接", - "IPv6": "IPv6", - "Log Level": "日志等级", - "Mixed Port": "端口设置", - "External": "外部控制", - "Clash Core": "Clash 内核", - "Tun Mode": "Tun 模式", - "Service Mode": "服务模式", - "Auto Launch": "开机自启", - "Silent Start": "静默启动", - "System Proxy": "系统代理", - "System Proxy Setting": "系统代理设置", - "Proxy Guard": "系统代理守卫", - "Guard Duration": "代理守卫间隔", - "Proxy Bypass": "Proxy Bypass", - "Current System Proxy": "当前系统代理", - "Theme Mode": "主题模式", - "Theme Blur": "背景模糊", - "Theme Setting": "主题设置", - "Layout Setting": "界面设置", - "Miscellaneous": "杂项设置", - "Hotkey Setting": "热键设置", - "Traffic Graph": "流量图显", - "Memory Usage": "内存使用", - "Language": "语言设置", - "Open App Dir": "应用目录", - "Open Core Dir": "内核目录", - "Open Logs Dir": "日志目录", - "Check for Updates": "检查更新", - "Verge Version": "应用版本", - "theme.light": "浅色", - "theme.dark": "深色", - "theme.system": "系统", - "Clash Field": "Clash 字段", - "Runtime Config": "运行配置", - "ReadOnly": "只读", - "Restart": "重启内核", - - "Back": "返回", - "Save": "保存", - "Cancel": "取消", - - "Default": "默认", - "Download Speed": "下载速度", - "Upload Speed": "上传速度", - - "open_dashboard": "打开面板", - "clash_mode_rule": "规则模式", - "clash_mode_global": "全局模式", - "clash_mode_direct": "直连模式", - "clash_mode_script": "脚本模式", - "toggle_system_proxy": "切换系统代理", - "enable_system_proxy": "开启系统代理", - "disable_system_proxy": "关闭系统代理", - "toggle_tun_mode": "切换Tun模式", - "enable_tun_mode": "开启Tun模式", - "disable_tun_mode": "关闭Tun模式", - - "App Log Level": "App日志等级", - "Auto Close Connections": "自动关闭连接", - "Enable Clash Fields Filter": "开启Clash字段过滤", - "Enable Builtin Enhanced": "开启内建增强功能", - "Proxy Layout Column": "代理页布局列数", - "Default Latency Test": "默认测试链接", - - "Auto Log Clean": "自动清理日志", - "Never Clean": "不清理", - "Retain 7 Days": "保留7天", - "Retain 30 Days": "保留30天", - "Retain 90 Days": "保留90天" -} diff --git a/src/main.tsx b/src/main.tsx deleted file mode 100644 index 8588844..0000000 --- a/src/main.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/// -/// -import "./assets/styles/index.scss"; - -import { ResizeObserver } from "@juggle/resize-observer"; -if (!window.ResizeObserver) { - window.ResizeObserver = ResizeObserver; -} - -import React from "react"; -import { createRoot } from "react-dom/client"; -import { RecoilRoot } from "recoil"; -import { BrowserRouter } from "react-router-dom"; -import { BaseErrorBoundary } from "./components/base"; -import Layout from "./pages/_layout"; -import "./services/i18n"; - -const mainElementId = "root"; -const container = document.getElementById(mainElementId); - -if (!container) { - throw new Error( - `No container '${mainElementId}' found to render application` - ); -} - -createRoot(container).render( - - - - - - - - - -); diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx deleted file mode 100644 index 27ef9b0..0000000 --- a/src/pages/_layout.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import dayjs from "dayjs"; -import i18next from "i18next"; -import relativeTime from "dayjs/plugin/relativeTime"; -import { SWRConfig, mutate } from "swr"; -import { useEffect } from "react"; -import { useTranslation } from "react-i18next"; -import { Route, Routes } from "react-router-dom"; -import { alpha, List, Paper, ThemeProvider } from "@mui/material"; -import { listen } from "@tauri-apps/api/event"; -import { appWindow } from "@tauri-apps/api/window"; -import { routers } from "./_routers"; -import { getAxios } from "@/services/api"; -import { useVerge } from "@/hooks/use-verge"; -import { ReactComponent as LogoSvg } from "@/assets/image/logo.svg"; -import { BaseErrorBoundary, Notice } from "@/components/base"; -import { LayoutItem } from "@/components/layout/layout-item"; -import { LayoutControl } from "@/components/layout/layout-control"; -import { LayoutTraffic } from "@/components/layout/layout-traffic"; -import { UpdateButton } from "@/components/layout/update-button"; -import { useCustomTheme } from "@/components/layout/use-custom-theme"; -import getSystem from "@/utils/get-system"; -import "dayjs/locale/ru"; -import "dayjs/locale/zh-cn"; - -dayjs.extend(relativeTime); - -const OS = getSystem(); - -const Layout = () => { - const { t } = useTranslation(); - - const { theme } = useCustomTheme(); - - const { verge } = useVerge(); - const { theme_blur, language } = verge || {}; - - useEffect(() => { - window.addEventListener("keydown", (e) => { - // macOS有cmd+w - if (e.key === "Escape" && OS !== "macos") { - appWindow.close(); - } - }); - - listen("verge://refresh-clash-config", async () => { - // the clash info may be updated - await getAxios(true); - mutate("getProxies"); - mutate("getVersion"); - mutate("getClashConfig"); - mutate("getProviders"); - }); - - // update the verge config - listen("verge://refresh-verge-config", () => mutate("getVergeConfig")); - - // 设置提示监听 - listen("verge://notice-message", ({ payload }) => { - const [status, msg] = payload as [string, string]; - switch (status) { - case "set_config::ok": - Notice.success("Refresh clash config"); - break; - case "set_config::error": - Notice.error(msg); - break; - default: - break; - } - }); - }, []); - - useEffect(() => { - if (language) { - dayjs.locale(language === "zh" ? "zh-cn" : language); - i18next.changeLanguage(language); - } - }, [language]); - - return ( - - - { - if (e.target?.dataset?.windrag) appWindow.startDragging(); - }} - onContextMenu={(e) => { - // only prevent it on Windows - const validList = ["input", "textarea"]; - const target = e.currentTarget; - if ( - OS === "windows" && - !( - validList.includes(target.tagName.toLowerCase()) || - target.isContentEditable - ) - ) { - e.preventDefault(); - } - }} - sx={[ - ({ palette }) => ({ - bgcolor: alpha(palette.background.paper, theme_blur ? 0.8 : 1), - }), - ]} - > -
-
- - - {!(OS === "windows" && WIN_PORTABLE) && ( - - )} -
- - - {routers.map((router) => ( - - {t(router.label)} - - ))} - - -
- -
-
- -
- {OS === "windows" && ( -
- -
- )} - -
- - {routers.map(({ label, link, ele: Ele }) => ( - - - - } - /> - ))} - -
-
-
-
-
- ); -}; - -export default Layout; diff --git a/src/pages/_routers.tsx b/src/pages/_routers.tsx deleted file mode 100644 index f53ed48..0000000 --- a/src/pages/_routers.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import LogsPage from "./logs"; -import ProxiesPage from "./proxies"; -import ProfilesPage from "./profiles"; -import SettingsPage from "./settings"; -import ConnectionsPage from "./connections"; -import RulesPage from "./rules"; - -export const routers = [ - { - label: "Label-Proxies", - link: "/", - ele: ProxiesPage, - }, - { - label: "Label-Profiles", - link: "/profile", - ele: ProfilesPage, - }, - { - label: "Label-Connections", - link: "/connections", - ele: ConnectionsPage, - }, - { - label: "Label-Rules", - link: "/rules", - ele: RulesPage, - }, - { - label: "Label-Logs", - link: "/logs", - ele: LogsPage, - }, - { - label: "Label-Settings", - link: "/settings", - ele: SettingsPage, - }, -]; diff --git a/src/pages/_theme.tsx b/src/pages/_theme.tsx deleted file mode 100644 index 37ce63e..0000000 --- a/src/pages/_theme.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// default theme setting -export const defaultTheme = { - primary_color: "#5b5c9d", - secondary_color: "#9c27b0", - primary_text: "#637381", - secondary_text: "#909399", - info_color: "#0288d1", - error_color: "#d32f2f", - warning_color: "#ed6c02", - success_color: "#2e7d32", - font_family: `"Roboto", "Helvetica", "Arial", sans-serif`, -}; - -// dark mode -export const defaultDarkTheme = { - ...defaultTheme, - primary_text: "#757575", - secondary_text: "#637381", -}; diff --git a/src/pages/connections.tsx b/src/pages/connections.tsx deleted file mode 100644 index 7c53f67..0000000 --- a/src/pages/connections.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import { useEffect, useMemo, useRef, useState } from "react"; -import { useLockFn } from "ahooks"; -import { - Box, - Button, - IconButton, - MenuItem, - Paper, - Select, - TextField, -} from "@mui/material"; -import { useRecoilState } from "recoil"; -import { Virtuoso } from "react-virtuoso"; -import { useTranslation } from "react-i18next"; -import { TableChartRounded, TableRowsRounded } from "@mui/icons-material"; -import { closeAllConnections } from "@/services/api"; -import { atomConnectionSetting } from "@/services/states"; -import { useClashInfo } from "@/hooks/use-clash"; -import { BaseEmpty, BasePage } from "@/components/base"; -import { useWebsocket } from "@/hooks/use-websocket"; -import { ConnectionItem } from "@/components/connection/connection-item"; -import { ConnectionTable } from "@/components/connection/connection-table"; -import { - ConnectionDetail, - ConnectionDetailRef, -} from "@/components/connection/connection-detail"; - -const initConn = { uploadTotal: 0, downloadTotal: 0, connections: [] }; - -type OrderFunc = (list: IConnectionsItem[]) => IConnectionsItem[]; - -const ConnectionsPage = () => { - const { t, i18n } = useTranslation(); - const { clashInfo } = useClashInfo(); - - const [filterText, setFilterText] = useState(""); - const [curOrderOpt, setOrderOpt] = useState("Default"); - const [connData, setConnData] = useState(initConn); - - const [setting, setSetting] = useRecoilState(atomConnectionSetting); - - const isTableLayout = setting.layout === "table"; - - const orderOpts: Record = { - Default: (list) => list, - "Upload Speed": (list) => list.sort((a, b) => b.curUpload! - a.curUpload!), - "Download Speed": (list) => - list.sort((a, b) => b.curDownload! - a.curDownload!), - }; - - const filterConn = useMemo(() => { - const orderFunc = orderOpts[curOrderOpt]; - const connections = connData.connections.filter((conn) => - (conn.metadata.host || conn.metadata.destinationIP)?.includes(filterText) - ); - - if (orderFunc) return orderFunc(connections); - return connections; - }, [connData, filterText, curOrderOpt]); - - const { connect, disconnect } = useWebsocket( - (event) => { - // meta v1.15.0 出现data.connections为null的情况 - const data = JSON.parse(event.data) as IConnections; - // 尽量与前一次connections的展示顺序保持一致 - setConnData((old) => { - const oldConn = old.connections; - const maxLen = data.connections?.length; - - const connections: typeof oldConn = []; - - const rest = (data.connections || []).filter((each) => { - const index = oldConn.findIndex((o) => o.id === each.id); - - if (index >= 0 && index < maxLen) { - const old = oldConn[index]; - each.curUpload = each.upload - old.upload; - each.curDownload = each.download - old.download; - - connections[index] = each; - return false; - } - return true; - }); - - for (let i = 0; i < maxLen; ++i) { - if (!connections[i] && rest.length > 0) { - connections[i] = rest.shift()!; - connections[i].curUpload = 0; - connections[i].curDownload = 0; - } - } - - return { ...data, connections }; - }); - }, - { errorCount: 3, retryInterval: 1000 } - ); - - useEffect(() => { - if (!clashInfo) return; - - const { server = "", secret = "" } = clashInfo; - connect(`ws://${server}/connections?token=${encodeURIComponent(secret)}`); - - return () => { - disconnect(); - }; - }, [clashInfo]); - - const onCloseAll = useLockFn(closeAllConnections); - - const detailRef = useRef(null!); - - return ( - - - setSetting((o) => - o.layout === "list" - ? { ...o, layout: "table" } - : { ...o, layout: "list" } - ) - } - > - {isTableLayout ? ( - - ) : ( - - )} - - - - - } - > - - - {!isTableLayout && ( - - )} - - setFilterText(e.target.value)} - sx={{ input: { py: 0.65, px: 1.25 } }} - /> - - - - {filterConn.length === 0 ? ( - - ) : isTableLayout ? ( - detailRef.current?.open(detail)} - /> - ) : ( - ( - detailRef.current?.open(item)} - /> - )} - /> - )} - - - - - - ); -}; - -export default ConnectionsPage; diff --git a/src/pages/logs.tsx b/src/pages/logs.tsx deleted file mode 100644 index a26b7eb..0000000 --- a/src/pages/logs.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { useMemo, useState } from "react"; -import { useRecoilState } from "recoil"; -import { - Box, - Button, - IconButton, - MenuItem, - Paper, - Select, - TextField, -} from "@mui/material"; -import { Virtuoso } from "react-virtuoso"; -import { useTranslation } from "react-i18next"; -import { - PlayCircleOutlineRounded, - PauseCircleOutlineRounded, -} from "@mui/icons-material"; -import { atomEnableLog, atomLogData } from "@/services/states"; -import { BaseEmpty, BasePage } from "@/components/base"; -import LogItem from "@/components/log/log-item"; - -const LogPage = () => { - const { t } = useTranslation(); - const [logData, setLogData] = useRecoilState(atomLogData); - const [enableLog, setEnableLog] = useRecoilState(atomEnableLog); - - const [logState, setLogState] = useState("all"); - const [filterText, setFilterText] = useState(""); - - const filterLogs = useMemo(() => { - return logData.filter((data) => { - return ( - data.payload.includes(filterText) && - (logState === "all" ? true : data.type.includes(logState)) - ); - }); - }, [logData, logState, filterText]); - - return ( - - setEnableLog((e) => !e)} - > - {enableLog ? ( - - ) : ( - - )} - - - - - } - > - - - - - setFilterText(e.target.value)} - sx={{ input: { py: 0.65, px: 1.25 } }} - /> - - - - {filterLogs.length > 0 ? ( - } - followOutput={"smooth"} - /> - ) : ( - - )} - - - - ); -}; - -export default LogPage; diff --git a/src/pages/profiles.tsx b/src/pages/profiles.tsx deleted file mode 100644 index 95a4fc8..0000000 --- a/src/pages/profiles.tsx +++ /dev/null @@ -1,334 +0,0 @@ -import useSWR, { mutate } from "swr"; -import { useMemo, useRef, useState } from "react"; -import { useLockFn } from "ahooks"; -import { useSetRecoilState } from "recoil"; -import { Box, Button, Grid, IconButton, Stack, TextField } from "@mui/material"; -import { - ClearRounded, - ContentCopyRounded, - LocalFireDepartmentRounded, - RefreshRounded, - TextSnippetOutlined, -} from "@mui/icons-material"; -import { useTranslation } from "react-i18next"; -import { - getProfiles, - importProfile, - enhanceProfiles, - getRuntimeLogs, - deleteProfile, - updateProfile, -} from "@/services/cmds"; -import { atomLoadingCache } from "@/services/states"; -import { closeAllConnections } from "@/services/api"; -import { BasePage, DialogRef, Notice } from "@/components/base"; -import { - ProfileViewer, - ProfileViewerRef, -} from "@/components/profile/profile-viewer"; -import { ProfileItem } from "@/components/profile/profile-item"; -import { ProfileMore } from "@/components/profile/profile-more"; -import { useProfiles } from "@/hooks/use-profiles"; -import { ConfigViewer } from "@/components/setting/mods/config-viewer"; -import { throttle } from "lodash-es"; - -const ProfilePage = () => { - const { t } = useTranslation(); - - const [url, setUrl] = useState(""); - const [disabled, setDisabled] = useState(false); - const [activating, setActivating] = useState(""); - - const { - profiles = {}, - activateSelected, - patchProfiles, - mutateProfiles, - } = useProfiles(); - - const { data: chainLogs = {}, mutate: mutateLogs } = useSWR( - "getRuntimeLogs", - getRuntimeLogs - ); - - const chain = profiles.chain || []; - const viewerRef = useRef(null); - const configRef = useRef(null); - - // distinguish type - const { regularItems, enhanceItems } = useMemo(() => { - const items = profiles.items || []; - const chain = profiles.chain || []; - - const type1 = ["local", "remote"]; - const type2 = ["merge", "script"]; - - const regularItems = items.filter((i) => i && type1.includes(i.type!)); - const restItems = items.filter((i) => i && type2.includes(i.type!)); - const restMap = Object.fromEntries(restItems.map((i) => [i.uid, i])); - const enhanceItems = chain - .map((i) => restMap[i]!) - .filter(Boolean) - .concat(restItems.filter((i) => !chain.includes(i.uid))); - - return { regularItems, enhanceItems }; - }, [profiles]); - - const onImport = async () => { - if (!url) return; - setUrl(""); - setDisabled(true); - - try { - await importProfile(url); - Notice.success("Successfully import profile."); - - getProfiles().then((newProfiles) => { - mutate("getProfiles", newProfiles); - - const remoteItem = newProfiles.items?.find((e) => e.type === "remote"); - if (!newProfiles.current && remoteItem) { - const current = remoteItem.uid; - patchProfiles({ current }); - mutateLogs(); - setTimeout(() => activateSelected(), 2000); - } - }); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } finally { - setDisabled(false); - } - }; - - const onSelect = useLockFn(async (current: string, force: boolean) => { - if (!force && current === profiles.current) return; - // 避免大多数情况下loading态闪烁 - const reset = setTimeout(() => setActivating(current), 100); - try { - await patchProfiles({ current }); - mutateLogs(); - closeAllConnections(); - setTimeout(() => activateSelected(), 2000); - Notice.success("Refresh clash config", 1000); - } catch (err: any) { - Notice.error(err?.message || err.toString(), 4000); - } finally { - clearTimeout(reset); - setActivating(""); - } - }); - - const onEnhance = useLockFn(async () => { - try { - await enhanceProfiles(); - mutateLogs(); - Notice.success("Refresh clash config", 1000); - } catch (err: any) { - Notice.error(err.message || err.toString(), 3000); - } - }); - - const onEnable = useLockFn(async (uid: string) => { - if (chain.includes(uid)) return; - const newChain = [...chain, uid]; - await patchProfiles({ chain: newChain }); - mutateLogs(); - }); - - const onDisable = useLockFn(async (uid: string) => { - if (!chain.includes(uid)) return; - const newChain = chain.filter((i) => i !== uid); - await patchProfiles({ chain: newChain }); - mutateLogs(); - }); - - const onDelete = useLockFn(async (uid: string) => { - try { - await onDisable(uid); - await deleteProfile(uid); - mutateProfiles(); - mutateLogs(); - } catch (err: any) { - Notice.error(err?.message || err.toString()); - } - }); - - const onMoveTop = useLockFn(async (uid: string) => { - if (!chain.includes(uid)) return; - const newChain = [uid].concat(chain.filter((i) => i !== uid)); - await patchProfiles({ chain: newChain }); - mutateLogs(); - }); - - const onMoveEnd = useLockFn(async (uid: string) => { - if (!chain.includes(uid)) return; - const newChain = chain.filter((i) => i !== uid).concat([uid]); - await patchProfiles({ chain: newChain }); - mutateLogs(); - }); - - // 更新所有配置 - const setLoadingCache = useSetRecoilState(atomLoadingCache); - const onUpdateAll = useLockFn(async () => { - const throttleMutate = throttle(mutateProfiles, 2000, { - trailing: true, - }); - const updateOne = async (uid: string) => { - try { - await updateProfile(uid); - throttleMutate(); - } finally { - setLoadingCache((cache) => ({ ...cache, [uid]: false })); - } - }; - - return new Promise((resolve) => { - setLoadingCache((cache) => { - // 获取没有正在更新的配置 - const items = regularItems.filter( - (e) => e.type === "remote" && !cache[e.uid] - ); - const change = Object.fromEntries(items.map((e) => [e.uid, true])); - - Promise.allSettled(items.map((e) => updateOne(e.uid))).then(resolve); - return { ...cache, ...change }; - }); - }); - }); - - const onCopyLink = async () => { - const text = await navigator.clipboard.readText(); - if (text) setUrl(text); - }; - - return ( - - - - - - configRef.current?.open()} - > - - - - - - - - } - > - - setUrl(e.target.value)} - sx={{ input: { py: 0.65, px: 1.25 } }} - placeholder={t("Profile URL")} - InputProps={{ - sx: { pr: 1 }, - endAdornment: !url ? ( - - - - ) : ( - setUrl("")} - > - - - ), - }} - /> - - - - - - - {regularItems.map((item) => ( - - onSelect(item.uid, f)} - onEdit={() => viewerRef.current?.edit(item)} - /> - - ))} - - - - {enhanceItems.length > 0 && ( - - {enhanceItems.map((item) => ( - - onEnable(item.uid)} - onDisable={() => onDisable(item.uid)} - onDelete={() => onDelete(item.uid)} - onMoveTop={() => onMoveTop(item.uid)} - onMoveEnd={() => onMoveEnd(item.uid)} - onEdit={() => viewerRef.current?.edit(item)} - /> - - ))} - - )} - - mutateProfiles()} /> - - - ); -}; - -export default ProfilePage; diff --git a/src/pages/proxies.tsx b/src/pages/proxies.tsx deleted file mode 100644 index 39c777b..0000000 --- a/src/pages/proxies.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import useSWR from "swr"; -import { useEffect, useMemo } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { Box, Button, ButtonGroup, Paper } from "@mui/material"; -import { - closeAllConnections, - getClashConfig, - updateConfigs, -} from "@/services/api"; -import { patchClashConfig } from "@/services/cmds"; -import { useVerge } from "@/hooks/use-verge"; -import { BasePage } from "@/components/base"; -import { ProxyGroups } from "@/components/proxy/proxy-groups"; -import { ProviderButton } from "@/components/proxy/provider-button"; - -const ProxyPage = () => { - const { t } = useTranslation(); - - const { data: clashConfig, mutate: mutateClash } = useSWR( - "getClashConfig", - getClashConfig - ); - - const { verge } = useVerge(); - - const modeList = useMemo(() => { - if (verge?.clash_core === "clash-meta") { - return ["rule", "global", "direct"]; - } - return ["rule", "global", "direct", "script"]; - }, [verge?.clash_core]); - - const curMode = clashConfig?.mode?.toLowerCase(); - - const onChangeMode = useLockFn(async (mode: string) => { - // 断开连接 - if (mode !== curMode && verge?.auto_close_connection) { - closeAllConnections(); - } - await updateConfigs({ mode }); - await patchClashConfig({ mode }); - mutateClash(); - }); - - useEffect(() => { - if (curMode && !modeList.includes(curMode)) { - onChangeMode("rule"); - } - }, [curMode]); - - return ( - - - - - {modeList.map((mode) => ( - - ))} - - - } - > - - - - - ); -}; - -export default ProxyPage; diff --git a/src/pages/rules.tsx b/src/pages/rules.tsx deleted file mode 100644 index 86cbdfa..0000000 --- a/src/pages/rules.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import useSWR from "swr"; -import { useState, useMemo } from "react"; -import { useTranslation } from "react-i18next"; -import { Virtuoso } from "react-virtuoso"; -import { Box, Paper, TextField } from "@mui/material"; -import { getRules } from "@/services/api"; -import { BaseEmpty, BasePage } from "@/components/base"; -import RuleItem from "@/components/rule/rule-item"; - -const RulesPage = () => { - const { t } = useTranslation(); - const { data = [] } = useSWR("getRules", getRules); - - const [filterText, setFilterText] = useState(""); - - const rules = useMemo(() => { - return data.filter((each) => each.payload.includes(filterText)); - }, [data, filterText]); - - return ( - - - - setFilterText(e.target.value)} - sx={{ input: { py: 0.65, px: 1.25 } }} - /> - - - - {rules.length > 0 ? ( - ( - - )} - followOutput={"smooth"} - /> - ) : ( - - )} - - - - ); -}; - -export default RulesPage; diff --git a/src/pages/settings.tsx b/src/pages/settings.tsx deleted file mode 100644 index 039513b..0000000 --- a/src/pages/settings.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { IconButton, Paper } from "@mui/material"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { BasePage, Notice } from "@/components/base"; -import { GitHub } from "@mui/icons-material"; -import { openWebUrl } from "@/services/cmds"; -import SettingVerge from "@/components/setting/setting-verge"; -import SettingClash from "@/components/setting/setting-clash"; -import SettingSystem from "@/components/setting/setting-system"; - -const SettingPage = () => { - const { t } = useTranslation(); - - const onError = (err: any) => { - Notice.error(err?.message || err.toString()); - }; - - const toGithubRepo = useLockFn(() => { - return openWebUrl("https://github.com/zzzgydi/clash-verge"); - }); - - return ( - - - - } - > - - - - - - - - - - - - - ); -}; - -export default SettingPage; diff --git a/src/services/api.ts b/src/services/api.ts deleted file mode 100644 index c9ded07..0000000 --- a/src/services/api.ts +++ /dev/null @@ -1,193 +0,0 @@ -import axios, { AxiosInstance } from "axios"; -import { getClashInfo } from "./cmds"; - -let axiosIns: AxiosInstance = null!; - -/// initialize some information -/// enable force update axiosIns -export const getAxios = async (force: boolean = false) => { - if (axiosIns && !force) return axiosIns; - - let server = ""; - let secret = ""; - - try { - const info = await getClashInfo(); - - if (info?.server) { - server = info.server; - - // compatible width `external-controller` - if (server.startsWith(":")) server = `127.0.0.1${server}`; - else if (/^\d+$/.test(server)) server = `127.0.0.1:${server}`; - } - if (info?.secret) secret = info?.secret; - } catch {} - - axiosIns = axios.create({ - baseURL: `http://${server}`, - headers: secret ? { Authorization: `Bearer ${secret}` } : {}, - timeout: 15000, - }); - axiosIns.interceptors.response.use((r) => r.data); - return axiosIns; -}; - -/// Get Version -export const getVersion = async () => { - const instance = await getAxios(); - return instance.get("/version") as Promise<{ - premium: boolean; - meta?: boolean; - version: string; - }>; -}; - -/// Get current base configs -export const getClashConfig = async () => { - const instance = await getAxios(); - return instance.get("/configs") as Promise; -}; - -/// Update current configs -export const updateConfigs = async (config: Partial) => { - const instance = await getAxios(); - return instance.patch("/configs", config); -}; - -/// Get current rules -export const getRules = async () => { - const instance = await getAxios(); - const response = await instance.get("/rules"); - return response?.rules as IRuleItem[]; -}; - -/// Get Proxy delay -export const getProxyDelay = async (name: string, url?: string) => { - const params = { - timeout: 10000, - url: url || "http://www.gstatic.com/generate_204", - }; - const instance = await getAxios(); - const result = await instance.get( - `/proxies/${encodeURIComponent(name)}/delay`, - { params } - ); - return result as any as { delay: number }; -}; - -/// Update the Proxy Choose -export const updateProxy = async (group: string, proxy: string) => { - const instance = await getAxios(); - return instance.put(`/proxies/${encodeURIComponent(group)}`, { name: proxy }); -}; - -// get proxy -export const getProxiesInner = async () => { - const instance = await getAxios(); - const response = await instance.get("/proxies"); - return (response?.proxies || {}) as Record; -}; - -/// Get the Proxy information -export const getProxies = async () => { - const [proxyRecord, providerRecord] = await Promise.all([ - getProxiesInner(), - getProviders(), - ]); - - // provider name map - const providerMap = Object.fromEntries( - Object.entries(providerRecord).flatMap(([provider, item]) => - item.proxies.map((p) => [p.name, { ...p, provider }]) - ) - ); - - // compatible with proxy-providers - const generateItem = (name: string) => { - if (proxyRecord[name]) return proxyRecord[name]; - if (providerMap[name]) return providerMap[name]; - return { name, type: "unknown", udp: false, history: [] }; - }; - - const { GLOBAL: global, DIRECT: direct, REJECT: reject } = proxyRecord; - - let groups: IProxyGroupItem[] = []; - - if (global?.all) { - groups = global.all - .filter((name) => proxyRecord[name]?.all) - .map((name) => proxyRecord[name]) - .map((each) => ({ - ...each, - all: each.all!.map((item) => generateItem(item)), - })); - } else { - groups = Object.values(proxyRecord) - .filter((each) => each.name !== "GLOBAL" && each.all) - .map((each) => ({ - ...each, - all: each.all!.map((item) => generateItem(item)), - })) - .sort((a, b) => b.name.localeCompare(a.name)); - } - - const proxies = [direct, reject].concat( - Object.values(proxyRecord).filter( - (p) => !p.all?.length && p.name !== "DIRECT" && p.name !== "REJECT" - ) - ); - - const _global: IProxyGroupItem = { - ...global, - all: global?.all?.map((item) => generateItem(item)) || [], - }; - - return { global: _global, direct, groups, records: proxyRecord, proxies }; -}; - -// get proxy providers -export const getProviders = async () => { - const instance = await getAxios(); - const response = await instance.get("/providers/proxies"); - - const providers = (response.providers || {}) as Record; - - return Object.fromEntries( - Object.entries(providers).filter(([key, item]) => { - const type = item.vehicleType.toLowerCase(); - return type === "http" || type === "file"; - }) - ); -}; - -// proxy providers health check -export const providerHealthCheck = async (name: string) => { - const instance = await getAxios(); - return instance.get( - `/providers/proxies/${encodeURIComponent(name)}/healthcheck` - ); -}; - -export const providerUpdate = async (name: string) => { - const instance = await getAxios(); - return instance.put(`/providers/proxies/${encodeURIComponent(name)}`); -}; - -export const getConnections = async () => { - const instance = await getAxios(); - const result = await instance.get("/connections"); - return result as any as IConnections; -}; - -// Close specific connection -export const deleteConnection = async (id: string) => { - const instance = await getAxios(); - await instance.delete(`/connections/${encodeURIComponent(id)}`); -}; - -// Close all connections -export const closeAllConnections = async () => { - const instance = await getAxios(); - await instance.delete(`/connections`); -}; diff --git a/src/services/cmds.ts b/src/services/cmds.ts deleted file mode 100644 index 02ee72a..0000000 --- a/src/services/cmds.ts +++ /dev/null @@ -1,180 +0,0 @@ -import dayjs from "dayjs"; -import { invoke } from "@tauri-apps/api/tauri"; -import { Notice } from "@/components/base"; - -export async function getClashLogs() { - const regex = /time="(.+?)"\s+level=(.+?)\s+msg="(.+?)"/; - const newRegex = /(.+?)\s+(.+?)\s+(.+)/; - const logs = await invoke("get_clash_logs"); - - return logs - .map((log) => { - const result = log.match(regex); - if (result) { - const [_, _time, type, payload] = result; - const time = dayjs(_time).format("MM-DD HH:mm:ss"); - return { time, type, payload }; - } - - const result2 = log.match(newRegex); - if (result2) { - const [_, time, type, payload] = result2; - return { time, type, payload }; - } - return null; - }) - .filter(Boolean) as ILogItem[]; -} - -export async function getProfiles() { - return invoke("get_profiles"); -} - -export async function enhanceProfiles() { - return invoke("enhance_profiles"); -} - -export async function patchProfilesConfig(profiles: IProfilesConfig) { - return invoke("patch_profiles_config", { profiles }); -} - -export async function createProfile( - item: Partial, - fileData?: string | null -) { - return invoke("create_profile", { item, fileData }); -} - -export async function viewProfile(index: string) { - return invoke("view_profile", { index }); -} - -export async function readProfileFile(index: string) { - return invoke("read_profile_file", { index }); -} - -export async function saveProfileFile(index: string, fileData: string) { - return invoke("save_profile_file", { index, fileData }); -} - -export async function importProfile(url: string) { - return invoke("import_profile", { - url, - option: { with_proxy: true }, - }); -} - -export async function updateProfile(index: string, option?: IProfileOption) { - return invoke("update_profile", { index, option }); -} - -export async function deleteProfile(index: string) { - return invoke("delete_profile", { index }); -} - -export async function patchProfile( - index: string, - profile: Partial -) { - return invoke("patch_profile", { index, profile }); -} - -export async function getClashInfo() { - return invoke("get_clash_info"); -} - -export async function getRuntimeConfig() { - return invoke("get_runtime_config"); -} - -export async function getRuntimeYaml() { - return invoke("get_runtime_yaml"); -} - -export async function getRuntimeExists() { - return invoke("get_runtime_exists"); -} - -export async function getRuntimeLogs() { - return invoke>("get_runtime_logs"); -} - -export async function patchClashConfig(payload: Partial) { - return invoke("patch_clash_config", { payload }); -} - -export async function getVergeConfig() { - return invoke("get_verge_config"); -} - -export async function patchVergeConfig(payload: IVergeConfig) { - return invoke("patch_verge_config", { payload }); -} - -export async function getSystemProxy() { - return invoke<{ - enable: boolean; - server: string; - bypass: string; - }>("get_sys_proxy"); -} - -export async function changeClashCore(clashCore: string) { - return invoke("change_clash_core", { clashCore }); -} - -export async function restartSidecar() { - return invoke("restart_sidecar"); -} - -export async function grantPermission(core: string) { - return invoke("grant_permission", { core }); -} - -export async function openAppDir() { - return invoke("open_app_dir").catch((err) => - Notice.error(err?.message || err.toString(), 1500) - ); -} - -export async function openCoreDir() { - return invoke("open_core_dir").catch((err) => - Notice.error(err?.message || err.toString(), 1500) - ); -} - -export async function openLogsDir() { - return invoke("open_logs_dir").catch((err) => - Notice.error(err?.message || err.toString(), 1500) - ); -} - -export async function openWebUrl(url: string) { - return invoke("open_web_url", { url }); -} - -export async function cmdGetProxyDelay(name: string, url?: string) { - name = encodeURIComponent(name); - return invoke<{ delay: number }>("clash_api_get_proxy_delay", { name, url }); -} - -/// service mode - -export async function checkService() { - try { - const result = await invoke("check_service"); - if (result?.code === 0) return "active"; - if (result?.code === 400) return "installed"; - return "unknown"; - } catch (err: any) { - return "uninstall"; - } -} - -export async function installService() { - return invoke("install_service"); -} - -export async function uninstallService() { - return invoke("uninstall_service"); -} diff --git a/src/services/delay.ts b/src/services/delay.ts deleted file mode 100644 index 9b18776..0000000 --- a/src/services/delay.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { cmdGetProxyDelay } from "./cmds"; - -const hashKey = (name: string, group: string) => `${group ?? ""}::${name}`; - -class DelayManager { - private cache = new Map(); - private urlMap = new Map(); - - // 每个item的监听 - private listenerMap = new Map void>(); - - // 每个分组的监听 - private groupListenerMap = new Map void>(); - - setUrl(group: string, url: string) { - this.urlMap.set(group, url); - } - - getUrl(group: string) { - return this.urlMap.get(group); - } - - setListener(name: string, group: string, listener: (time: number) => void) { - const key = hashKey(name, group); - this.listenerMap.set(key, listener); - } - - removeListener(name: string, group: string) { - const key = hashKey(name, group); - this.listenerMap.delete(key); - } - - setGroupListener(group: string, listener: () => void) { - this.groupListenerMap.set(group, listener); - } - - removeGroupListener(group: string) { - this.groupListenerMap.delete(group); - } - - setDelay(name: string, group: string, delay: number) { - const key = hashKey(name, group); - this.cache.set(key, [Date.now(), delay]); - this.listenerMap.get(key)?.(delay); - this.groupListenerMap.get(group)?.(); - } - - getDelay(name: string, group: string) { - if (!name) return -1; - - const result = this.cache.get(hashKey(name, group)); - if (result && Date.now() - result[0] <= 18e5) { - return result[1]; - } - return -1; - } - - /// 暂时修复provider的节点延迟排序的问题 - getDelayFix(proxy: IProxyItem, group: string) { - if (!proxy.provider) { - const delay = this.getDelay(proxy.name, group); - if (delay >= 0 || delay === -2) return delay; - } - - if (proxy.history.length > 0) { - // 0ms以error显示 - return proxy.history[proxy.history.length - 1].delay || 1e6; - } - return -1; - } - - async checkDelay(name: string, group: string) { - let delay = -1; - - try { - const url = this.getUrl(group); - const result = await cmdGetProxyDelay(name, url); - delay = result.delay; - } catch { - delay = 1e6; // error - } - - this.setDelay(name, group, delay); - return delay; - } - - async checkListDelay(nameList: string[], group: string, concurrency = 36) { - const names = nameList.filter(Boolean); - // 设置正在延迟测试中 - names.forEach((name) => this.setDelay(name, group, -2)); - - let total = names.length; - let current = 0; - - return new Promise((resolve) => { - const help = async (): Promise => { - if (current >= concurrency) return; - const task = names.shift(); - if (!task) return; - current += 1; - await this.checkDelay(task, group); - current -= 1; - total -= 1; - if (total <= 0) resolve(null); - else return help(); - }; - for (let i = 0; i < concurrency; ++i) help(); - }); - } - - formatDelay(delay: number) { - if (delay < 0) return "-"; - if (delay > 1e5) return "Error"; - if (delay >= 10000) return "Timeout"; // 10s - return `${delay}`; - } - - formatDelayColor(delay: number) { - if (delay <= 0) return "text.secondary"; - if (delay >= 10000) return "error.main"; - if (delay > 500) return "warning.main"; - if (delay > 100) return "text.secondary"; - return "success.main"; - } -} - -export default new DelayManager(); diff --git a/src/services/i18n.ts b/src/services/i18n.ts deleted file mode 100644 index 8d4c14b..0000000 --- a/src/services/i18n.ts +++ /dev/null @@ -1,19 +0,0 @@ -import i18n from "i18next"; -import { initReactI18next } from "react-i18next"; -import en from "@/locales/en.json"; -import ru from "@/locales/ru.json"; -import zh from "@/locales/zh.json"; - -const resources = { - en: { translation: en }, - ru: { translation: ru }, - zh: { translation: zh }, -}; - -i18n.use(initReactI18next).init({ - resources, - lng: "en", - interpolation: { - escapeValue: false, - }, -}); diff --git a/src/services/states.ts b/src/services/states.ts deleted file mode 100644 index 6ac6edc..0000000 --- a/src/services/states.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { atom } from "recoil"; - -export const atomThemeMode = atom<"light" | "dark">({ - key: "atomThemeMode", - default: "light", -}); - -export const atomLogData = atom({ - key: "atomLogData", - default: [], -}); - -export const atomEnableLog = atom({ - key: "atomEnableLog", - effects: [ - ({ setSelf, onSet }) => { - const key = "enable-log"; - - try { - setSelf(localStorage.getItem(key) !== "false"); - } catch {} - - onSet((newValue, _, isReset) => { - try { - if (isReset) { - localStorage.removeItem(key); - } else { - localStorage.setItem(key, newValue.toString()); - } - } catch {} - }); - }, - ], -}); - -interface IConnectionSetting { - layout: "table" | "list"; -} - -export const atomConnectionSetting = atom({ - key: "atomConnectionSetting", - effects: [ - ({ setSelf, onSet }) => { - const key = "connections-setting"; - - try { - const value = localStorage.getItem(key); - const data = value == null ? { layout: "table" } : JSON.parse(value); - setSelf(data); - } catch { - setSelf({ layout: "table" }); - } - - onSet((newValue) => { - try { - localStorage.setItem(key, JSON.stringify(newValue)); - } catch {} - }); - }, - ], -}); - -// save the state of each profile item loading -export const atomLoadingCache = atom>({ - key: "atomLoadingCache", - default: {}, -}); - -// save update state -export const atomUpdateState = atom({ - key: "atomUpdateState", - default: false, -}); diff --git a/src/services/types.d.ts b/src/services/types.d.ts deleted file mode 100644 index 3fe2175..0000000 --- a/src/services/types.d.ts +++ /dev/null @@ -1,263 +0,0 @@ -type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - -/** - * defines in `vite.config.ts` - */ -declare const WIN_PORTABLE: boolean; -declare const OS_PLATFORM: Platform; - -/** - * Some interface for clash api - */ -interface IConfigData { - port: number; - mode: string; - ipv6: boolean; - "socket-port": number; - "allow-lan": boolean; - "log-level": string; - "mixed-port": number; - "redir-port": number; - "socks-port": number; - "tproxy-port": number; - "external-controller": string; - secret: string; -} - -interface IRuleItem { - type: string; - payload: string; - proxy: string; -} - -interface IProxyItem { - name: string; - type: string; - udp: boolean; - history: { - time: string; - delay: number; - }[]; - all?: string[]; - now?: string; - provider?: string; // 记录是否来自provider -} - -type IProxyGroupItem = Omit & { - all: IProxyItem[]; -}; - -interface IProviderItem { - name: string; - type: string; - proxies: IProxyItem[]; - updatedAt: string; - vehicleType: string; -} - -interface ITrafficItem { - up: number; - down: number; -} - -interface ILogItem { - type: string; - time?: string; - payload: string; -} - -interface IConnectionsItem { - id: string; - metadata: { - network: string; - type: string; - host: string; - sourceIP: string; - sourcePort: string; - destinationPort: string; - destinationIP?: string; - process?: string; - processPath?: string; - }; - upload: number; - download: number; - start: string; - chains: string[]; - rule: string; - rulePayload: string; - curUpload?: number; // upload speed, calculate at runtime - curDownload?: number; // download speed, calculate at runtime -} - -interface IConnections { - downloadTotal: number; - uploadTotal: number; - connections: IConnectionsItem[]; -} - -/** - * Some interface for command - */ - -interface IClashInfo { - // status: string; - port?: number; // clash mixed port - server?: string; // external-controller - secret?: string; -} - -interface IProfileItem { - uid: string; - type?: "local" | "remote" | "merge" | "script"; - name?: string; - desc?: string; - file?: string; - url?: string; - updated?: number; - selected?: { - name?: string; - now?: string; - }[]; - extra?: { - upload: number; - download: number; - total: number; - expire: number; - }; - option?: IProfileOption; -} - -interface IProfileOption { - user_agent?: string; - with_proxy?: boolean; - self_proxy?: boolean; - update_interval?: number; -} - -interface IProfilesConfig { - current?: string; - chain?: string[]; - valid?: string[]; - items?: IProfileItem[]; -} - -interface IVergeConfig { - app_log_level?: "trace" | "debug" | "info" | "warn" | "error" | string; - language?: string; - clash_core?: string; - theme_mode?: "light" | "dark" | "system"; - theme_blur?: boolean; - traffic_graph?: boolean; - enable_memory_usage?: boolean; - enable_tun_mode?: boolean; - enable_auto_launch?: boolean; - enable_service_mode?: boolean; - enable_silent_start?: boolean; - enable_system_proxy?: boolean; - enable_proxy_guard?: boolean; - proxy_guard_duration?: number; - system_proxy_bypass?: string; - web_ui_list?: string[]; - hotkeys?: string[]; - theme_setting?: { - primary_color?: string; - secondary_color?: string; - primary_text?: string; - secondary_text?: string; - info_color?: string; - error_color?: string; - warning_color?: string; - success_color?: string; - font_family?: string; - css_injection?: string; - }; - auto_close_connection?: boolean; - default_latency_test?: string; - enable_clash_fields?: boolean; - enable_builtin_enhanced?: boolean; - auto_log_clean?: 0 | 1 | 2 | 3; - proxy_layout_column?: number; -} - -type IClashConfigValue = any; - -interface IProfileMerge { - // clash config fields (default supports) - rules?: IClashConfigValue; - proxies?: IClashConfigValue; - "proxy-groups"?: IClashConfigValue; - "proxy-providers"?: IClashConfigValue; - "rule-providers"?: IClashConfigValue; - // clash config fields (use flag) - tun?: IClashConfigValue; - dns?: IClashConfigValue; - hosts?: IClashConfigValue; - script?: IClashConfigValue; - profile?: IClashConfigValue; - payload?: IClashConfigValue; - "interface-name"?: IClashConfigValue; - "routing-mark"?: IClashConfigValue; - // functional fields - use?: string[]; - "prepend-rules"?: any[]; - "append-rules"?: any[]; - "prepend-proxies"?: any[]; - "append-proxies"?: any[]; - "prepend-proxy-groups"?: any[]; - "append-proxy-groups"?: any[]; - // fix - ebpf?: any; - experimental?: any; - iptables?: any; - sniffer?: any; - authentication?: any; - "bind-address"?: any; - "external-ui"?: any; - "auto-redir"?: any; - "socks-port"?: any; - "redir-port"?: any; - "tproxy-port"?: any; - "geodata-mode"?: any; - "tcp-concurrent"?: any; -} - -// partial of the clash config -type IProfileData = Partial<{ - rules: any[]; - proxies: any[]; - "proxy-groups": any[]; - "proxy-providers": any[]; - "rule-providers": any[]; - - [k: string]: any; -}>; - -interface IChainItem { - item: IProfileItem; - merge?: IProfileMerge; - script?: string; -} - -interface IEnhancedPayload { - chain: IChainItem[]; - valid: string[]; - current: IProfileData; - callback: string; -} - -interface IEnhancedResult { - data: IProfileData; - status: string; - error?: string; -} diff --git a/src/utils/clash-fields.ts b/src/utils/clash-fields.ts deleted file mode 100644 index 86e1b60..0000000 --- a/src/utils/clash-fields.ts +++ /dev/null @@ -1,52 +0,0 @@ -export const HANDLE_FIELDS = [ - "mode", - "port", - "socks-port", - "mixed-port", - "allow-lan", - "log-level", - "ipv6", - "secret", - "external-controller", -]; - -export const DEFAULT_FIELDS = [ - "proxies", - "proxy-groups", - "proxy-providers", - "rules", - "rule-providers", -] as const; - -export const OTHERS_FIELDS = [ - "dns", - "tun", - "ebpf", - "hosts", - "script", - "profile", - "payload", - "tunnels", - "auto-redir", - "experimental", - "interface-name", - "routing-mark", - "redir-port", - "tproxy-port", - "iptables", - "external-ui", - "bind-address", - "authentication", - "tls", // meta - "sniffer", // meta - "geox-url", // meta - "listeners", // meta - "sub-rules", // meta - "geodata-mode", // meta - "unified-delay", // meta - "tcp-concurrent", // meta - "enable-process", // meta - "find-process-mode", // meta - "external-controller-tls", // meta - "global-client-fingerprint", // meta -] as const; diff --git a/src/utils/get-system.ts b/src/utils/get-system.ts deleted file mode 100644 index 8917703..0000000 --- a/src/utils/get-system.ts +++ /dev/null @@ -1,14 +0,0 @@ -// get the system os -// according to UA -export default function getSystem() { - const ua = navigator.userAgent; - const platform = OS_PLATFORM; - - if (ua.includes("Mac OS X") || platform === "darwin") return "macos"; - - if (/win64|win32/i.test(ua) || platform === "win32") return "windows"; - - if (/linux/i.test(ua)) return "linux"; - - return "unknown"; -} diff --git a/src/utils/ignore-case.ts b/src/utils/ignore-case.ts deleted file mode 100644 index f6533f6..0000000 --- a/src/utils/ignore-case.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Deep copy and change all keys to lowercase -type TData = Record; - -export default function ignoreCase(data: TData): TData { - if (!data) return {}; - - const newData = {} as TData; - - Object.entries(data).forEach(([key, value]) => { - newData[key.toLowerCase()] = JSON.parse(JSON.stringify(value)); - }); - - return newData; -} diff --git a/src/utils/noop.ts b/src/utils/noop.ts deleted file mode 100644 index ca6a744..0000000 --- a/src/utils/noop.ts +++ /dev/null @@ -1 +0,0 @@ -export default function noop() {} diff --git a/src/utils/parse-hotkey.ts b/src/utils/parse-hotkey.ts deleted file mode 100644 index 864ef4f..0000000 --- a/src/utils/parse-hotkey.ts +++ /dev/null @@ -1,48 +0,0 @@ -const KEY_MAP: Record = { - '"': "'", - ":": ";", - "?": "/", - ">": ".", - "<": ",", - "{": "[", - "}": "]", - "|": "\\", - "!": "1", - "@": "2", - "#": "3", - $: "4", - "%": "5", - "^": "6", - "&": "7", - "*": "8", - "(": "9", - ")": "0", - "~": "`", -}; - -export const parseHotkey = (key: string) => { - let temp = key.toUpperCase(); - - if (temp.startsWith("ARROW")) { - temp = temp.slice(5); - } else if (temp.startsWith("DIGIT")) { - temp = temp.slice(5); - } else if (temp.startsWith("KEY")) { - temp = temp.slice(3); - } else if (temp.endsWith("LEFT")) { - temp = temp.slice(0, -4); - } else if (temp.endsWith("RIGHT")) { - temp = temp.slice(0, -5); - } - - switch (temp) { - case "CONTROL": - return "CTRL"; - case "META": - return "CMD"; - case " ": - return "SPACE"; - default: - return KEY_MAP[temp] || temp; - } -}; diff --git a/src/utils/parse-traffic.ts b/src/utils/parse-traffic.ts deleted file mode 100644 index 514d24f..0000000 --- a/src/utils/parse-traffic.ts +++ /dev/null @@ -1,14 +0,0 @@ -const UNITS = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; - -const parseTraffic = (num?: number) => { - if (typeof num !== "number") return ["NaN", ""]; - if (num < 1000) return [`${Math.round(num)}`, "B"]; - const exp = Math.min(Math.floor(Math.log2(num) / 10), UNITS.length - 1); - const dat = num / Math.pow(1024, exp); - const ret = dat >= 1000 ? dat.toFixed(0) : dat.toPrecision(3); - const unit = UNITS[exp]; - - return [ret, unit]; -}; - -export default parseTraffic; diff --git a/src/utils/truncate-str.ts b/src/utils/truncate-str.ts deleted file mode 100644 index 491fa07..0000000 --- a/src/utils/truncate-str.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const truncateStr = (str?: string, prefixLen = 16, maxLen = 56) => { - if (!str || str.length <= maxLen) return str; - return ( - str.slice(0, prefixLen) + " ... " + str.slice(-(maxLen - prefixLen - 5)) - ); -}; diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index a285c97..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "target": "ESNext", - "useDefineForClassFields": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": false, - "skipLibCheck": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "Node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "paths": { - "@/*": ["src/*"], - "@root/*": ["./*"] - } - }, - "include": ["./src"] -} diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index 0315d76..0000000 --- a/vite.config.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { defineConfig } from "vite"; -import path from "path"; -import svgr from "vite-plugin-svgr"; -import react from "@vitejs/plugin-react"; -import monaco from "vite-plugin-monaco-editor"; - -// https://vitejs.dev/config/ -export default defineConfig({ - root: "src", - server: { port: 3000 }, - plugins: [ - svgr(), - react(), - monaco({ languageWorkers: ["editorWorkerService", "typescript"] }), - ], - build: { - outDir: "../dist", - emptyOutDir: true, - }, - resolve: { - alias: { - "@": path.resolve("./src"), - "@root": path.resolve("."), - }, - }, - define: { - OS_PLATFORM: `"${process.platform}"`, - WIN_PORTABLE: !!process.env.VITE_WIN_PORTABLE, - }, -}); diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 895c8bb..0000000 --- a/yarn.lock +++ /dev/null @@ -1,2348 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@actions/github@^5.0.3": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@actions/github/-/github-5.0.3.tgz#b305765d6173962d113451ea324ff675aa674f35" - integrity sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A== - dependencies: - "@actions/http-client" "^2.0.1" - "@octokit/core" "^3.6.0" - "@octokit/plugin-paginate-rest" "^2.17.0" - "@octokit/plugin-rest-endpoint-methods" "^5.13.0" - -"@actions/http-client@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" - integrity sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw== - dependencies: - tunnel "^0.0.6" - -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== - dependencies: - "@jridgewell/trace-mapping" "^0.3.0" - -"@babel/code-frame@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/compat-data@^7.18.8": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.13.tgz#6aff7b350a1e8c3e40b029e46cbe78e24a913483" - integrity sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw== - -"@babel/core@^7.18.10", "@babel/core@^7.18.5": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.13.tgz#9be8c44512751b05094a4d3ab05fc53a47ce00ac" - integrity sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-module-transforms" "^7.18.9" - "@babel/helpers" "^7.18.9" - "@babel/parser" "^7.18.13" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.18.13" - "@babel/types" "^7.18.13" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@^7.18.13": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.13.tgz#59550cbb9ae79b8def15587bdfbaa388c4abf212" - integrity sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ== - dependencies: - "@babel/types" "^7.18.13" - "@jridgewell/gen-mapping" "^0.3.2" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-compilation-targets@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" - integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== - dependencies: - "@babel/compat-data" "^7.18.8" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0" - integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== - dependencies: - "@babel/template" "^7.18.6" - "@babel/types" "^7.18.9" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" - integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f" - integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== - -"@babel/helper-simple-access@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" - integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" - integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helpers@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" - integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== - dependencies: - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.18.10", "@babel/parser@^7.18.13": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.13.tgz#5b2dd21cae4a2c5145f1fbd8ca103f9313d3b7e4" - integrity sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg== - -"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-react-jsx-development@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" - integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.18.6" - -"@babel/plugin-transform-react-jsx-self@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz#3849401bab7ae8ffa1e3e5687c94a753fc75bda7" - integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-react-jsx-source@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.18.6.tgz#06e9ae8a14d2bc19ce6e3c447d842032a50598fc" - integrity sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-react-jsx@^7.18.10", "@babel/plugin-transform-react-jsx@^7.18.6": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz#ea47b2c4197102c196cbd10db9b3bb20daa820f1" - integrity sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-jsx" "^7.18.6" - "@babel/types" "^7.18.10" - -"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" - integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2" - integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.19.0": - version "7.20.1" - resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" - integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== - dependencies: - regenerator-runtime "^0.13.10" - -"@babel/template@^7.18.10", "@babel/template@^7.18.6": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/traverse@^7.18.13", "@babel/traverse@^7.18.9": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.13.tgz#5ab59ef51a997b3f10c4587d648b9696b6cb1a68" - integrity sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.18.13" - "@babel/types" "^7.18.13" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.18.10", "@babel/types@^7.18.13", "@babel/types@^7.18.4", "@babel/types@^7.18.6", "@babel/types@^7.18.9": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.13.tgz#30aeb9e514f4100f7c1cb6e5ba472b30e48f519a" - integrity sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ== - dependencies: - "@babel/helper-string-parser" "^7.18.10" - "@babel/helper-validator-identifier" "^7.18.6" - to-fast-properties "^2.0.0" - -"@emotion/babel-plugin@^11.10.5": - version "11.10.5" - resolved "https://registry.npmmirror.com/@emotion/babel-plugin/-/babel-plugin-11.10.5.tgz#65fa6e1790ddc9e23cc22658a4c5dea423c55c3c" - integrity sha512-xE7/hyLHJac7D2Ve9dKroBBZqBT7WuPQmWcq7HSGb84sUuP4mlOWoB8dvVfD9yk5DHkU1m6RW7xSoDtnQHNQeA== - dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/plugin-syntax-jsx" "^7.17.12" - "@babel/runtime" "^7.18.3" - "@emotion/hash" "^0.9.0" - "@emotion/memoize" "^0.8.0" - "@emotion/serialize" "^1.1.1" - babel-plugin-macros "^3.1.0" - convert-source-map "^1.5.0" - escape-string-regexp "^4.0.0" - find-root "^1.1.0" - source-map "^0.5.7" - stylis "4.1.3" - -"@emotion/cache@^11.10.3": - version "11.10.3" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.3.tgz#c4f67904fad10c945fea5165c3a5a0583c164b87" - integrity sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ== - dependencies: - "@emotion/memoize" "^0.8.0" - "@emotion/sheet" "^1.2.0" - "@emotion/utils" "^1.2.0" - "@emotion/weak-memoize" "^0.3.0" - stylis "4.0.13" - -"@emotion/cache@^11.10.5": - version "11.10.5" - resolved "https://registry.npmmirror.com/@emotion/cache/-/cache-11.10.5.tgz#c142da9351f94e47527ed458f7bbbbe40bb13c12" - integrity sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA== - dependencies: - "@emotion/memoize" "^0.8.0" - "@emotion/sheet" "^1.2.1" - "@emotion/utils" "^1.2.0" - "@emotion/weak-memoize" "^0.3.0" - stylis "4.1.3" - -"@emotion/hash@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" - integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== - -"@emotion/is-prop-valid@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" - integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== - dependencies: - "@emotion/memoize" "^0.8.0" - -"@emotion/memoize@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" - integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== - -"@emotion/react@^11.10.5": - version "11.10.5" - resolved "https://registry.npmmirror.com/@emotion/react/-/react-11.10.5.tgz#95fff612a5de1efa9c0d535384d3cfa115fe175d" - integrity sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.5" - "@emotion/cache" "^11.10.5" - "@emotion/serialize" "^1.1.1" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" - "@emotion/utils" "^1.2.0" - "@emotion/weak-memoize" "^0.3.0" - hoist-non-react-statics "^3.3.1" - -"@emotion/serialize@^1.1.1": - version "1.1.1" - resolved "https://registry.npmmirror.com/@emotion/serialize/-/serialize-1.1.1.tgz#0595701b1902feded8a96d293b26be3f5c1a5cf0" - integrity sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA== - dependencies: - "@emotion/hash" "^0.9.0" - "@emotion/memoize" "^0.8.0" - "@emotion/unitless" "^0.8.0" - "@emotion/utils" "^1.2.0" - csstype "^3.0.2" - -"@emotion/sheet@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5" - integrity sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w== - -"@emotion/sheet@^1.2.1": - version "1.2.1" - resolved "https://registry.npmmirror.com/@emotion/sheet/-/sheet-1.2.1.tgz#0767e0305230e894897cadb6c8df2c51e61a6c2c" - integrity sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA== - -"@emotion/styled@^11.10.5": - version "11.10.5" - resolved "https://registry.npmmirror.com/@emotion/styled/-/styled-11.10.5.tgz#1fe7bf941b0909802cb826457e362444e7e96a79" - integrity sha512-8EP6dD7dMkdku2foLoruPCNkRevzdcBaY6q0l0OsbyJK+x8D9HWjX27ARiSIKNF634hY9Zdoedh8bJCiva8yZw== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.5" - "@emotion/is-prop-valid" "^1.2.0" - "@emotion/serialize" "^1.1.1" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" - "@emotion/utils" "^1.2.0" - -"@emotion/unitless@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" - integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== - -"@emotion/use-insertion-effect-with-fallbacks@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df" - integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A== - -"@emotion/utils@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" - integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== - -"@emotion/weak-memoize@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" - integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== - -"@esbuild/android-arm@0.15.18": - version "0.15.18" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.18.tgz#266d40b8fdcf87962df8af05b76219bc786b4f80" - integrity sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw== - -"@esbuild/linux-loong64@0.15.18": - version "0.15.18" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239" - integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ== - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== - -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" - integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@juggle/resize-observer@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" - integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== - -"@mui/base@5.0.0-alpha.105": - version "5.0.0-alpha.105" - resolved "https://registry.npmmirror.com/@mui/base/-/base-5.0.0-alpha.105.tgz#ddf92c86db3355e0fe6886a818be073e2ee9a9f9" - integrity sha512-4IPBcJQIgVVXQvN6DQMoCHed52GBtwSqYs0jD0dDcMR3o76AodQtpEeWFz3p7mJoc6f/IHBl9U6jEfL1r/kM4g== - dependencies: - "@babel/runtime" "^7.19.0" - "@emotion/is-prop-valid" "^1.2.0" - "@mui/types" "^7.2.0" - "@mui/utils" "^5.10.9" - "@popperjs/core" "^2.11.6" - clsx "^1.2.1" - prop-types "^15.8.1" - react-is "^18.2.0" - -"@mui/core-downloads-tracker@^5.10.13": - version "5.10.13" - resolved "https://registry.npmmirror.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.13.tgz#34068ede2853392ca4fd82ad16d9c1ca664f69b3" - integrity sha512-zWkWPV/SaNdsIdxAWiuVGZ+Ue3BkfSIlU/BFIrJmuUcwiIa7gQsbI/DOpj1KzLvqZhdEe2wC1aG4nCHfzgc1Hg== - -"@mui/icons-material@^5.10.9": - version "5.10.9" - resolved "https://registry.npmmirror.com/@mui/icons-material/-/icons-material-5.10.9.tgz#f9522c49797caf30146acc576e37ecb4f95bbc38" - integrity sha512-sqClXdEM39WKQJOQ0ZCPTptaZgqwibhj2EFV9N0v7BU1PO8y4OcX/a2wIQHn4fNuDjIZktJIBrmU23h7aqlGgg== - dependencies: - "@babel/runtime" "^7.19.0" - -"@mui/material@^5.10.13": - version "5.10.13" - resolved "https://registry.npmmirror.com/@mui/material/-/material-5.10.13.tgz#49c505ed99bc97e573d0cc15bec074b080aacee1" - integrity sha512-TkkT1rNc0/hhL4/+zv4gYcA6egNWBH/1Tz+azoTnQIUdZ32fgwFI2pFX2KVJNTt30xnLznxDWtTv7ilmJQ52xw== - dependencies: - "@babel/runtime" "^7.19.0" - "@mui/base" "5.0.0-alpha.105" - "@mui/core-downloads-tracker" "^5.10.13" - "@mui/system" "^5.10.13" - "@mui/types" "^7.2.0" - "@mui/utils" "^5.10.9" - "@types/react-transition-group" "^4.4.5" - clsx "^1.2.1" - csstype "^3.1.1" - prop-types "^15.8.1" - react-is "^18.2.0" - react-transition-group "^4.4.5" - -"@mui/private-theming@^5.10.9": - version "5.10.9" - resolved "https://registry.npmmirror.com/@mui/private-theming/-/private-theming-5.10.9.tgz#c427bfa736455703975cdb108dbde6a174ba7971" - integrity sha512-BN7/CnsVPVyBaQpDTij4uV2xGYHHHhOgpdxeYLlIu+TqnsVM7wUeF+37kXvHovxM6xmL5qoaVUD98gDC0IZnHg== - dependencies: - "@babel/runtime" "^7.19.0" - "@mui/utils" "^5.10.9" - prop-types "^15.8.1" - -"@mui/styled-engine@^5.10.8": - version "5.10.8" - resolved "https://registry.npmmirror.com/@mui/styled-engine/-/styled-engine-5.10.8.tgz#2db411e4278f06f70ccb6b5cd56ace67109513f6" - integrity sha512-w+y8WI18EJV6zM/q41ug19cE70JTeO6sWFsQ7tgePQFpy6ToCVPh0YLrtqxUZXSoMStW5FMw0t9fHTFAqPbngw== - dependencies: - "@babel/runtime" "^7.19.0" - "@emotion/cache" "^11.10.3" - csstype "^3.1.1" - prop-types "^15.8.1" - -"@mui/system@^5.10.13": - version "5.10.13" - resolved "https://registry.npmmirror.com/@mui/system/-/system-5.10.13.tgz#b32a4441f9dd0760724cdbccf0a09728e63e3674" - integrity sha512-Xzx26Asu5fVlm0ucm+gnJmeX4Y1isrpVDvqxX4yJaOT7Fzmd8Lfq9ih3QMfZajns5LMtUiOuCQlVFRtUG5IY7A== - dependencies: - "@babel/runtime" "^7.19.0" - "@mui/private-theming" "^5.10.9" - "@mui/styled-engine" "^5.10.8" - "@mui/types" "^7.2.0" - "@mui/utils" "^5.10.9" - clsx "^1.2.1" - csstype "^3.1.1" - prop-types "^15.8.1" - -"@mui/types@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.0.tgz#91380c2d42420f51f404120f7a9270eadd6f5c23" - integrity sha512-lGXtFKe5lp3UxTBGqKI1l7G8sE2xBik8qCfrLHD5olwP/YU0/ReWoWT7Lp1//ri32dK39oPMrJN8TgbkCSbsNA== - -"@mui/utils@^5.10.3": - version "5.10.3" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.10.3.tgz#ce2a96f31de2a5e717f507b5383dbabbddbc4dfc" - integrity sha512-4jXMDPfx6bpMVuheLaOpKTjpzw39ogAZLeaLj5+RJec3E37/hAZMYjURfblLfTWMMoGoqkY03mNsZaEwNobBow== - dependencies: - "@babel/runtime" "^7.18.9" - "@types/prop-types" "^15.7.5" - "@types/react-is" "^16.7.1 || ^17.0.0" - prop-types "^15.8.1" - react-is "^18.2.0" - -"@mui/utils@^5.10.9": - version "5.10.9" - resolved "https://registry.npmmirror.com/@mui/utils/-/utils-5.10.9.tgz#9dc455f9230f43eeb81d96a9a4bdb3855bb9ea39" - integrity sha512-2tdHWrq3+WCy+G6TIIaFx3cg7PorXZ71P375ExuX61od1NOAJP1mK90VxQ8N4aqnj2vmO3AQDkV4oV2Ktvt4bA== - dependencies: - "@babel/runtime" "^7.19.0" - "@types/prop-types" "^15.7.5" - "@types/react-is" "^16.7.1 || ^17.0.0" - prop-types "^15.8.1" - react-is "^18.2.0" - -"@mui/x-data-grid@^5.17.11": - version "5.17.11" - resolved "https://registry.npmmirror.com/@mui/x-data-grid/-/x-data-grid-5.17.11.tgz#3a2a9889fb24030d8f11b03319638392d7df8752" - integrity sha512-9KaAsEHKTho/hXXSboxkewBI5HF9NwmgaHCjX7UCg/av3yP2wcWELui9mAWUjI6qm6+8hvKmKclf20ZZ+aPiNg== - dependencies: - "@babel/runtime" "^7.18.9" - "@mui/utils" "^5.10.3" - clsx "^1.2.1" - prop-types "^15.8.1" - reselect "^4.1.6" - -"@octokit/auth-token@^2.4.4": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" - integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== - dependencies: - "@octokit/types" "^6.0.3" - -"@octokit/core@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" - integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== - dependencies: - "@octokit/auth-token" "^2.4.4" - "@octokit/graphql" "^4.5.8" - "@octokit/request" "^5.6.3" - "@octokit/request-error" "^2.0.5" - "@octokit/types" "^6.0.3" - before-after-hook "^2.2.0" - universal-user-agent "^6.0.0" - -"@octokit/endpoint@^6.0.1": - version "6.0.12" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" - integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA== - dependencies: - "@octokit/types" "^6.0.3" - is-plain-object "^5.0.0" - universal-user-agent "^6.0.0" - -"@octokit/graphql@^4.5.8": - version "4.8.0" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" - integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg== - dependencies: - "@octokit/request" "^5.6.0" - "@octokit/types" "^6.0.3" - universal-user-agent "^6.0.0" - -"@octokit/openapi-types@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" - integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== - -"@octokit/plugin-paginate-rest@^2.17.0": - version "2.17.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7" - integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw== - dependencies: - "@octokit/types" "^6.34.0" - -"@octokit/plugin-rest-endpoint-methods@^5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba" - integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA== - dependencies: - "@octokit/types" "^6.34.0" - deprecation "^2.3.1" - -"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" - integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== - dependencies: - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": - version "5.6.3" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" - integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== - dependencies: - "@octokit/endpoint" "^6.0.1" - "@octokit/request-error" "^2.1.0" - "@octokit/types" "^6.16.1" - is-plain-object "^5.0.0" - node-fetch "^2.6.7" - universal-user-agent "^6.0.0" - -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0": - version "6.34.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218" - integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== - dependencies: - "@octokit/openapi-types" "^11.2.0" - -"@popperjs/core@^2.11.6": - version "2.11.6" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" - integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== - -"@remix-run/router@1.0.3": - version "1.0.3" - resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.0.3.tgz#953b88c20ea00d0eddaffdc1b115c08474aa295d" - integrity sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q== - -"@rollup/pluginutils@^4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" - integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== - dependencies: - estree-walker "^2.0.1" - picomatch "^2.2.2" - -"@svgr/babel-plugin-add-jsx-attribute@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.3.1.tgz#b9a5d84902be75a05ede92e70b338d28ab63fa74" - integrity sha512-jDBKArXYO1u0B1dmd2Nf8Oy6aTF5vLDfLoO9Oon/GLkqZ/NiggYWZA+a2HpUMH4ITwNqS3z43k8LWApB8S583w== - -"@svgr/babel-plugin-remove-jsx-attribute@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.3.1.tgz#4877995452efc997b36777abe1fde9705ef78e8b" - integrity sha512-dQzyJ4prwjcFd929T43Z8vSYiTlTu8eafV40Z2gO7zy/SV5GT+ogxRJRBIKWomPBOiaVXFg3jY4S5hyEN3IBjQ== - -"@svgr/babel-plugin-remove-jsx-empty-expression@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.3.1.tgz#2d67a0e92904c9be149a5b22d3a3797ce4d7b514" - integrity sha512-HBOUc1XwSU67fU26V5Sfb8MQsT0HvUyxru7d0oBJ4rA2s4HW3PhyAPC7fV/mdsSGpAvOdd8Wpvkjsr0fWPUO7A== - -"@svgr/babel-plugin-replace-jsx-attribute-value@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.3.1.tgz#306f5247139c53af70d1778f2719647c747998ee" - integrity sha512-C12e6aN4BXAolRrI601gPn5MDFCRHO7C4TM8Kks+rDtl8eEq+NN1sak0eAzJu363x3TmHXdZn7+Efd2nr9I5dA== - -"@svgr/babel-plugin-svg-dynamic-title@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.3.1.tgz#6ce26d34cbc93eb81737ef528528907c292e7aa2" - integrity sha512-6NU55Mmh3M5u2CfCCt6TX29/pPneutrkJnnDCHbKZnjukZmmgUAZLtZ2g6ZoSPdarowaQmAiBRgAHqHmG0vuqA== - -"@svgr/babel-plugin-svg-em-dimensions@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.3.1.tgz#5ade2a724b290873c30529d1d8cd23523856287a" - integrity sha512-HV1NGHYTTe1vCNKlBgq/gKuCSfaRlKcHIADn7P8w8U3Zvujdw1rmusutghJ1pZJV7pDt3Gt8ws+SVrqHnBO/Qw== - -"@svgr/babel-plugin-transform-react-native-svg@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.3.1.tgz#d654f509d692c3a09dfb475757a44bd9f6ad7ddf" - integrity sha512-2wZhSHvTolFNeKDAN/ZmIeSz2O9JSw72XD+o2bNp2QAaWqa8KGpn5Yk5WHso6xqfSAiRzAE+GXlsrBO4UP9LLw== - -"@svgr/babel-plugin-transform-svg-component@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.3.1.tgz#21a285dbffdce9567c437ebf0d081bf9210807e6" - integrity sha512-cZ8Tr6ZAWNUFfDeCKn/pGi976iWSkS8ijmEYKosP+6ktdZ7lW9HVLHojyusPw3w0j8PI4VBeWAXAmi/2G7owxw== - -"@svgr/babel-preset@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.3.1.tgz#8bd1ead79637d395e9362b01dd37cfd59702e152" - integrity sha512-tQtWtzuMMQ3opH7je+MpwfuRA1Hf3cKdSgTtAYwOBDfmhabP7rcTfBi3E7V3MuwJNy/Y02/7/RutvwS1W4Qv9g== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^6.3.1" - "@svgr/babel-plugin-remove-jsx-attribute" "^6.3.1" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^6.3.1" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.3.1" - "@svgr/babel-plugin-svg-dynamic-title" "^6.3.1" - "@svgr/babel-plugin-svg-em-dimensions" "^6.3.1" - "@svgr/babel-plugin-transform-react-native-svg" "^6.3.1" - "@svgr/babel-plugin-transform-svg-component" "^6.3.1" - -"@svgr/core@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.3.1.tgz#752adf49d8d5473b15d76ca741961de093f715bd" - integrity sha512-Sm3/7OdXbQreemf9aO25keerZSbnKMpGEfmH90EyYpj1e8wMD4TuwJIb3THDSgRMWk1kYJfSRulELBy4gVgZUA== - dependencies: - "@svgr/plugin-jsx" "^6.3.1" - camelcase "^6.2.0" - cosmiconfig "^7.0.1" - -"@svgr/hast-util-to-babel-ast@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.3.1.tgz#59614e24d2a4a28010e02089213b3448d905769d" - integrity sha512-NgyCbiTQIwe3wHe/VWOUjyxmpUmsrBjdoIxKpXt3Nqc3TN30BpJG22OxBvVzsAh9jqep0w0/h8Ywvdk3D9niNQ== - dependencies: - "@babel/types" "^7.18.4" - entities "^4.3.0" - -"@svgr/plugin-jsx@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.3.1.tgz#de7b2de824296b836d6b874d498377896e367f50" - integrity sha512-r9+0mYG3hD4nNtUgsTXWGYJomv/bNd7kC16zvsM70I/bGeoCi/3lhTmYqeN6ChWX317OtQCSZZbH4wq9WwoXbw== - dependencies: - "@babel/core" "^7.18.5" - "@svgr/babel-preset" "^6.3.1" - "@svgr/hast-util-to-babel-ast" "^6.3.1" - svg-parser "^2.0.4" - -"@tauri-apps/api@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.3.0.tgz#d0c853ab2cc7506bd826c5f7f260c67c7c15def5" - integrity sha512-AH+3FonkKZNtfRtGrObY38PrzEj4d+1emCbwNGu0V2ENbXjlLHMZQlUh+Bhu/CRmjaIwZMGJ3yFvWaZZgTHoog== - -"@tauri-apps/cli-darwin-arm64@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.3.1.tgz#ef0fe290e0a6e3e53fa2cc4f1a72a0c87921427c" - integrity sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg== - -"@tauri-apps/cli-darwin-x64@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.3.1.tgz#4c84ea0f08a5b636b067943d637a38e091a4aad3" - integrity sha512-fKcAUPVFO3jfDKXCSDGY0MhZFF/wDtx3rgFnogWYu4knk38o9RaqRkvMvqJhLYPuWaEM5h6/z1dRrr9KKCbrVg== - -"@tauri-apps/cli-linux-arm-gnueabihf@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.3.1.tgz#a4f1b237189e4f8f89cc890e1dc2eec76d4345be" - integrity sha512-+4H0dv8ltJHYu/Ma1h9ixUPUWka9EjaYa8nJfiMsdCI4LJLNE6cPveE7RmhZ59v9GW1XB108/k083JUC/OtGvA== - -"@tauri-apps/cli-linux-arm64-gnu@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.3.1.tgz#e2391326b64dfe13c7442bdcc13c4988ce5e6df9" - integrity sha512-Pj3odVO1JAxLjYmoXKxcrpj/tPxcA8UP8N06finhNtBtBaxAjrjjxKjO4968KB0BUH7AASIss9EL4Tr0FGnDuw== - -"@tauri-apps/cli-linux-arm64-musl@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.3.1.tgz#49354349f80f879ffc6950c0c03c0aea1395efa5" - integrity sha512-tA0JdDLPFaj42UDIVcF2t8V0tSha40rppcmAR/MfQpTCxih6399iMjwihz9kZE1n4b5O4KTq9GliYo50a8zYlQ== - -"@tauri-apps/cli-linux-x64-gnu@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.3.1.tgz#9a33ffe9e0d9b1b3825db57cbcfcddeb773682c6" - integrity sha512-FDU+Mnvk6NLkqQimcNojdKpMN4Y3W51+SQl+NqG9AFCWprCcSg62yRb84751ujZuf2MGT8HQOfmd0i77F4Q3tQ== - -"@tauri-apps/cli-linux-x64-musl@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.3.1.tgz#5283731e894c17bc070c499e73145cfe2633ef21" - integrity sha512-MpO3akXFmK8lZYEbyQRDfhdxz1JkTBhonVuz5rRqxwA7gnGWHa1aF1+/2zsy7ahjB2tQ9x8DDFDMdVE20o9HrA== - -"@tauri-apps/cli-win32-ia32-msvc@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.3.1.tgz#f31538abfd94f27ade1f17d01f30da6be1660c6f" - integrity sha512-9Boeo3K5sOrSBAZBuYyGkpV2RfnGQz3ZhGJt4hE6P+HxRd62lS6+qDKAiw1GmkZ0l1drc2INWrNeT50gwOKwIQ== - -"@tauri-apps/cli-win32-x64-msvc@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.3.1.tgz#1eb09d55b99916a3cd84cb91c75ef906db67d35d" - integrity sha512-wMrTo91hUu5CdpbElrOmcZEoJR4aooTG+fbtcc87SMyPGQy1Ux62b+ZdwLvL1sVTxnIm//7v6QLRIWGiUjCPwA== - -"@tauri-apps/cli@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.3.1.tgz#4c5259bf1f9c97084dd016e6b34dca53de380e24" - integrity sha512-o4I0JujdITsVRm3/0spfJX7FcKYrYV1DXJqzlWIn6IY25/RltjU6qbC1TPgVww3RsRX63jyVUTcWpj5wwFl+EQ== - optionalDependencies: - "@tauri-apps/cli-darwin-arm64" "1.3.1" - "@tauri-apps/cli-darwin-x64" "1.3.1" - "@tauri-apps/cli-linux-arm-gnueabihf" "1.3.1" - "@tauri-apps/cli-linux-arm64-gnu" "1.3.1" - "@tauri-apps/cli-linux-arm64-musl" "1.3.1" - "@tauri-apps/cli-linux-x64-gnu" "1.3.1" - "@tauri-apps/cli-linux-x64-musl" "1.3.1" - "@tauri-apps/cli-win32-ia32-msvc" "1.3.1" - "@tauri-apps/cli-win32-x64-msvc" "1.3.1" - -"@types/fs-extra@^9.0.13": - version "9.0.13" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" - integrity sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA== - dependencies: - "@types/node" "*" - -"@types/js-cookie@^2.x.x": - version "2.2.7" - resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" - integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== - -"@types/js-cookie@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.2.tgz#451eaeece64c6bdac8b2dde0caab23b085899e0d" - integrity sha512-6+0ekgfusHftJNYpihfkMu8BWdeHs9EOJuGcSofErjstGPfPGEu9yTu4t460lTzzAMl2cM5zngQJqPMHbbnvYA== - -"@types/lodash-es@^4.17.7": - version "4.17.7" - resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.7.tgz#22edcae9f44aff08546e71db8925f05b33c7cc40" - integrity sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*": - version "4.14.191" - resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa" - integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ== - -"@types/lodash@^4.14.180": - version "4.14.180" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.180.tgz#4ab7c9ddfc92ec4a887886483bc14c79fb380670" - integrity sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g== - -"@types/minimatch@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== - -"@types/node@*": - version "17.0.23" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" - integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== - -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - -"@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== - -"@types/prop-types@^15.7.5": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== - -"@types/react-dom@^18.0.11": - version "18.0.11" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.11.tgz#321351c1459bc9ca3d216aefc8a167beec334e33" - integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw== - dependencies: - "@types/react" "*" - -"@types/react-is@^16.7.1 || ^17.0.0": - version "17.0.3" - resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a" - integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw== - dependencies: - "@types/react" "*" - -"@types/react-transition-group@^4.4.5": - version "4.4.5" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" - integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== - dependencies: - "@types/react" "*" - -"@types/react@*": - version "17.0.43" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55" - integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== - -"@virtuoso.dev/react-urx@^0.2.12": - version "0.2.13" - resolved "https://registry.yarnpkg.com/@virtuoso.dev/react-urx/-/react-urx-0.2.13.tgz#e2cfc42d259d2a002695e7517d34cb97b64ee9c4" - integrity sha512-MY0ugBDjFb5Xt8v2HY7MKcRGqw/3gTpMlLXId2EwQvYJoC8sP7nnXjAxcBtTB50KTZhO0SbzsFimaZ7pSdApwA== - dependencies: - "@virtuoso.dev/urx" "^0.2.13" - -"@virtuoso.dev/urx@^0.2.12", "@virtuoso.dev/urx@^0.2.13": - version "0.2.13" - resolved "https://registry.yarnpkg.com/@virtuoso.dev/urx/-/urx-0.2.13.tgz#a65e7e8d923cb03397ac876bfdd45c7f71c8edf1" - integrity sha512-iirJNv92A1ZWxoOHHDYW/1KPoi83939o83iUBQHIim0i3tMeSKEh+bxhJdTHQ86Mr4uXx9xGUTq69cp52ZP8Xw== - -"@vitejs/plugin-react@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-2.0.1.tgz#3197c01d8e4a4eb9fed829c7888c467a43aadd4e" - integrity sha512-uINzNHmjrbunlFtyVkST6lY1ewSfz/XwLufG0PIqvLGnpk2nOIOa/1CACTDNcKi1/RwaCzJLmsXwm1NsUVV/NA== - dependencies: - "@babel/core" "^7.18.10" - "@babel/plugin-transform-react-jsx" "^7.18.10" - "@babel/plugin-transform-react-jsx-development" "^7.18.6" - "@babel/plugin-transform-react-jsx-self" "^7.18.6" - "@babel/plugin-transform-react-jsx-source" "^7.18.6" - magic-string "^0.26.2" - react-refresh "^0.14.0" - -adm-zip@^0.5.9: - version "0.5.9" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.9.tgz#b33691028333821c0cf95c31374c5462f2905a83" - integrity sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -ahooks-v3-count@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz#ddeb392e009ad6e748905b3cbf63a9fd8262ca80" - integrity sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ== - -ahooks@^3.7.2: - version "3.7.2" - resolved "https://registry.npmmirror.com/ahooks/-/ahooks-3.7.2.tgz#0afa42625e77ae1cc4b60b19c45cf12a8cf29b56" - integrity sha512-nJPsQJcmJnGaNXiqgZdfO7UMs+o926LQg6VyDYt2vzKhXU8Ze/U87NsA/FeIvlIZB0rQr/j7uotFb1bGPp627A== - dependencies: - "@types/js-cookie" "^2.x.x" - ahooks-v3-count "^1.0.0" - dayjs "^1.9.1" - intersection-observer "^0.12.0" - js-cookie "^2.x.x" - lodash "^4.17.21" - resize-observer-polyfill "^1.5.1" - screenfull "^5.0.0" - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -array-differ@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" - integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -axios@^1.1.3: - version "1.1.3" - resolved "https://registry.npmmirror.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -babel-plugin-macros@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" - integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== - dependencies: - "@babel/runtime" "^7.12.5" - cosmiconfig "^7.0.0" - resolve "^1.19.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.20.2: - version "4.20.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" - integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== - dependencies: - caniuse-lite "^1.0.30001332" - electron-to-chromium "^1.4.118" - escalade "^3.1.1" - node-releases "^2.0.3" - picocolors "^1.0.0" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001332: - version "1.0.30001341" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001341.tgz#59590c8ffa8b5939cf4161f00827b8873ad72498" - integrity sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA== - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -"chokidar@>=3.0.0 <4.0.0": - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -clsx@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -convert-source-map@^1.5.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cross-env@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" - integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== - dependencies: - cross-spawn "^7.0.1" - -cross-spawn@^7.0.0, cross-spawn@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.0.11" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" - integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== - -csstype@^3.1.1: - version "3.1.1" - resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== - -data-uri-to-buffer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" - integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== - -dayjs@1.11.5, dayjs@^1.9.1: - version "1.11.5" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93" - integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA== - -debug@4, debug@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -deprecation@^2.0.0, deprecation@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" - integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== - -dom-helpers@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" - integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== - dependencies: - "@babel/runtime" "^7.8.7" - csstype "^3.0.2" - -electron-to-chromium@^1.4.118: - version "1.4.137" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz#186180a45617283f1c012284458510cd99d6787f" - integrity sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA== - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -entities@^4.3.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" - integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -esbuild-android-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz#20a7ae1416c8eaade917fb2453c1259302c637a5" - integrity sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA== - -esbuild-android-arm64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz#9cc0ec60581d6ad267568f29cf4895ffdd9f2f04" - integrity sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ== - -esbuild-darwin-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz#428e1730ea819d500808f220fbc5207aea6d4410" - integrity sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg== - -esbuild-darwin-arm64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz#b6dfc7799115a2917f35970bfbc93ae50256b337" - integrity sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA== - -esbuild-freebsd-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz#4e190d9c2d1e67164619ae30a438be87d5eedaf2" - integrity sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA== - -esbuild-freebsd-arm64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz#18a4c0344ee23bd5a6d06d18c76e2fd6d3f91635" - integrity sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA== - -esbuild-linux-32@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz#9a329731ee079b12262b793fb84eea762e82e0ce" - integrity sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg== - -esbuild-linux-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz#532738075397b994467b514e524aeb520c191b6c" - integrity sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw== - -esbuild-linux-arm64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz#5372e7993ac2da8f06b2ba313710d722b7a86e5d" - integrity sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug== - -esbuild-linux-arm@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz#e734aaf259a2e3d109d4886c9e81ec0f2fd9a9cc" - integrity sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA== - -esbuild-linux-mips64le@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz#c0487c14a9371a84eb08fab0e1d7b045a77105eb" - integrity sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ== - -esbuild-linux-ppc64le@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz#af048ad94eed0ce32f6d5a873f7abe9115012507" - integrity sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w== - -esbuild-linux-riscv64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz#423ed4e5927bd77f842bd566972178f424d455e6" - integrity sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg== - -esbuild-linux-s390x@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz#21d21eaa962a183bfb76312e5a01cc5ae48ce8eb" - integrity sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ== - -esbuild-netbsd-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz#ae75682f60d08560b1fe9482bfe0173e5110b998" - integrity sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg== - -esbuild-openbsd-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz#79591a90aa3b03e4863f93beec0d2bab2853d0a8" - integrity sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ== - -esbuild-sunos-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz#fd528aa5da5374b7e1e93d36ef9b07c3dfed2971" - integrity sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw== - -esbuild-windows-32@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz#0e92b66ecdf5435a76813c4bc5ccda0696f4efc3" - integrity sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ== - -esbuild-windows-64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz#0fc761d785414284fc408e7914226d33f82420d0" - integrity sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw== - -esbuild-windows-arm64@0.15.18: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz#5b5bdc56d341d0922ee94965c89ee120a6a86eb7" - integrity sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ== - -esbuild@^0.15.9: - version "0.15.18" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.18.tgz#ea894adaf3fbc036d32320a00d4d6e4978a2f36d" - integrity sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q== - optionalDependencies: - "@esbuild/android-arm" "0.15.18" - "@esbuild/linux-loong64" "0.15.18" - esbuild-android-64 "0.15.18" - esbuild-android-arm64 "0.15.18" - esbuild-darwin-64 "0.15.18" - esbuild-darwin-arm64 "0.15.18" - esbuild-freebsd-64 "0.15.18" - esbuild-freebsd-arm64 "0.15.18" - esbuild-linux-32 "0.15.18" - esbuild-linux-64 "0.15.18" - esbuild-linux-arm "0.15.18" - esbuild-linux-arm64 "0.15.18" - esbuild-linux-mips64le "0.15.18" - esbuild-linux-ppc64le "0.15.18" - esbuild-linux-riscv64 "0.15.18" - esbuild-linux-s390x "0.15.18" - esbuild-netbsd-64 "0.15.18" - esbuild-openbsd-64 "0.15.18" - esbuild-sunos-64 "0.15.18" - esbuild-windows-32 "0.15.18" - esbuild-windows-64 "0.15.18" - esbuild-windows-arm64 "0.15.18" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -estree-walker@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -execa@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" - integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" - -fetch-blob@^3.1.2, fetch-blob@^3.1.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.5.tgz#0077bf5f3fcdbd9d75a0b5362f77dbb743489863" - integrity sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg== - dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-root@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -formdata-polyfill@^4.0.10: - version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" - integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== - dependencies: - fetch-blob "^3.1.2" - -fs-extra@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" - integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-stream@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -hamt_plus@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz#e21c252968c7e33b20f6a1b094cd85787a265601" - integrity sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE= - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hoist-non-react-statics@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -html-parse-stringify@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" - integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== - dependencies: - void-elements "3.1.0" - -https-proxy-agent@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -human-signals@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" - integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== - -husky@^7.0.0: - version "7.0.4" - resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" - integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== - -i18next@^22.0.4: - version "22.0.4" - resolved "https://registry.npmmirror.com/i18next/-/i18next-22.0.4.tgz#77d8871687b0ab072b38991e3887187823667e30" - integrity sha512-TOp7BTMKDbUkOHMzDlVsCYWpyaFkKakrrO3HNXfSz4EeJaWwnBScRmgQSTaWHScXVHBUFXTvShrCW8uryBYFcg== - dependencies: - "@babel/runtime" "^7.17.2" - -ignore@^5.1.4: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -immutable@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" - integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -intersection-observer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.0.tgz#6c84628f67ce8698e5f9ccf857d97718745837aa" - integrity sha512-2Vkz8z46Dv401zTWudDGwO7KiGHNDkMv417T5ItcNYfmvHR/1qCTVBO9vwH8zZmQ0WkA/1ARwpysR9bsnop4NQ== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -js-cookie@^2.x.x: - version "2.2.1" - resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" - integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash-es@^4.17.21: - version "4.17.21" - resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" - integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -magic-string@^0.26.2: - version "0.26.3" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.26.3.tgz#25840b875140f7b4785ab06bddc384270b7dd452" - integrity sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg== - dependencies: - sourcemap-codec "^1.4.8" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -monaco-editor@^0.34.1: - version "0.34.1" - resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.34.1.tgz#1b75c4ad6bc4c1f9da656d740d98e0b850a22f87" - integrity sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ== - -mri@^1.1.5: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" - integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multimatch@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" - integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== - dependencies: - "@types/minimatch" "^3.0.3" - array-differ "^3.0.0" - array-union "^2.1.0" - arrify "^2.0.1" - minimatch "^3.0.4" - -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== - -node-domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" - integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== - -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.6.tgz#6d4627181697a9d9674aae0d61548e0d629b31b9" - integrity sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw== - dependencies: - data-uri-to-buffer "^4.0.0" - fetch-blob "^3.1.4" - formdata-polyfill "^4.0.10" - -node-releases@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476" - integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -postcss@^8.4.18: - version "8.4.21" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" - integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== - dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prettier@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== - -pretty-quick@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.3.tgz#15281108c0ddf446675157ca40240099157b638e" - integrity sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA== - dependencies: - chalk "^3.0.0" - execa "^4.0.0" - find-up "^4.1.0" - ignore "^5.1.4" - mri "^1.1.5" - multimatch "^4.0.0" - -prop-types@^15.6.2, prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-error-boundary@^3.1.4: - version "3.1.4" - resolved "https://registry.npmmirror.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0" - integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA== - dependencies: - "@babel/runtime" "^7.12.5" - -react-hook-form@^7.39.5: - version "7.39.5" - resolved "https://registry.npmmirror.com/react-hook-form/-/react-hook-form-7.39.5.tgz#a4272b60288ef5e1bb42bbb6ba3b36d243ab2879" - integrity sha512-OE0HKyz5IPc6svN2wd+e+evidZrw4O4WZWAWYzQVZuHi+hYnHFSLnxOq0ddjbdmaLIsLHut/ab7j72y2QT3+KA== - -react-i18next@^12.0.0: - version "12.0.0" - resolved "https://registry.npmmirror.com/react-i18next/-/react-i18next-12.0.0.tgz#634015a2c035779c5736ae4c2e5c34c1659753b1" - integrity sha512-/O7N6aIEAl1FaWZBNvhdIo9itvF/MO/nRKr9pYqRc9LhuC1u21SlfwpiYQqvaeNSEW3g3qUXLREOWMt+gxrWbg== - dependencies: - "@babel/runtime" "^7.14.5" - html-parse-stringify "^3.0.1" - -react-is@^16.13.1, react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -react-refresh@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" - integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== - -react-router-dom@^6.4.3: - version "6.4.3" - resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.4.3.tgz#70093b5f65f85f1df9e5d4182eb7ff3a08299275" - integrity sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ== - dependencies: - "@remix-run/router" "1.0.3" - react-router "6.4.3" - -react-router@6.4.3: - version "6.4.3" - resolved "https://registry.npmmirror.com/react-router/-/react-router-6.4.3.tgz#9ed3ee4d6e95889e9b075a5d63e29acc7def0d49" - integrity sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA== - dependencies: - "@remix-run/router" "1.0.3" - -react-transition-group@^4.4.5: - version "4.4.5" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" - integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== - dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" - loose-envify "^1.4.0" - prop-types "^15.6.2" - -react-virtuoso@^3.1.3: - version "3.1.3" - resolved "https://registry.npmmirror.com/react-virtuoso/-/react-virtuoso-3.1.3.tgz#db811ff6fdd4749cfe9348f6d0b1333a348e65c4" - integrity sha512-sc4WICEZkyT+XdVc7gA/61UT43ZnMSX0ugh+xBG2cX+EDWs31wP1dSKQ2HSQ0YFLhZXRJ+Jqndqa8MTu4NE4CQ== - dependencies: - "@virtuoso.dev/react-urx" "^0.2.12" - "@virtuoso.dev/urx" "^0.2.12" - -react@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -recoil@^0.7.6: - version "0.7.6" - resolved "https://registry.npmmirror.com/recoil/-/recoil-0.7.6.tgz#75297ecd70bbfeeb72e861aa6141a86bb6dfcd5e" - integrity sha512-hsBEw7jFdpBCY/tu2GweiyaqHKxVj6EqF2/SfrglbKvJHhpN57SANWvPW+gE90i3Awi+A5gssOd3u+vWlT+g7g== - dependencies: - hamt_plus "1.0.2" - -regenerator-runtime@^0.13.10: - version "0.13.10" - resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" - integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== - -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -reselect@^4.1.6: - version "4.1.6" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.6.tgz#19ca2d3d0b35373a74dc1c98692cdaffb6602656" - integrity sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ== - -resize-observer-polyfill@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" - integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@^1.19.0, resolve@^1.22.1: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -rollup@^2.79.1: - version "2.79.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== - optionalDependencies: - fsevents "~2.3.2" - -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -sass@^1.54.0: - version "1.54.8" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.54.8.tgz#4adef0dd86ea2b1e4074f551eeda4fc5f812a996" - integrity sha512-ib4JhLRRgbg6QVy6bsv5uJxnJMTS2soVcCp9Y88Extyy13A8vV0G1fAwujOzmNkFQbR3LvedudAMbtuNRPbQww== - dependencies: - chokidar ">=3.0.0 <4.0.0" - immutable "^4.0.0" - source-map-js ">=0.6.2 <2.0.0" - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -screenfull@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" - integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== - -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -snarkdown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/snarkdown/-/snarkdown-2.0.0.tgz#b1feb4db91b9f94a8ebbd7a50f3e99aee18b1e03" - integrity sha512-MgL/7k/AZdXCTJiNgrO7chgDqaB9FGM/1Tvlcenenb7div6obaDATzs16JhFyHHBGodHT3B7RzRc5qk8pFhg3A== - -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -sourcemap-codec@^1.4.8: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -stylis@4.0.13: - version "4.0.13" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" - integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== - -stylis@4.1.3: - version "4.1.3" - resolved "https://registry.npmmirror.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" - integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -svg-parser@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== - -swr@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8" - integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -tunnel@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" - integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== - -typescript@^4.7.4: - version "4.7.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" - integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== - -universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -vite-plugin-monaco-editor@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz#a6238c2e13d5e98dd54a1bc51f6f189325219de3" - integrity sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww== - -vite-plugin-svgr@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-2.2.1.tgz#6e1132a3b66f71e1d69e8c5fe989393260184ac3" - integrity sha512-+EqwahbwjETJH/ssA/66dNYyKN1cO0AStq96MuXmq5maU7AePBMf2lDKfQna49tJZAjtRz+R899BWCsUUP45Fg== - dependencies: - "@rollup/pluginutils" "^4.2.1" - "@svgr/core" "^6.3.1" - -vite@^3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/vite/-/vite-3.2.5.tgz#dee5678172a8a0ab3e547ad4148c3d547f90e86a" - integrity sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ== - dependencies: - esbuild "^0.15.9" - postcss "^8.4.18" - resolve "^1.22.1" - rollup "^2.79.1" - optionalDependencies: - fsevents "~2.3.2" - -void-elements@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" - integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= - -web-streams-polyfill@^3.0.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" - integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -yaml@^1.10.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==